Spring Cloud / Netflix OSS 中的负载均衡

Posted

技术标签:

【中文标题】Spring Cloud / Netflix OSS 中的负载均衡【英文标题】:Load Balancing in Spring Cloud / Netflix OSS 【发布时间】:2016-10-07 08:13:01 【问题描述】:

我正在查看 Spring Boot / Cloud 和 Netflix FW(Eureka,Ribbon)。我正在研究这个例子:

https://spring.io/blog/2015/07/14/microservices-with-spring 基本上它是关于一些使用 Eureka Service Registry 的小型 Spring Boot 微服务。

我现在想启动同一个服务的多个实例(在这个例子中是 AccountService,在不同的端口上)。我读到的所有内容(上面的文章,http://callistaenterprise.se/blogg/teknik/2015/04/10/building-microservices-with-spring-cloud-and-netflix-oss-part-1/ 等)都表明,如果我这样做,所有实例都会冗余地注册到 Eureka,当我调用服务时,会应用客户端负载平衡并动态选择要调用的服务。

但是,事实并非如此。当我启动第一个服务实例时,它会注册并显示在 Eureka Dashboard 中。当我在不同的端口上启动相同的服务时,它也会注册,但它似乎替换了以前的服务实例:Eureka Dashboard 仍然只显示一个可用区 = 1(应该是 2?)的实例并且所有调用此服务由第二个实例处理。当我查询注册表时,只应用了这个实例。

当我停止第二个实例时,一段时间后 Eureka 切换回第一个实例,它仍然有效。所以它似乎保留了所有实例,但只使用最新注册的实例。

我错过了什么重要的事情吗?我认为应该同时使用所有实例?

=========== 应用程序属性是(实际上与 Spring 站点中的示例相同):

EurekaServer

eureka:  
  instance:  
    hostname: localhost  
  client:    
    registerWithEureka: false  
    fetchRegistry: false  

server:  
  port: 1111     

spring:  
  thymeleaf:  
    enabled: false  

帐户服务器

spring:  
  application:  
    name: accounts-service  
  freemarker:  
    enabled: false           
  thymeleaf:  
    cache: false             
    prefix: classpath:/accounts-server/templates/      

eureka:  
  client:  
    serviceUrl:  
      defaultZone: http://localhost:1111/eureka/  

server:  
  port: 4444   # HTTP (Tomcat) port, for the second instance this is changed to a different port

【问题讨论】:

您可以从客户端和服务器发布您的 application.properties 吗? 【参考方案1】:

@dshuld 如果您使用的是 Angel 发布系列或版本 1.0.x,您需要使每个实例都有一个唯一的 ID。请参阅docs here。比如:

eureka:
  instance:
    metadataMap:
      instanceId: $spring.application.name:$spring.application.instance_id:$server.port

对于 Brixton 发布系列 (1.1.x),它应该有一个合理的默认值。

【讨论】:

【参考方案2】:

我认为,由于您在 AccountsServer 上使用静态端口号,Eureka 只会注册一个实例... 你可以在客户端上做这样的事情

server:
  compression.enabled: true
  port: 0

(在这种情况下,我使用 YAML 进行配置,而不是属性)

在网关上,你应该指定你想要一个负载均衡器,就像那样

 @Autowired
 private LoadBalancerClient loadBalancer;
 ....
 private String getUrl()
    return loadBalancer.choose("your-service-name").getUri().toString();

我也做过类似的,有兴趣的可以看看here

【讨论】:

正如我在问题中所写,第二个实例使用不同的端口启动。而且我也尝试过 LoadBalancerClient.choose() 方法,但那个方法只给我一个实例,而不是另一个。 哦,抱歉,我没看到。如果您等待 1 或 2 分钟会发生什么?客户是否可能找到这 2 个实例? 不,它只会找到最近注册的实例...当我停止该实例时,它会切换回第一个注册的实例

以上是关于Spring Cloud / Netflix OSS 中的负载均衡的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud Netflix—使用EurekaClient

Spring Cloud Netflix(网飞)

`spring-cloud-starter-eureka-server`和`spring-cloud-starter-netflix-eureka-server`之间的区别

Netflix之后,如何用Spring Cloud 新组件构建微服务架构?

Spring Cloud / Netflix OSS 中的负载均衡

随手记录关于spring-cloud-starter-eureka-server 和 spring-cloud-starter-netflix-eureka-server