【问题标题】:Netflix Ribbon and Hystrix TimeoutNetflix 功能区和 Hystrix 超时
【发布时间】:2017-01-02 10:28:54
【问题描述】:

我们在项目中使用 Spring Cloud。我们有几个微服务,每个都有自己的 .yml 文件。

以下属性仅在zuul服务器中

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000

    ribbon: 
     ConnectTimeout: 3000
     ReadTimeout: 60000

测试 1:

账户服务:

我调用这个服务来测试超时,我通过 zuul 调用请求,即使用端口 8006。

@RequestMapping(value = "/accountholders/{cardHolderId}/accounts", produces = "application/json; charset=utf-8", method = RequestMethod.GET)
    @ResponseBody
    public AllAccountsVO getAccounts(@PathVariable("cardHolderId") final String cardHolderId,
            @RequestHeader("userContextId") final String userContextId,
            @RequestParam final MultiValueMap<String, String> allRequestParams, final HttpServletRequest request) {

        return iAccountService.getCardHolderAccountsInfo(cardHolderId, userContextId, request, allRequestParams,
                ApplicationConstants.ACCOUNTHOLDER);
    }

上面的服务在内部使用 Spring RestTemplate 调用下面的服务。 我通过在 Association Service 中添加如下所示的 5000 毫秒睡眠时间开始测试,并向 Accounts Service 发出请求(getAccounts 调用)。

协会服务:

@RequestMapping(value = "/internal/userassociationstatus", produces = "application/json; charset=utf-8", consumes = "application/json", method = RequestMethod.GET)
    @ResponseBody
    public UserAssociationStatusVO getUserAssociationStatus(@RequestParam final Map<String, String> allRequestParams) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return iUserAssociationsService.getUserAssociationStatus(allRequestParams);
    }

以下是我在Association Service

中遇到的错误
org.apache.catalina.connector.ClientAbortException: java.io.IOException: An established connection was aborted by the software in your host machine
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:393) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:426) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:342) ~[tomcat-embed-core-8.0.30.jar:8.0.30]

以下是我在 Accounts Service

中遇到的错误
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://USERASSOCIATIONS-V1/user/v1/internal/userassociationstatus?cardholderid=123&usercontextid=222&role=ACCOUNT": com.sun.jersey.api.client.ClientHandlerException: java.net.SocketTimeoutException: Read timed out; nested exception is java.io.IOException: com.sun.jersey.api.client.ClientHandlerException: java.net.SocketTimeoutException: Read timed out
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:607) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:557) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:475) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]

如果我将睡眠时间保持为 4500,它会给我响应,但如果是 >=4800,它会引发上述异常。我认为这与功能区超时无关,而是与其他有关。在某一点之后出现上述异常的任何具体原因。

测试 2

然后我尝试直接在Accounts Service中保持75000毫秒的休眠时间,并去掉休眠时间Association Service

@RequestMapping(value = "/accountholders/{cardHolderId}/accounts", produces = "application/json; charset=utf-8", method = RequestMethod.GET)
    @ResponseBody
    public AllAccountsVO getAccounts(@PathVariable("cardHolderId") final String cardHolderId,
            @RequestHeader("userContextId") final String userContextId,
            @RequestParam final MultiValueMap<String, String> allRequestParams, final HttpServletRequest request) {

        try {
            Thread.sleep(75000);
        } catch (InterruptedException ex) {
            // TODO Auto-generated catch block
            ex.printStackTrace();
        }
        return iAccountService.getCardHolderAccountsInfo(cardHolderId, userContextId, request, allRequestParams,
                ApplicationConstants.ACCOUNTHOLDER);
    }

在这种情况下,我得到了“异常”:“com.netflix.zuul.exception.ZuulException”,

在我的 APIGateway(Zuul 应用程序)日志中,我看到以下错误。

com.netflix.zuul.exception.ZuulException: Forwarding error
    at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.forward(RibbonRoutingFilter.java:134) ~[spring-cloud-netflix-core-1.1.0.M5.jar:1.1.0.M5]
    at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.run(RibbonRoutingFilter.java:76) ~[spring-cloud-netflix-core-1.1.0.M5.jar:1.1.0.M5]
    at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:112) ~[zuul-core-1.1.0.jar:1.1.0]
    at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:197) ~[zuul-core-1.1.0.jar:1.1.0]


Caused by: com.netflix.hystrix.exception.HystrixRuntimeException: useraccounts-v1RibbonCommand timed-out and no fallback available.
    at com.netflix.hystrix.AbstractCommand$16.call(AbstractCommand.java:806) ~[hystrix-core-1.4.23.jar:1.4.23]
    at com.netflix.hystrix.AbstractCommand$16.call(AbstractCommand.java:790) ~[hystrix-core-1.4.23.jar:1.4.23]
    at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:99) ~[rxjava-1.0.14.jar:1.0.14]
    at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70) ~[rxjava-1.0.14.jar:1.0.14]

我认为这与 Ribbon ConnectTimeout 或 ReadTimeout 无关。此错误是由于属性 “execution.isolation.thread.timeoutInMilliseconds: 60000”。我还将此属性减少到 10000 毫秒以测试行为,如果睡眠时间更长(例如:12000),则会得到相同的异常。

我想了解 Ribbon ConnectTimeout 和 Read-timeout 与 Hystrix 超时以及如何在我的应用程序中测试功能区超时。另外,如果我想为不同的微服务设置不同的超时时间,我是否将这些属性保存在各自的 .yml 文件中?有什么想法吗?

我正在尝试创建一个供我的团队使用的文档,以便开发人员轻松了解这些超时选项在 Spring Cloud 中的工作原理。

(描述很长,但为了更清楚,我必须写详细)

【问题讨论】:

  • Hystrix 是一个与正在运行的代码无关的断路器。如果代码的运行时间比 hystrix 超时时间长,你会得到一个 hystrix 超时异常。我不确定关于 yml 文件的问题。
  • @spencergibb 谢谢,知道了。但是这里 Ribbon ConnectTimeout 和 Readtimeout 的目的是什么。当有人向微服务发出请求时,它们是如何工作的?

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


【解决方案1】:

功能区中的 connectTimeoutreadTimeout 被向下传递到底层 HTTP 客户端。它们适用于 HTTP 连接(而不是建立连接后的 HTTP 请求)。我不确定为什么你真的需要像这样测试它,但是对于一个健康的服务器来说这会很困难。比如connectTimeout,你需要一个可以接受TCP连接但不能完成HTTP层连接的。对于readTimeout,您需要一个能够建立连接但不发送任何数据(根本)的设备。

【讨论】:

  • config 中真正的解决方案是什么?
猜你喜欢
  • 2019-01-27
  • 2016-02-06
  • 2018-11-02
  • 2017-09-10
  • 2014-05-20
  • 2016-04-18
  • 2017-01-10
  • 2016-07-05
  • 2020-08-04
相关资源
最近更新 更多