2

我使用 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);
}

假装配置:

@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();
}

假装配置:

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

4

2 回答 2

0

功能区 - 负载均衡器

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

Feign - Http 客户端

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

我在下面提到了RandomRule. 也可以在此处查看 Github以获取源代码。

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

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

另外,请参阅使用 Feign 设置高可用性负载均衡器

于 2021-05-12T05:21:11.647 回答
0

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

因此,您应该通过提供自己的实现来更改功能区 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)或者,当您认为时机成熟时,您应该在客户端代码中提供调用功能区方法的实现。

我建议您阅读这篇stackoverflow 帖子,我认为这与您的问题直接相关。

于 2021-05-12T10:57:44.817 回答