什么是弹性呢?在当前的代码中,如果hello microservice失败了,我们将会失败并执行此如下的代码:
t -> {
t.printStackTrace();
req.response().setStatusCode(500).end(t.getMessage());
}
即使用户得到一个错误消息,我们也不会崩溃,我们不会限制我们的可伸缩性,我们仍然可以处理请求。但是,为了提高用户体验,我们应该总是及时地给用户回复,即使我们没有收到来自服务的回复。为了实现这个逻辑,我们可以通过超时来增强代码。
为了说明这一点,让我们修改Hello microservice来注入失败和错误行为。此代码位于代码存储库的 microservices/hello-microservice-faulty 目录中。
这个新的开始方法随机选择三种策略中的一种:(1)显式的回复失败,(2)忘记回复(导致客户端超时),或者(3)发送正确的结果。
public class HelloMicroservice extends AbstractVerticle {
@Override
public void start() {
Random random = new Random();
vertx.eventBus().<String>consumer("hello", message -> {
int chaos = random.nextInt(10);
JsonObject json = new JsonObject()
.put("served-by", this.toString());
if (chaos < 6) {
// Normal behavior
if (message.body().isEmpty()) {
message.reply(json.put("message", "hello"));
} else {
message.reply(json.put("message", "hello " + message.body()));
}
} else if (chaos < 9) {
System.out.println("Returning a failure");
// Reply with a failure
message.fail(500, "message processing failure");
} else {
System.out.println("Not replying");
// Just do not reply, leading to a timeout on the consumer side.
}
});
}
}
重新打包并重新启动两个Hello microservice实例。
有了这种故障注入,我们需要提高消费者的容错性。实际上,消费者可能会得到一个超时或收到显式的失败。在hello consumer microservice中,改变我们调用hello服务的方式:
EventBus bus = vertx.eventBus();
Single<JsonObject> obs1 = bus
.<JsonObject>rxSend("hello", "Luke")
.subscribeOn(RxHelper.scheduler(vertx))
.timeout(3, TimeUnit.SECONDS)
.retry()
.map(Message::body);
Single<JsonObject> obs2 = bus.
<JsonObject>rxSend("hello", "Leia")
.subscribeOn(RxHelper.scheduler(vertx))
.timeout(3, TimeUnit.SECONDS)
.retry()
.map(Message::body);
此代码位于Github的microservices/hello- customer -microservice- microservice-timeout目录中。如果在给定的时间内没有收到响应,则timeout方法会发出失败。如果以超时或显式失败的形式中失败,则重新尝试通过retry检索该值。subscribeOn方法表明完成调用的线程。我们使用的是Vert.x 的事件回环来调用我们的回调函数。如果没有这个,方法将由默认的RxJava线程池中的一个线程来执行,从而破坏了这个Vert.x的线程模型。RXHelper类由Vert.x提供。盲目地重试服务调用并不是一个机智的容错策略。甚至是有害的。下一章详细介绍了不同的方法。
现在可以重新刷新页面。你总会得到一个结果,即使有失败或超时。请记住,在调用服务时线程没有被阻塞,因此您可以始终接受新的请求并及时响应它们。但是,这个超时重试常常会造成更多的危害,我们将在下一章中看到。