使用Vert.x开发响应式微服务之服务发现和断路器

上一页

  之前展示了Vert.x HTTP客户端如何方便调用消费一个REST服务,客户端需要事先知道REST服务在哪个主机和端口,不幸的是,这个信息是不能在编码阶段事先知道,在部署运行应用程序的生命周期甚至可能会改变。Vert.x提供了服务发现机制,如下图,服务发现让服务提供者发布服务,让消费者找到其正确的服务,也提供桥接到其他服务发现机制如Consul Zookeeper或Kubernetes。

Vert.x服务发现

为了使用服务发现机制,增加下面依赖:

<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-service-discovery</artifactId>
</dependency>

发布一条记录到Vert.x服务发现中:

ServiceDiscovery discovery = ServiceDiscovery.create(vertx);
discovery.publish(HttpEndpoint.createRecord(
 "my-rest-api",
 "localhost", 8080,
 "/names"),
 ar -> {
 if (ar.succeeded()) {
 System.out.println("REST API published");
 } else {
 System.out.println("Unable to publish the REST API: " +
 ar.cause().getMessage());
 }
 });
 

Vert.x存储这些记录在分布式map共享给Vert.x集群所有成员,可以以配置替代map,使用Redis Zookeeper等。

另外一边,消费者需要获得这些记录信息,只要输入名称即可:

 public MyRestAPIClient(ServiceDiscovery discovery,
 Handler<asyncresult> completionHandler) {
 HttpEndpoint.getClient(discovery,
new JsonObject().put("name", "my-rest-api"),
ar -> {
 if (ar.failed()) {
 // No service
 completionHandler.handle(Future.failedFuture(
 "No matching services"));
 } else {
 client = ar.result();
 completionHandler.handle(Future.succeededFuture());
 }
 });

Vert.x让你很容易获得的定位服务的透明性,能够无论什么环境部署微服务。如果服务更改位置,或如果服务变得不可用,您的应用程序会自动作出反应,并顺利管理这些情况。

 

容错弹性

Vert。X配有一套弹性模式使你的应用程序准备好面对失败。首先,正如你在文章的不同代码段看到,失败是一流的公民,必须使用你的代码来对付他们。因此,故障失败不会被传播,使得每一个服务都有舱壁。此外,你可以设置一个超时timeout管理所有分布式交互。

下面是设置超时代码:



client.get("/names",
 response ->
 // Handler called when the response is received
 // We register a second handler to retrieve the body
 response.bodyHandler(body -> {
 // When the body is read, invoke the result handler
 handler.handle(Future.succeededFuture(body.toJsonArray()));
 }))
 // Set the timeout (time given in ms)
 .setTimeout(5000)
 .exceptionHandler(t -> {
 // If something bad happen, report the failure to the passed handler
 // Also called when the timeout is reached
 handler.handle(Future.failedFuture(t));
 })
 // Call end to send the request
 .end();

不要忘记一个超时并不意味着实际操作没有完成,只是它没有按时完成,或者其他的事情出错了。

断路器

还有另一种弹性模式应用很著名:断路器。这种模式的优点是包括一个“恢复”功能。基本上,一个断路器是一个状态自动机如下所示:

断路器监视一个操作,并跟踪执行此操作时遇到的故障数。当达到一个阈值时,断路器开关到打开状态。在这种状态下操作不再被调用了,但一个后备函数会立即执行。它会定期地,发送一个请求调用实际操作。根据执行的结果,如成功断路器可切换到关闭状态后,如果操作再次失败或回到打开状态。断路器模式的一个重要方面是给你的服务以时间来恢复,而不是积累越来越多的调用操作。

下面是Vert.x断路器实现:

 // Step 1 - create a circuit breaker
// Create an instance of circuit breaker.
circuitBreaker = CircuitBreaker.create("my-circuit-breaker", vertx,
 // Configure it
 new CircuitBreakerOptions()
 .setTimeout(5000) // Operation timeout
 .setFallbackOnFailure(true) // Call the fallback on failure
 .setResetTimeout(10000)); // Switch to the half-open state every 10s
//…
public void getNames(Handler<asyncresult> handler) {
 // Step 2 - Protect operation with it
 circuitBreaker.executeWithFallback(
 operation -> {
 client.get("/names",
 response ->
 response.bodyHandler(body -> {
 operation.complete(body.toJsonArray());
 }))
 .exceptionHandler(operation::fail)
 .end();
 },
 failure ->
 // Return an empty json array on failures
 new JsonArray()
 ).setHandler(handler); // Just call the handler.

微服务

Vert.x入门教程

Reactive响应式编程