4

我编写了一组简单的微服务,其架构如下:在此处输入图像描述

总之,我添加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,负载均衡器都会选择两个 HomeService 中的一个,它们在 8080 或 8081 端口上运行并调用其端点/home

但是,当 HomeService 之一关闭时,负载均衡器似乎没有意识到(尽管进行了ServerListRefreshInterval配置),并且error=500如果它尝试调用关闭实例,它将失败。

我该如何解决?

4

2 回答 2

0

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

解决方案在 github

总结一下:

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

应用程序.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
于 2017-05-25T09:26:27.943 回答
0

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

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

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

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

RetryableRibbonLoadBalancingHttpClient#executeWithRetry对于调试,在orRetryableRibbonLoadBalancingHttpClient#execute方法中创建断点很方便。此时,您有:

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

如果没有命中断点,则说明org.springframework.cloud.netflix.ribbon.apache.RetryableRibbonLoadBalancingHttpClientbean 没有被实例化。当 spring-retry 库不在类路径中时会发生这种情况。

于 2017-06-22T07:20:24.627 回答