Vert.x提供了一个可扩展的服务发现机制。您可以使用相同的API来应用客户端服务发现或服务器端服务发现。Vert.x服务发现可以从许多类型的服务发现基础设施(如Consul或Kubernetes)导入或导出服务(图4-3)。它还可以在没有任何专门的服务发现基础设施的情况下使用。在这种情况下,它在Vert.x 集群上使用了一个共享的分布式的数据结构。
图4 - 3:从/向其他服务发现机制导入和导出服务。
您可以通过types来检索服务,以获得一个配置好的针对目标服务调用的客户端。服务的类型可以是HTTP端点、事件总线地址、数据源等等。例如,如果您想检索我们在前一章中实现的名为hello的HTTP端点,您将编写以下代码:
// We create an instance of service discovery
ServiceDiscovery discovery = ServiceDiscovery.create(vertx);
// As we know we want to use an HTTP microservice, we can
// retrieve a WebClient already configured for the service
HttpEndpoint
.rxGetWebClient(discovery,
// This method is a filter to select the service
rec -> rec.getName().endsWith("hello")
)
.flatMap(client ->
// We have retrieved the WebClient, use it to call
// the service
client.get("/").as(BodyCodec.string()).rxSend())
.subscribe(response -> System.out.println(response.body()));
检索到的WebClient被配置了服务位置,这意味着您可以立即使用它来调用服务。如果您的环境使用客户端服务发现,则配置的URL针对服务的特定实例。如果您正在使用服务器端服务发现,则该客户端使用一个虚拟URL。
根据您的运行时基础设施,您可能需要注册您的服务。但是,当使用服务器端服务发现时,您通常不需要这样做,因为您在部署服务时声明了服务。否则,您需要显式地发布服务。要发布服务,您需要创建包含服务名称、位置和元数据的Record:
// We create the service discovery object
ServiceDiscovery discovery = ServiceDiscovery.create(vertx);
vertx.createHttpServer()
.requestHandler(req -> req.response().end("hello"))
.rxListen(8083)
.flatMap(
// Once the HTTP server is started (we are ready to serve)
// we publish the service.
server -> {
// We create a record describing the service and its
// location (for HTTP endpoint)
Record record = HttpEndpoint.createRecord(
"hello", // the name of the service
"localhost", // the host
server.actualPort(), // the port
"/" // the root of the endpoint
);
// We publish the service
return discovery.rxPublish(record);
}
)
.subscribe(rec -> System.out.println("Service published"));
服务发现是微服务基础结构中的关键组件。它支持动态、位置透明性和移动性。在处理少量服务时,服务发现可能看起来很麻烦,但是当系统增长时,它就是必须的了。Vert.x服务发现为您提供了一个独特的API,而不管您使用的基础设施和服务发现类型。然而,当系统增长时,也会有另一个可变因素呈指数级增长-----failures。