Spring Cloud / Netflix OSS中的负载平衡

时间:2016-06-07 12:15:56

标签: spring-boot spring-cloud microservices netflix-eureka netflix-ribbon

我正在关注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  

AccountsServer

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

2 个答案:

答案 0 :(得分:4)

@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),它应该有合理的默认值。

答案 1 :(得分:0)

我认为,由于您在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