当前位置:首页 > Vert.X学习笔记
});
3. Vert.x中EventBus中的使用
event bus 是vert.x的神经系统。
每一个vert.x的实例都有一个单一的event bus 实例。它是使用vertx.eventBus()方法获得的。
event bus 允许程序中的不同语言编写的模块进行通信,不论他们是相同的vert.x实例,还是不同的vert.x实例。 它甚至可以桥接浏览器中运行的Javascript通信。
event bus可以在分布式系统中的多个服务器节点之间进行点对点通信和多个浏览器。 event bus支持发布/订阅模式,点对点模式,和请求/响应模式。
event bus的API是非常容易的,它主要包括注册消息处理事件,取消处理事件,发送和发布消息。 EVENT BUS 的API让我们跳进event bus的API。 获得event bus 的对象
你可以通过如下代码获得event bus的单一对象: EventBus eb = vertx.eventBus(); 注册处理事件
使用下面这个简单方法注册一个消费处理程序: EventBus eb = vertx.eventBus();
eb.consumer(―news.uk.sport‖, message -> {
System.out.println(―I have received a message: ‖ + message.body()); });
当一个消息到达你的处理事件是。你的事件将被激活,并处理这个消息。
consumer()方法返回一个MessageConsumer的对象实例。这个对象随后用于注销处理程序,或者用处理程序作为流。 然而您也可以使用consumer()返回MessageConsumer没有处理程序,然后单独设置处理程序。例如: EventBus eb = vertx.eventBus();
MessageConsumer
System.out.println(―I have received a message: ‖ + message.body()); });
当在集群事件总线上注册一个处理程序时,它可以花一些时间登记到集群的所有节点上。
如果你希望在注册完成时得到通知的话,你可以在MessageConsumer上注册一个注册完成的处理程序: consumer.completionHandler(res -> { if (res.succeeded()) {
System.out.println(―The handler registration has reached all nodes‖); } else {
System.out.println(―Registration failed!‖); } });
注销处理事件
去除处理事件,叫做注销。
如果你是集群事件总线, 如果你想当这个过程完成时通知注销,你可以使用下面的方法: consumer.unregister(res -> { if (res.succeeded()) {
System.out.println(―The handler un-registration has reached all nodes‖); } else {
System.out.println(―Un-registration failed!‖); } }); 发布消息
发布消息非常简单,只需要把它发布到指定地址即可:
eventBus.publish(―news.uk.sport‖, ―Yay! Someone kicked a ball‖); 这一消息将被交付所有订阅news.uk.sport地址处理。 发送消息
发送消息将导致只有一个注册地址的处理程序接收到消息(多个注册地址也只有一个能收到)。这就是点对点模式,选择处理程序的方法采用非严格循环方式。 你可用用send()方法发送一条消息。
eventBus.send(―news.uk.sport‖, ―Yay! Someone kicked a ball‖);
未解决的指令包括在
有时你发送消息后希望得到接收到消息的人的回复。这就需要你使用请求-响应模式。 要做到这一点,在消息发送的时候,你可以指定一个回复事件。 当你接收到消息的时候,你可以通过调用reply()方法来应答。
当这一切发生的时候它会导致一个答复发送回发送方,发送方收到应答消息再做处理。 接收方:
MessageConsumer
System.out.println(“I have received a message: ” + message.body()); message.reply(“how interesting!”); }); 发送方:
eventBus.send(“news.uk.sport”, “Yay! Someone kicked a ball across a patch of grass”, ar -> {
if (ar.succeeded()) {
System.out.println(\reply: \+ ar.result().body()); } });
对应答也可以做应答。这样你就可以在两个不同的程序中创建一个包含多个回合的对话。 发送超时
当你发送消息时和指定应答事件时你可以通过DeliveryOptions指定超时时间。 如果应答事件不少于超时时间,这个应答事件将失败。 默认的超时时间是30S。 发送失败
消息发送失败的其他原因,包括: 没有可用的事件去发送消息
接收者已经明确使用失败:失败的消息 在所有情况下,应答事件将回复特定的失败。
未解决的指令包含在
event bus 不仅仅存在于一个单一的Vert.x实例中,在一个集群中不同的Vert.x实例也可以形成一个单一的,分布的事件总线。 集群编程
如果你创建一个Vert.x实例用于集群编程,你需要的得到一个关于集群事件总线配置 VertxOptions options = new VertxOptions(); Vertx.clusteredVertx(options, res -> {
if (res.succeeded()) {
Vertx vertx = res.result();
EventBus eventBus = vertx.eventBus();
System.out.println(“We now have a clustered event bus: ” + eventBus); } else {
System.out.println(“Failed: ” + res.cause()); } });
你应该确保在你的类路径中实现了一个ClusterManager,例如默认的:HazelcastClusterManager。 使用命令集群
你可以使用命令行运行集群:vertx run my-verticle.js -cluster Automatic clean-up in verticles
4.Vert.x的微服务verticle
而Vert.x的verticle本身就是很好的一种服务定义,你可以把verticle看成一个service,也可以把verticle看成一个actor。这样你的视角会切到Actor模型里。本文我们将讨论如何基于Vert.x实现远程调用。 Vert.x EventBus两宗罪
但Vert.x的EventBus有两点不太好的地方,导致不能原生支持面向接口的服务调用。
EventBus是Vert.x的核心,因为它的存在可以使得系统模块化解耦成为可能,同时也可以将业务水平扩展。我们只需要定义EventBus地址然后传入Json对象就可以,所有的事情都很流畅。但是这里有一点不太好的地方,默认传输协议走Json,而Json本身不太好定义数据类型。
如果了解Vert.x历史的同学肯定知道为什么EventBus一定要使用Json作为主要的传输对象——为了兼容其他JVM上的弱语言。可是现实情况中80%的项目都是基于Java跑的,根本就没有考虑去兼容其他JVM上的语言。这就造成了一种尴尬,大家都传Json对象,然后在Handler里先做一次转换,将Json对象转换成POJO,之后再做业务上的逻辑。这里明显在Handler里做了很多与业务无关的事情,服务定位与对象转换,这些本质上应该是框架层面去解决的。
不能隐试的将Json对象转成POJO这是EventBus的一宗罪。(Vert.x3可以直接接受POJO,但是针对一个address,只能接收一种POJO格式。)另外当我们使用EventBus的时候不能很方便的确定方法逻辑,简单的讲我只能EventBus。send()后面跟地址参数以及JSON对象,而这并不适合描述业务,这是EventBus的二宗罪。
举个例子,有一个业务逻辑,对用户的账户进行存款与取款这两个操作,如果用Java接口来描述就很Easy。 Java代码
interface Account {
void saveMemory(int total); void withdrawMemory(int total); }
如果换成EventBus你会发现没办法定义行为的名称(Java的方法),只能通过eb.send(\, json)来调用目标接口。这里的json也许得包含method的描述。这样会显得很啰嗦,关键是对IDE不友好,重构起来不方便,严重影响团队开发流畅度。
5. Vertx-RPC介绍
介于上面的原因,我们开发了一个简单的RPC框架,它简单的封装了EventBus,使之可以包装成Java的接口。这样客户端与服务端之间调用就像本地接口一样。 vertx-rpc其实做的非常简单,他只依赖protostuff,作为数据传输的协议,当然也可以使用JSON协议。接着只需要定义好接口,然后在服务端实现接口,而客户端只依赖接口,单独将项目打包成jar暴露给出来就可以使用了。 我们继续上面的例子,根据接口我们会把项目分成两个Maven模块。SPI,SPI-impl,在parent的pom.xml定义好即可。下面我们先在impl的项目里启动好service并通过EventBus暴露服务。 Java代码
Vertx vertx = Vertx.vertx(); String address = \
RPCServerOptions rpcServerOptions = new RPCServerOptions(vertx).setBusAddress(address).addService(new MyServiceImpl()); new VertxRPCServer(rpcServerOptions);
以上四行代码就已经成功的定义了服务,是这里要注意new MyServiceimpl()必须实现spi项目里的MyService接口。下面我们来看调用方,怎么调用服务。 Java代码
Vertx vertx = Vertx.vertx(); String address = \
RPCClientOptions
RPCClientOptions
共分享92篇相关文档