我之前一直在做我一生中最复杂的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);
}
}
}
}
}
然后它工作得很好。
现在你可能会说:你的码头服务器有问题。给我看看这个配置。试试 ecipe jetty 的升级,无论如何,不,我负担不起这种类型的跑来跑去。我宁愿放弃整个 Linux 系统,转而使用 FreeBSD。但我报告这个细节是希望有人看到这样的问题,并可能会给出一些自由联想。评论或回答。我给你投票,我保证。
如果我发现出了什么问题,我会回来报告自己。
PS:是的,奇怪的是,在 EC2 上,这些连接在 netstat -d -a -t 上显示为 tcp6,即使它们显示的是 IPv4 地址。但这不是问题。它仍然可以在旧服务器上运行,并且在确切的克隆上失败。
PS:现在我把所有东西都移到了 FreeBSD 上,我遇到了完全相同的问题!
我发现了这个问题。使用该 Jetty 代码中的调试器找到它。
这是一个配置错误。
它与配置参数“spawnOrShrinkAt”有关,事实上,我认为这仍然是较新的 org.eclipe Jetty 代码中的一个参数,因此它可能对构建“嵌入式”Web 服务器的人有所帮助。
我从线程池中的两个线程开始,它们都被 SocketConnectors 使用,一个用于 HTTP,一个用于 HTTPS。现在我建立了一个联系。ThreadPool 的 spawnOrShrinkAt 配置参数设置为 5。发生的情况是由于 3 < spawnOrShrinkAt 没有生成请求处理程序线程,因此将请求放入队列。我一直看到这种情况,因为我在再次尝试之前总是断开连接。如果我只是让连接保持打开状态并再试两次,最终将超过阈值 5 并且请求将得到处理。
为什么在我克隆服务器时发生这种情况是因为没有客户端进行连接尝试(我认为是这样)。
Jetty 线程池配置参数在 IMO 中相当模糊,我不清楚 spawnOrShrink 值的不利影响。我现在将其保留为默认值,它可以工作。