如何解决服务实例关闭时更新服务状态
我使用 Spring Cloud 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
解决方法
功能区 - 负载均衡器
它开箱即用地为您提供循环负载平衡,但您可以实现自己的 @RibbonClient
(即使是针对特定服务)并设计您的自定义负载平衡,例如基于 eureka 元数据。负载平衡发生在客户端。
Feign - Http 客户端
使用 @FeignClient
,您可以为您的其他服务(或基础设施之外的服务)快速开发客户端。它与 Ribbon 和 eureka 集成在一起,因此您可以参考您的服务 @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
,根据 documentation,当请求失败时,Ribbon 不会做任何事情来将服务器标记为关闭,而是依靠 ping 负载均衡器的服务器或客户端来通过调用 {{1 }}。
因此,您应该通过提供自己的实现来更改功能区 ping 服务器的时间间隔:
markServerDown(Server server)
然后在您的 SpringBootApplication 配置中使用它,如下所示:
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));
}
}
或者您应该提供一个实现来在您认为合适的时候在您的客户端代码中调用功能区的 @RibbonClients(defaultConfiguration = CustomLoadBalancer.class)
方法。
我建议您阅读 this stackoverflow 帖子,我认为这与您的问题直接相关。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。