我之前做过一生中最复杂的 IP 技巧,所以我绝不是新手。现在我遇到了一个非常奇怪的情况。
我有一个系统,我复制了几十次甚至几百次,使用 jetty servlet 服务器,我使用的是 org.mortbay.jetty 6.11 的旧版可信版本。非常轻量。在 Windows、Linux、FreeBSD、Solaris 等操作系统上运行 JRE-1.5、-1.6、-1.7、-1.8 等。没问题。
目前,该系统在 Amazon Linux 此特定版本上运行良好。
__| __|_ )
_| ( / Amazon Linux 2 AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-2/
104 package(s) needed for security, out of 190 available
Run "sudo yum update" to apply all updates.
[ec2-user@ws ~]$ uname -a
Linux ws.pill.guru 4.14.88-88.73.amzn2.x86_64 #1 SMP Thu Dec 13 18:04:55 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
如果我仅通过创建 AMI 来克隆系统,然后启动一个实例,在相同的硬件类别(t2.nano、t2.micro)中。实例启动时,服务器会立即启动。日志中没有错误。但只是一些简单的事情:
curl -v http://localhost/
就会卡住。
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.55.1
> Accept: */*
>
然后它就卡在这里了。没有反应。卡住了。
Netstat 显示连接为 ESTABLISHED。
端口是80,我使用setcap方法允许打开该端口,cat /etc/rc.local:
touch /var/lock/subsys/local
setcap cap_net_bind_service=+ep $(readlink -f $(which java))
并且 /etc/ld.so.conf.d/java.conf 是
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-0.amzn2.x86_64/jre/lib/amd64/jli
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-0.amzn2.x86_64/lib/amd64/jli
使用 find /usr/lib/jvm/ -name jli >/etc/ld.so.conf.d/java.conf 创建
奇怪的是,如果我创建一个非常简单的 Java netcat 类型服务器,如下所示:
import java.net.Socket;
import java.net.ServerSocket;
import java.io.InputStream;
import java.io.OutputStream;
public class SimpleServer {
public static void main(String[] args) throws Exception {
try(ServerSocket serverSocket = new ServerSocket(Integer.parseInt(args[0]))) {
while(true) {
Socket conn = serverSocket.accept();
InputStream in = conn.getInputStream();
byte buffer[] = new byte[1024];
while(true) {
int n = in.read(buffer);
if(n < 0)
break;
System.out.write(buffer, 0, n);
}
}
}
}
}
那么它就可以正常工作。
现在您可能会说:您的 jetty 服务器有问题。请给我看看这个配置。尝试升级 eclipe jetty,不管怎样,不行,我承受不起这种类型的麻烦。我宁愿放弃整个 Linux 系统,转而使用 FreeBSD。但我报告这个细节,希望有人见过这样的问题,并可能提供一些自由联想。评论或回答。我会投票给你,我保证。
如果我发现什么问题,我就会回到这里并报告。
PS:是的,奇怪的是,在 EC2 上,这些连接在 netstat -d -a -t 上显示为 tcp6,即使它们显示 IPv4 地址。但这不是问题所在。它在旧服务器上仍然有效,但在完全相同的克隆上失败。
附言:现在我刚刚将所有内容转移到 FreeBSD,但遇到了完全相同的问题!
答案1
我找到了问题。使用 Jetty 代码中的调试器找到了它。
这是一个配置错误。
它与配置参数“spawnOrShrinkAt”有关,事实上,我认为这仍然是较新的 org.eclipe Jetty 代码中的一个参数,因此它可能对构建“嵌入式” Web 服务器的人有所帮助。
我开始在线程池中使用两个线程,它们都被 SocketConnectors 使用,一个用于 HTTP,一个用于 HTTPS。现在我建立了一个连接。ThreadPool 的 spawnOrShrinkAt 配置参数设置为 5。发生的事情是,由于 3 < spawnOrShrinkAt,因此未生成请求处理程序线程,因此请求被放入队列中。我一直看到这种情况,因为我总是在再次尝试之前断开连接。如果我保持连接打开并再试两次,最终就会超过 5 的阈值,并且请求将被处理。
当我克隆服务器时会发生这种情况是因为没有客户端尝试连接(我认为是这样)。
在我看来,Jetty 线程池配置参数相当晦涩难懂,而且 spawnOrShrink 值的不利影响对我来说也不清楚。我现在只需将其保留为默认值即可。