事件总线 (Event Bus)

使用 Vert.x Service Proxy 构建事件总线 RPC 服务

本文档将向你展示如何使用 Vert.x Service Proxy 模块快速搭建基于 Event Bus 的 RPC 微服务。 你将深刻体会到:通过简单的 Java 接口声明,即可在事件总线上轻松定义与消费强类型异步服务。

你将构建什么

你将构建一个 Vert.x 应用程序,发布并调用 BarmanService —— 这是一个在 Event Bus 上运行、负责调制啤酒并管理顾客账单的远程服务。 我们将部署两个 Verticle: * BarmanVerticle:负责提供并暴露该服务的服务端; * DrunkVerticle:负责消费调用该服务的客户端。

前置要求

  • 文本编辑器或 IDE

  • Java 11 或更高版本

  • Maven

创建工程项目

这是你应该使用的 pom.xml 文件内容:

必须引入带有 processor 分类器的 vertx-codegen 以及 vertx-service-proxy。

声明 BarmanService 接口契约

首先,我们定义服务契约接口。底层代码生成器会自动分析该接口,生成 Event Bus 消息分发处理器以及客户端代理代理类(Proxy):

package io.vertx.howtos.ebservice.beers;

import io.vertx.codegen.annotations.ProxyGen;
import io.vertx.codegen.annotations.VertxGen;
import io.vertx.core.Future;
import io.vertx.core.Vertx;

@VertxGen
@ProxyGen (1)
public interface BarmanService {

  Future<Beer> giveMeARandomBeer(String customerName); (2)

  Future<Integer> getMyBill(String customerName); (3)

  void payMyBill(String customerName); (4)

  static BarmanService createProxy(Vertx vertx, String address) { (5)
    return new BarmanServiceVertxEBProxy(vertx, address);
  }

}

服务接口的必须遵循以下规则: . 添加 @ProxyGen 注解告知代码生成器; . 方法异步回调必须以 Handler<AsyncResult<T>> 或返回 Future<T> 作为结尾。

服务端与客户端 Verticle 实现

服务端实现

BarmanVerticle 创建服务实现类实例,并使用自动生成的 BarmanServiceVertxEBProxy 将其绑定到 Event Bus 地址上:

package io.vertx.howtos.ebservice;

import io.vertx.core.Future;
import io.vertx.core.VerticleBase;
import io.vertx.core.eventbus.MessageConsumer;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.client.WebClient;
import io.vertx.howtos.ebservice.beers.BarmanService;
import io.vertx.howtos.ebservice.beers.impl.BarmanServiceImpl;
import io.vertx.serviceproxy.ServiceBinder;

public class BarmanVerticle extends VerticleBase {

  @Override
  public Future<?> start() {
    BarmanService service = new BarmanServiceImpl(WebClient.create(vertx)); (1)

    MessageConsumer<JsonObject> consumer = new ServiceBinder(vertx) (2)
      .setAddress("beers.services.myapplication") (3)
      .register(BarmanService.class, service);(4)

    return consumer.completion();
  }
}

客户端消费实现

DrunkVerticle 直接使用自动生成的工厂方法获取代理对象,像调用本地普通 Java 方法一样发起跨组件异步通信:

package io.vertx.howtos.ebservice;

import io.vertx.core.Future;
import io.vertx.core.VerticleBase;
import io.vertx.howtos.ebservice.beers.BarmanService;

public class DrunkVerticle extends VerticleBase {

  @Override
  public Future<?> start() {
    BarmanService barmanService = BarmanService.createProxy(vertx, "beers.services.myapplication"); (1)
    return barmanService.giveMeARandomBeer("homer") (2)
      .onSuccess(beer1 -> System.out.println("My first beer is a " + beer1.getName() + " and it costs " + beer1.getPrice() + "€"))  (3)
      .compose(v -> vertx.timer(1500))
      .compose(v -> barmanService.giveMeARandomBeer("homer")) (4)
      .onSuccess(beer2 -> System.out.println("My second beer is a " + beer2.getName() + " and it costs " + beer2.getPrice() + "€")) (5)
      .compose(v -> barmanService.getMyBill("homer")) (6)
      .onSuccess(bill -> {
        System.out.println("My bill with the bar is " + bill + "€");
        barmanService.payMyBill("homer"); (7)
      });
  }
}

运行应用程序

通过 Maven 编译运行:

mvn compile exec:java

控制台将输出酒保服务收到订单、调制啤酒以及酒客结账的完整 Event Bus 交互日志。

总结

本文档展示了:

  • 使用 @ProxyGen 声明强类型异步服务契约;

  • 利用代码生成技术透明屏蔽 Event Bus 消息序列化与地址路由细节;

  • 构建松耦合且类型安全的微服务通信架构。