当我执行
端口1234的监听由HTTPServer触发并创建,创建的代码为
根据netstat(8) - Linux manual page,我们知道在套接字处于
netstat -tulnp
命令时,输出如下:Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.11:43043 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8005 0.0.0.0:* LISTEN 1/java
tcp 0 0 0.0.0.0:2021 0.0.0.0:* LISTEN 1/java
tcp 0 0 0.0.0.0:22222 0.0.0.0:* LISTEN 1/java
tcp 0 0 0.0.0.0:8719 0.0.0.0:* LISTEN 1/java
tcp 101 0 0.0.0.0:80 0.0.0.0:* LISTEN 1/java
tcp 51 0 0.0.0.0:1234 0.0.0.0:* LISTEN 1/java
tcp 0 0 0.0.0.0:20891 0.0.0.0:* LISTEN 1/java
udp 0 0 127.0.0.11:55285 0.0.0.0:* -
Recv-Q的值引起了我的注意。在调查后,我发现JVM应用程序中发生了OOM,并且可以在日志中找到负责监视端口80的http-nio-80-Acceptor-0线程已退出,负责分派端口1234请求的线程也已退出。相关的日志如下:
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "http-nio-80-Acceptor-0"
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "Thread-5"
tomcat的默认配置是backlog为100,源代码位于tomcat/AbstractEndpoint.java at 8.5.59 · apache/tomcat · GitHub。
/**
* Allows the server developer to specify the acceptCount (backlog) that
* should be used for server sockets. By default, this value
* is 100.
*/
private int acceptCount = 100;
public void setAcceptCount(int acceptCount) { if (acceptCount > 0) this.acceptCount = acceptCount; }
public int getAcceptCount() { return acceptCount; }
端口1234的监听由HTTPServer触发并创建,创建的代码为
HttpServer.create(new InetSocketAddress(PROMETHEUS_SERVER_PORT), 0);
,backlog在ServerSocket.java
中被更正为50,源代码位于jdk/ServerSocket.java at jdk8-b120 · openjdk/jdk · GitHub。public void bind(SocketAddress endpoint, int backlog) throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
if (!oldImpl && isBound())
throw new SocketException("Already bound");
if (endpoint == null)
endpoint = new InetSocketAddress(0);
if (!(endpoint instanceof InetSocketAddress))
throw new IllegalArgumentException("Unsupported address type");
InetSocketAddress epoint = (InetSocketAddress) endpoint;
if (epoint.isUnresolved())
throw new SocketException("Unresolved address");
if (backlog < 1)
backlog = 50;
try {
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkListen(epoint.getPort());
getImpl().bind(epoint.getAddress(), epoint.getPort());
getImpl().listen(backlog);
bound = true;
} catch(SecurityException e) {
bound = false;
throw e;
} catch(IOException e) {
bound = false;
throw e;
}
}
根据netstat(8) - Linux manual page,我们知道在套接字处于
Listening
状态时,Recv-Q表示当前的syn backlog。令人困惑的是,为什么Recv-Q的值比我们设置的backlog值多1?
ss
代替telnet。正在进一步研究中... - Liam Kelly