【问题标题】:Hystrix: Apache http client requests are not interruptedHystrix:Apache http 客户端请求不会被中断
【发布时间】:2016-06-28 13:32:38
【问题描述】:

我有一个 apache HTTP 客户端定义如下:

private static HttpClient httpClient = null;
HttpParams httpParams = new BasicHttpParams();
httpParams.setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, Boolean.TRUE);
httpParams.setParameter(CoreProtocolPNames.USER_AGENT, "ABC");

HttpConnectionParams.setStaleCheckingEnabled(httpParams, Boolean.TRUE);

SSLSocketFactory sf = SSLSocketFactory.getSocketFactory();

SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
schemeRegistry.register(new Scheme("https", 443, sf));

//Initialize the http connection pooling
PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager(schemeRegistry);

// Initialize the connection parameters for performance tuning
connectionManager.setMaxTotal(12);
connectionManager.setDefaultMaxPerRoute(10);

httpClient = new DefaultHttpClient(connectionManager, httpParams);

我有一个 hystrix 命令play 并启用了以下属性:

hystrix.command.play.execution.isolation.thread.timeoutInMilliseconds=1
hystrix.command.play.execution.isolation.thread.interruptOnTimeout=true

命令本身定义如下:

    @HystrixCommand(groupKey="play_group",commandKey="play")
    public String process(String request) throws UnsupportedOperationException, IOException, InterruptedException {
        System.out.println("Before -  process method : " + request);
        callHttpClient(request);
        System.out.println("After -  process method" + request);
        return "";
    }

    private void callHttpClient(String request) throws ClientProtocolException, IOException, InterruptedException {
        HttpGet get = new HttpGet("http://www.google.co.in");
        HttpResponse response = httpClient.execute(get);
        System.out.println("Response:" + response);
    }

我现在尝试循环执行该命令 5 次:

    public static void main(String[] args) throws UnsupportedOperationException, IOException, InterruptedException {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContextTest.xml");
        HystrixPlayground obj = ctx.getBean(HystrixPlayground.class);

        long t1 = System.currentTimeMillis();
        for (int i = 0; i < 5; i++) {
            try{
                System.out.println(obj.process("test" + i));
            } catch(Exception ex) {
                System.out.println(ex);
            }
            long t2 = System.currentTimeMillis();
            System.out.println("Time(ms) : ---->" + (t2 - t1));

超时设置为 1 毫秒,因此 process 方法会抛出 HystrixRunTimeException。但是,http请求继续执行并打印“后处理方法”字符串。

我已经看到这种行为仅适​​用于 http 客户端请求。如果 http 请求被其他任何东西(例如线程睡眠或非常大的 for 循环)替换,则 hystrix 线程会按预期中断。

有没有人知道为什么会发生这种情况?

【问题讨论】:

标签: java timeout hystrix


【解决方案1】:

原因是在 Java 中中断线程不会“强制停止”它。相反,调用Thread.interrupt() 只是设置一个可以但不必由正在运行的线程解释的标志。在此处查看更多信息:What does java.lang.Thread.interrupt() do?

Apache HTTP 客户端不解释这个标志(因为 JRE 的套接字读取操作不能被中断)。因此,HTTP 请求不会被取消而只是完成。

【讨论】:

  • 有人在 Apache httpclient 项目中提出过这个问题吗?
  • Thread.interrupt() 不会中断在 JRE 本机代码中阻塞的套接字读取操作。此问题与 HttpClient 无关。
  • 确实如此。感谢您的澄清。我调整了答案。
【解决方案2】:

过去,在某些平台(solaris)上,似乎可以使用Thread.interrupt() 中断某些 IO 操作。现在对于 java.io 似乎不再可能/指定,但对于 java.nio 仍然可能。 (详情请参阅Java bug 4385444Java bug 7188233

所以即使with some platforms/versions it seems still possibleThread.interrupt() 中断阻塞IO,这似乎显然不推荐:

所以httpclient 没有错。使用 Hystrix,您应该 abort() Hystrix 超时请求。如果你正在使用 fallback,你可以在getFallback() 中调用它,如果没有,你可以在得到结果后调用它。例如:

try {
    hystrixCommand.execute();
} catch (HystrixRuntimeException e) {
    switch (e.getFailureType()) {
    case TIMEOUT:
       // supposing you add a getHttpRequest getter on your command.
       hystrixCommand.getHttpRequest().abort();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-09
    • 2020-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多