首页 > 解决方案 > Spring Cloud Consul 客户端不会忽略关键服务

问题描述

我已经实现了一个基于 Spring Cloud 的应用程序,它具有以下主要架构。多个实例的GatewayService委托HelloService。我使用Consul进行服务发现。GatewayService是通过以下方式实现的:

@EnableDiscoveryClient
@SpringBootApplication
public class GatewayApplication {

  public static void main(String[] args) {
    SpringApplication.run(ApiGatewayApplication.class, args);
  }

  @Bean
  @LoadBalanced
  public WebClient.Builder loadBalancedWebClientBuilder() {
    return WebClient.builder();
  }

  @RestController
  static class GateWayController {

    private final WebClient.Builder webClientBuilder;

    @Data
    @NoArgsConstructor
    private static class Response {
      private String message;
      private String appName;
      private int port;
    }

    @Autowired
    public GateWayController(WebClient.Builder webClientBuilder) {
      this.webClientBuilder = webClientBuilder;
    }

    @GetMapping("/lbhello")
    public Mono<Response> hello() {
      return webClientBuilder.build()
                             .get()
                             .uri("lb://hello-service/hello")
                             .retrieve()
                             .bodyToMono(Response.class);
    }
  }
}

spring-cloud-starter-consul-discoveryspring-cloud-starter-loadbalancer作为依赖项包含在pom.xml. 在application.yaml我只设置application.name和禁用Ribbon,以便使用Spring Cloud Loadbalancer。当我启动GatewayService和两个实例时,HelloService一切都按预期工作。对端点的服务调用lbhello交替委托给两个HelloService实例。

当一个实例HelloService停止时,Consul检测到该实例缺少一个将其标记为关键的实例。因此,我希望负载均衡器至少在一段时间后停止将请求转发到不存在的服务。但这永远不会发生。每隔一个服务调用就会委托给这个服务实例,因此会失败。当使用Eureka作为发现服务时,注册表会被调整,只有剩余HelloService的被考虑用于服务调用。

这是Consul的预期行为吗?如果答案是肯定的,是否有 Spring Cloud 设置来适应这种行为?

标签: javaspring-bootspring-cloudspring-cloud-consul

解决方案


Spring CloudConsulDiscoveryClient默认加载所有服务实例,无论它们的健康状态如何。可以通过以下配置设置更改此行为:

spring.cloud.consul.discovery.query-passing = true

使用此设置,请求不会在延迟一段时间后委托给非健康实例。


推荐阅读