【问题标题】:Update Service status when service instance is shutdown服务实例关闭时更新服务状态
【发布时间】:2021-07-28 06:35:23
【问题描述】:

我使用 Spring Cloud Feign 客户端实现了请求。我试过这个:

Feign 客户端:

@FeignClient(name = "mail-service")
public interface EmailClient {

    @RequestMapping(method = RequestMethod.POST, value = "/register")
    void setUserRegistration(RegisterUserDTO registerUserDTO);

    @RequestMapping(method = RequestMethod.POST, value = "/password_reset")
    void setUserPasswordReset(PasswordResetDTO passwordResetDTO);
}

Feign 配置:

@Configuration
public class LoadBalancerConfiguration {

    @Bean
    public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) {
        return ServiceInstanceListSupplier.builder()
                .withBlockingDiscoveryClient()
                .withSameInstancePreference()
                .withHealthChecks()
                .build(context);
    }
}

请求 DTO:

@Getter
@Setter
public class PasswordResetDTO {

    private int id;
}

控制器:

@Autowire
EmailClient emailClient;

@PostMapping("/dummy")
public ResponseEntity<?> test() {

    RegisterUserDTO obj = new RegisterUserDTO();
    obj.setId(12);

    emailClient.setUserRegistration(obj);

    return ok().build();
}

Feign 配置:

spring:
    cloud:
    loadbalancer:
        ribbon:
            enable: false
feign:
    client:
        config:
            default:
                connectTimeout: 5000
                readTimeout: 5000
                loggerLevel: basic
eureka:
    client:
        serviceUrl:
            defaultZone: ${EUREKA_URI:http://localhost:8761/eureka}
    instance:
        preferIpAddress: true

POM.xml

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-netflix-eureka-client</artifactId>
    </dependency>
    <dependency> 
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>

我启动了 3 个端点服务实例,这些服务以循环顺序从 Feign 客户端作为端点使用。到目前为止一切顺利,它按预期工作。但是,例如当我关闭第一个服务实例时,Feign 客户端不会收到此更改的通知,并继续向非活动服务发送请求。 你知道当端点服务关闭并且不在活动服务列表中时如何通知消费者服务吗?我想我需要配置一些健康检查?

你知道我该如何解决这个问题吗?

测试问题的源代码:https://github.com/rcbandit111/eureka-discovery-poc/tree/master

【问题讨论】:

  • 你有 Spring Cloud 负载均衡器的 Java 代码,然后有一个功能区依赖项。功能区应该被移除
  • 好的,完成。关于主要问题的任何建议?
  • 检查 eureka UI 以了解您的非活动实例处于什么状态?检查thisthis 它应该有助于理解尤里卡作品。
  • 您是否收到 500 错误代码作为响应?

标签: spring spring-boot spring-cloud spring-cloud-feign spring-cloud-loadbalancer


【解决方案1】:

功能区 - 负载均衡器

它为您提供开箱即用的循环负载平衡,但您可以实现自己的@RibbonClient(即使对于特定服务)并设计您的自定义负载平衡,例如基于 eureka 元数据。负载平衡发生在客户端。

Feign - Http 客户端

使用@FeignClient,您可以为您的其他服务(或基础架构之外的服务)快速开发客户端。它与功能区和尤里卡集成,因此您可以参考您的服务@FeignClient(yourServiceNameInEureka),您最终得到的是一个客户端,它使用您的首选逻辑在注册实例之间进行负载平衡。如果您使用的是 spring,您可以使用熟悉的 @RequestMapping 注解来描述您正在使用的端点。

我在下面提到了RandomRule 的例子。也可以查看 Github here 获取源代码。

@RibbonClient(name = "cloud-provider", configuration = CloudProviderConfiguration.class)
public class ConsumerApplication { 
    /* ... */
}

class CloudProviderConfiguration {
    @Bean
    public IRule ribbonRule(IClientConfig config) {
        return new RandomRule();
    }
}

另外,请参阅使用 Feign 设置 High Availability Load Balancer

【讨论】:

    【解决方案2】:

    根据documentation,当请求失败时,Ribbon 不会做任何事情来将服务器标记为关闭,而是依靠 ping 负载均衡器的服务器或客户端通过调用 markServerDown(Server server) 来通知 Ribbon。

    因此,您应该通过提供自己的实现来更改功能区 ping 服务器的时间间隔:

    public class CustomLoadBalancer {
      @Bean 
      public ILoadBalancer ribbonLoadBalancer(IClientConfig config,
                                              ServerList<Server> serverList, ServerListFilter<Server> serverListFilter,
                                              IRule rule, IPing ping) {
          return new ZoneAwareLoadBalancer<>(config, rule, ping, serverList, 
                                             serverListFilter, new PollingServerListUpdater(config));
      }
    }
    

    然后在你的 SpringBootApplication 配置中使用它,如下所示:

    @RibbonClients(defaultConfiguration = CustomLoadBalancer.class)
    
    

    或者您应该提供一个实现,以便在您认为合适的时候在您的客户端代码中调用功能区的markServerDown(Server) 方法。

    我建议你阅读thisstackoverflow 的帖子,我认为与你的问题直接相关。

    【讨论】:

    • 我在谷歌上查过。貌似 Ribbon 已经被弃用了https://stackoverflow.com/questions/65469735/versions-spring-boot-spring-cloud-ribbon-not-working 会被 spring-cloud-starter-loadbalancer 代替你知道新框架怎么解决这个问题吗?
    • 如果你想使用 spring-cloud-starter-loadbalancer 而不是 Ribbon,除了 eureka,你应该首先通过设置 spring.cloud.loadbalancer.ribbon.enabled=false 禁用 Ribbon 然后确保 spring-cloud-starter-loadbalancer 在你的类路径中。它将自动使用 eureka 创建其服务器列表,并将用作您的客户端负载均衡器。
    • 但根据上面的帖子,功能区不再包含在 Spring 父级中......
    • 这取决于您使用的发行版本。在这里查看表 1:spring.io/projects/spring-cloud
    • 还有github.com/spring-cloud/spring-cloud-release/wiki/…的已知问题,如果你需要这些功能,我不建议使用它。
    猜你喜欢
    • 2019-09-10
    • 2017-03-17
    • 2018-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    相关资源
    最近更新 更多