我写了一个服务器,在连接后向所有客户端发送大量消息。
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
while (true){
content = arrayblockqueue.poll()
ctx.writeAndFlush(content+"\r\n");
}
}
发送数千条消息后,该频道不再发送消息。通过调试,我发现调用了AbstractNioByteChannel.incompleteWrite,当网络拥塞时,selectionKey将添加SelectionKey.OP_WRITE。设置OP_WRITE后,AbstractNioUnsafe.isFlushPending()将返回true,因此无法完成flush()。如何让netty恢复这种情况?或者我以错误的方式使用netty?
答案 0 :(得分:2)
直接从I / O线程调用您的处理程序方法。在处理程序方法返回之前,调用处理程序方法的I / O线程无法执行任何I / O,这就是为什么没有看到任何内容的原因。
从代码中看,您想要的是从阻塞队列中获取消息并将其写入通道。您可以只写入通道,而不是使用阻塞队列。几乎Netty中的所有操作都是线程安全的。例如:
public static void main(String[] args) throws Exception {
...
Channel ch = ...;
for (int i = 0; i < 1000000; i ++) {
ch.writeAndFlush(String.valueOf(i) + "\r\n");
}
...
}
// And your handler doesn't need an arrayblockingqueue.
但是,上面的代码可能会使Netty的事件队列无限增长,从而产生OutOfMemoryError
。为了防止写入请求无限排队,您必须使用writeAndFlush()
操作返回的未来。
for (int i = 0; i < 1000000; i ++) {
ChannelFuture f = ch.writeAndFlush(String.valueOf(i) + "\r\n");
if ((i + 1) % 100 == 0) {
// Wait until the write request is actually finished
// so that the event queue becomes empty.
f.sync();
}
}