什么是弹性呢?在当前的代码中,如果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提供。盲目地重试服务调用并不是一个机智的容错策略。甚至是有害的。下一章详细介绍了不同的方法。

现在可以重新刷新页面。你总会得到一个结果,即使有失败或超时。请记住,在调用服务时线程没有被阻塞,因此您可以始终接受新的请求并及时响应它们。但是,这个超时重试常常会造成更多的危害,我们将在下一章中看到。

results matching ""

    No results matching ""