我们有一个服务器程序构建来处理来自客户端程序的数据。
构建此服务器以接受每分钟50K连接的数据。当我们没有服务器上的巨大负载时,它工作得很好。如果我们遇到负载,我们开始获得许多close_wait连接,这将永远不会被服务器释放。
这是我们正在做的方法。
这是我们使用的示例代码
public class Server {
public void start() {
bossGroup = new NioEventLoopGroup(bossThreads);
workerGroup = new NioEventLoopGroup(workerThreads);
bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new PipelineFactory())
.option(ChannelOption.SO_BACKLOG, serverBackLog);
try {
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress("127.0.0.1",6754));
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e.getCause());
}
}
}
class PipelineFactory extends ChannelInitializer<SocketChannel>{
private static final int SESSION_IDLE_TIME_MIN = 3;
public void addPipeline(ChannelPipeline pipeline) {
// Idle Timer
pipeline.addLast("timeout", new CustomTimeoutHandler(SESSION_IDLE_TIME_MIN, SESSION_IDLE_TIME_MIN, 0, TimeUnit.MINUTES));
// Message Decoder
pipeline.addLast("decoder", new SomeDecoder());
// Message Encoder
pipeline.addLast("encoder", new SomeEncoder());
// Protocol Handler
pipeline.addLast("handler", new DataHandler());
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
addPipeline(p);
}
}
我们仍然不知道为什么会产生许多close_wait连接。
有人可以指出我们在这里做错了吗?
答案 0 :(得分:-1)
你试过用吗?
.childOption(ChannelOption.SO_REUSEADDR, true);
答案 1 :(得分:-1)
客户端似乎尝试从其侧面关闭连接,但服务器不会从其侧面关闭连接,并且连接仍处于CLOSE_WAIT状态。
当应用程序未读取服务器读取缓冲区中的所有数据时,会发生这种情况,在从客户端收到第一个FIN后,不允许传输级别关闭连接。
我知道当您将通道设置为不可读时会发生这种情况,这会阻止应用程序从读取缓冲区接收新数据。在这种情况下,只有当通道设置为可读或服务器应用程序从其侧面明确关闭连接时,通道才会关闭。 如果我理解正确,您的服务器将在3分钟后关闭此连接,因为它将处于空闲状态。您可以通过捕获流量来查看这是否是问题。如果服务器用重置标志关闭连接,那么当没有从缓冲区读取所有数据时,可能表示连接已关闭。
检查您是否由于某种原因将通道设置为长时间不可读(错误与否)。
有关TCP连接终止FSM的更多信息,请参阅本指南The TCP/IP Guide