服务器关闭时,负载平衡失败

时间:2017-05-24 20:45:56

标签: spring load-balancing netflix-zuul netflix-ribbon

我编写了一套简单的微服务,其架构如下:enter image description here

总而言之,我添加了spring-boot-starter-actuator以添加/health端点。

在Zuul / Ribbon配置中,我添加了:

zuul:
  ignoredServices: "*"
  routes:
    home-service:
      path: /service/**
      serviceId: home-service
      retryable: true

home-service:
  ribbon:
    listOfServers: localhost:8080,localhost:8081
    eureka.enabled: false
    ServerListRefreshInterval: 1

这样,每次客户端调用GET http://localhost:7070/service/home时,loadbalancer将选择两个运行在8080或8081端口上的HomeService中的一个,并将调用其端点/home

但是,当其中一个HomeService关闭时,负载均衡器似乎不知道(尽管有ServerListRefreshInterval配置),如果它尝试调用关闭实例,则会因error=500而失败。 / p>

我该如何解决?

2 个答案:

答案 0 :(得分:0)

我已收到并测试了spring-cloud team的解决方案。

解决方案是here in github

总结:

  • 我已将org.springframework.retry.spring-retry添加到我的zuul classpath
  • 我已将@EnableRetry添加到我的zuul应用程序
  • 我在zuul配置中添加了以下属性

<强> application.yml

server:
  port: ${PORT:7070}

spring:
  application:
    name: gateway

endpoints:
  health:
    enabled: true
    sensitive: true
  restart:
    enabled: true
  shutdown:
    enabled: true

zuul:
  ignoredServices: "*"
  routes:
    home-service:
      path: /service/**
      serviceId: home-service
      retryable: true
  retryable: true

home-service:
  ribbon:
    listOfServers: localhost:8080,localhost:8081
    eureka.enabled: false
    ServerListRefreshInterval: 100
    retryableStatusCodes: 500
    MaxAutoRetries: 2
    MaxAutoRetriesNextServer: 1
    OkToRetryOnAllOperations: true
    ReadTimeout: 10000
    ConnectTimeout: 10000
    EnablePrimeConnections: true

ribbon:
  eureka:
    enabled: false

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 30000

答案 1 :(得分:0)

调试超时可能很棘手,考虑到仅有3级路由(Zuul→Hystrix→Ribbon),不包括异步执行层和重试引擎。以下方案适用于Spring Cloud版本Camden.SR6及更新版本(我已经在Dalston.SR1上查看过此内容):

Zuul通过RibbonRoutingFilter路由请求,该请求使用请求上下文创建Ribbon命令。然后,Ribbon命令创建一个LoadBalancer命令,该命令使用spring-retry执行命令,根据Zuul设置为RetryTemplate选择重试策略。 @EnableRetry在这种情况下不执行任何操作,因为此注释允许在重试代理时使用@Retryable注释包装方法。

这意味着,您的命令持续时间仅限于这两者的较小值(请参阅this post):

  • [HystrixTimeout],这是调用的Hystrix命令的超时
  • [RibbonTimeout * MaxAutoRetries * MaxAutoRetriesNextServer](仅当Zuul在其配置中启用了它们时才重试),http客户端上的[RibbonTimeout = ConnectTimeout + ReadTimeout]。

为了进行调试,可以方便地在RetryableRibbonLoadBalancingHttpClient#executeWithRetryRetryableRibbonLoadBalancingHttpClient#execute方法中创建断点。此时,你有:

  • ContextAwareRequest个实例(例如RibbonApacheHttpRequestOkHttpRibbonRequest)包含请求上下文,其中包含Zuul的retryable属性;
  • LoadBalancedRetryPolicy使用负载均衡器上下文,其中包含功能区的maxAutoRetriesmaxAutoRetriesNextServerokToRetryOnAllOperations属性;
  • 带有requestConfig的
  • RetryCallback实例,其中包含HttpClient的connectTimeoutsocketTimeout属性;
  • RetryTemplate具有所选重试策略的实例。

如果未命中断点,则表示未实例化org.springframework.cloud.netflix.ribbon.apache.RetryableRibbonLoadBalancingHttpClient bean。当spring-retry库不在类路径中时会发生这种情况。

相关问题