从单个服务多次调用多个微服务的最佳方法或设计模式是什么?

时间:2018-08-21 10:24:54

标签: java spring-mvc spring-boot microservices

微服务A依赖于微服务B&C。当客户端在服务A上调用某个终结点时,这将导致从A到服务B&C的多个HTTP请求,以获取相关的详细信息。能同时处理这种情况的最佳,性能有效的设计模式或方法是什么?

注意:在这种情况下,我们不使用API​​网关。

1 个答案:

答案 0 :(得分:1)

根据您的问题,我假设没有能力利用event-based/reactive approach,并且已经在考虑了here的情况下做出了一些折衷的架构决定(请注意,在本资源中,以下提出的方法被称为“混合”)。

编排

在这些条件下,您要寻找的模式称为Orchestration。请查看this great answer,以获取更广泛的概述。

快速回顾一下,您可以使用Spring Integration之类的东西来实现以下要点:

  • 在处理对A的请求时,尽可能同时执行对B&C的调用,以实现A最快的响应时间
  • 将并发调用的结果累积,转换和聚合为完整的响应实体
  • 利用线程池将并发运行的请求限制为B和C,以防止级联故障的放大
  • 快速失败:如果某些请求失败(即,如果对B的调用未成功,则不要呼叫C)及早取消后续的呼叫
  • 切断:涉及最长的处理时间,您可以等待当前正在运行的对B&C的一堆呼叫完成,并在经过时由A做出错误响应

更新-依靠客户端Reactor pattern的实现

如果您可以使用Spring 5 / Spring Boot 2.x,还可以使用基于Spring WebFluxProject Reactor以响应方式对B&C进行呼叫,以达到上述目的。

从原理上讲,您可以执行以下操作:

@Service
public class MyService {

    private final WebClient webClient;

    ...

    public Mono<Details> someRestCall(String name) {
        return this.webClient.get().url("{name}/details", name)
                        .retrieve().bodyToMono(ResponseEntity.class);
    }

}

...


Mono<ResponseEntity> b1 = myService.someRestCall("serviceB");
Mono<ResponseEntity> c1 = myService.someRestCall("serviceC");
Mono<ResponseEntity> b2 = myService.someOtherRestCall("serviceB");

ResponseEntity response = Flux
       .parallel(NUM_CPUS)
       .merge(b1, c1, b2)
       .limitRequest(MAX_REQUESTS)
       .onErrorReturn(ERR_RESPONSE_ENTITY)
       .blockLast(CUTOFF_TIMEOUT);

(基于this example