Hystrix:Apache http客户端请求不中断
Hystrix: Apache http client requests are not interrupted
我有一个 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 请求继续执行并打印 "After - process method" 字符串。
我只在 http 客户端请求中看到过这种行为。如果 http 请求被诸如线程睡眠或非常大的 for 循环之类的任何其他内容替换,hystrix 线程将按预期中断。
有没有人知道为什么会发生这种情况?
原因是在 Java 中中断线程不会 "force stop" 它。相反,调用 Thread.interrupt()
只是设置一个标志,该标志可以但不必由 运行 线程解释。在此处查看更多信息:What does java.lang.Thread.interrupt() do?
Apache HTTP 客户端不解释这个标志(因为 JRE 的套接字读取操作不能被中断)。因此,HTTP 请求没有被取消,只是完成了。
似乎在过去,一些 IO 操作,在某些平台(solaris)上可以使用 Thread.interrupt()
中断。现在对于 java.io, 似乎不再是 possible/specified,但对于 java.nio 仍然是可能的。
(有关详细信息,请参阅 Java bug 4385444 and Java bug 7188233)
所以即使 with some platforms/versions it seems still possible 使用 Thread.interrupt()
中断阻塞 IO,这似乎显然不推荐:
- https://www.oreilly.com/library/view/java-threads-second/1565924185/ch04s05.html#ch04-8-fm2xml
- https://wiki.sei.cmu.edu/confluence/display/java/THI04-J.+Ensure+that+threads+performing+blocking+operations+can+be+terminated
所以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();
}
}
我有一个 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 请求继续执行并打印 "After - process method" 字符串。
我只在 http 客户端请求中看到过这种行为。如果 http 请求被诸如线程睡眠或非常大的 for 循环之类的任何其他内容替换,hystrix 线程将按预期中断。
有没有人知道为什么会发生这种情况?
原因是在 Java 中中断线程不会 "force stop" 它。相反,调用 Thread.interrupt()
只是设置一个标志,该标志可以但不必由 运行 线程解释。在此处查看更多信息:What does java.lang.Thread.interrupt() do?
Apache HTTP 客户端不解释这个标志(因为 JRE 的套接字读取操作不能被中断)。因此,HTTP 请求没有被取消,只是完成了。
似乎在过去,一些 IO 操作,在某些平台(solaris)上可以使用 Thread.interrupt()
中断。现在对于 java.io, 似乎不再是 possible/specified,但对于 java.nio 仍然是可能的。
(有关详细信息,请参阅 Java bug 4385444 and Java bug 7188233)
所以即使 with some platforms/versions it seems still possible 使用 Thread.interrupt()
中断阻塞 IO,这似乎显然不推荐:
- https://www.oreilly.com/library/view/java-threads-second/1565924185/ch04s05.html#ch04-8-fm2xml
- https://wiki.sei.cmu.edu/confluence/display/java/THI04-J.+Ensure+that+threads+performing+blocking+operations+can+be+terminated
所以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();
}
}