[英]Java embedded HttpServer: socket leak
I have next proxy handler (used embedded HttpServer and Jersey client): 我有下一个代理处理程序(用于嵌入式HttpServer和Jersey客户端):
@Override
public void handle(HttpExchange httpExchange) throws IOException {
....
....
WebTarget webTarget = httpClientHolder.getClient().target(url);
try (Response response = webTarget.request().get()) {
if (response.getStatusInfo().getStatusCode() != HttpStatus.SC_OK) {
logger.warn("Failed to download resource, url = " + url + " code = " +
response.getStatusInfo().getStatusCode());
throw new HttpException("Not found", 404);
}
httpExchange.sendResponseHeaders(200, response.getLength());
final InputStream is = response.readEntity(InputStream.class);
try (final OutputStream os = httpExchange.getResponseBody()) {
IOUtils.copy(is, os, 128);
} catch (IOException e) {
logger.warn("Error proxy data", e);
}
}
....
}
sometimes the following happens 有时发生以下情况
Error proxy data
java.io.IOException: Broken pipe
at sun.nio.ch.FileDispatcherImpl.write0(Native Method) ~[?:1.8.0_191]
at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47) ~[?:1.8.0_191]
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93) ~[?:1.8.0_191]
at sun.nio.ch.IOUtil.write(IOUtil.java:65) ~[?:1.8.0_191]
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471) ~[?:1.8.0_191]
at sun.net.httpserver.Request$WriteStream.write(Request.java:391) ~[?:1.8.0_191]
at sun.net.httpserver.FixedLengthOutputStream.write(FixedLengthOutputStream.java:78) ~[?:1.8.0_191]
at sun.net.httpserver.PlaceholderOutputStream.write(ExchangeImpl.java:444) ~[?:1.8.0_191]
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2315) ~[cache-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at org.apache.commons.io.IOUtils.copy(IOUtils.java:2270) ~[cache-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at server.TimelineVttHandler.handle(TimelineVttHandler.java:129) [cache-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79) [?:1.8.0_191]
at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83) [?:1.8.0_191]
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82) [?:1.8.0_191]
at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675) [?:1.8.0_191]
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79) [?:1.8.0_191]
at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647) [?:1.8.0_191]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_191]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_191]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_191]
Suppressed: java.io.IOException: insufficient bytes written to stream
at sun.net.httpserver.FixedLengthOutputStream.close(FixedLengthOutputStream.java:89) ~[?:1.8.0_191]
at sun.net.httpserver.PlaceholderOutputStream.close(ExchangeImpl.java:454) ~[?:1.8.0_191]
at server.TimelineVttHandler.handle(TimelineVttHandler.java:130) [cache-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79) [?:1.8.0_191]
at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83) [?:1.8.0_191]
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82) [?:1.8.0_191]
at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675) [?:1.8.0_191]
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79) [?:1.8.0_191]
at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647) [?:1.8.0_191]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_191]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_191]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_191]
It is not great problem for client, but resource still alive and we can see it via lsof: 对于客户端来说这不是一个大问题,但是资源仍然有效,我们可以通过lsof看到它:
lsof -n -p 14121 | grep TCPv6
java 13161 cache 143u sock 0,9 0t0 3617991518 protocol: TCPv6
java 13161 cache 180u sock 0,9 0t0 3618027565 protocol: TCPv6
java 13161 cache 184u sock 0,9 0t0 3618017649 protocol: TCPv6
This sockets will never closed while run the application. 运行应用程序时,此套接字永远不会关闭。 How to correct perform it ? 如何正确执行呢?
I solved this problem by throwing IOException
from handle
method. 我通过从handle
方法中抛出IOException
解决了这个问题。
try (final OutputStream os = httpExchange.getResponseBody()) {
IOUtils.copy(is, os, 128);
} catch (IOException e) {
logger.warn("Error proxy data", e);
throw e;
}
I have got this thought from contract of method 我从方法合同中得到了这个想法
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.