我收到了netty4.0作为水槽源的udp数据,使用本地传输,替换为Epoll *类。 我使用AdaptiveRecvByteBufAllocator设置了EpollChannelOption,但是recvbuffer没有自动调整大小。它总是丢失一些数据。我做错了什么?感谢
@Override
public void start() {
ExecutorService threadPool = Executors.newFixedThreadPool(maxThreads);
group = new EpollEventLoopGroup();
sourceCounter.start();
try {
Bootstrap serverBootstrap = new Bootstrap();
serverBootstrap.group(group).channel(EpollDatagramChannel.class)
.option(EpollChannelOption.SO_RCVBUF, 65536)
.option(EpollChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(200,65536,65536))
//.option(EpollChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(65536))
.option(EpollChannelOption.SO_REUSEPORT, true)
.handler(new UDPChannelHandler(maxSize, delimiter, threadPool));
//get Processors number
int updworkerThreads = Runtime.getRuntime().availableProcessors();
logger.info("availableProcessors is" + updworkerThreads);
for (int i = 0; i < updworkerThreads; ++i) {
ChannelFuture future = serverBootstrap.bind(new InetSocketAddress(host, port)).await();
if (!future.isSuccess()) {
logger.error(String.format("Fail to bind on port = %d.",
port), future.cause());
} else {
logger.info(String.format("success to bind on port = %d,count %d times.",
port, i + 1));
}
}
sourceCounter.setOpenConnectionCount(updworkerThreads);
} catch (InterruptedException ex) {
logger.error("listen SO_REUSEPORT port " + port + "error:", ex);
}
super.start();
}
@Override
public void stop() {
logger.info("UDP Source stopping...");
logger.info("Metrics:{}", counterGroup);
if (group != null) {
group.shutdownGracefully();
}
sourceCounter.stop();
super.stop();
}
class HandleTask implements Runnable {
ByteBuf msg;
String remoteIP;
public HandleTask(ByteBuf msg,String remoteIp) {
this.msg = msg;
this.remoteIP = remoteIp;
}
public void run() {
try {
Event e = buildEvent(msg);
if (e == null) {
logger.info("build event is null");
return;
}
getChannelProcessor().processEvent(e);
counterGroup.incrementAndGet("events.success");
sourceCounter.incrementAppendAcceptedCount();
sourceCounter.incrementEventAcceptedCount();
} catch (ChannelException ex) {
counterGroup.incrementAndGet("events.dropped");
logger.error("Error writting to channel", ex);
return;
}
}
// class to handle incoming Netty message events.
@ChannelHandler.Sharable
public class UDPChannelHandler extends SimpleChannelInboundHandler<DatagramPacket> {
protected int maxSize;
protected char delimiter;
protected boolean isIncompleteEvent;
private ExecutorService threadPool;
public UDPChannelHandler(int maxSize, char delimiter, ExecutorService threadPool) {
super();
this.maxSize = maxSize;
this.delimiter = delimiter;
this.isIncompleteEvent = false;
this.threadPool = threadPool;
}
@Override
public void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet)
throws Exception {
/*
* ChannelBuffer buf = (ChannelBuffer)e.getMessage(); byte[] des =
* buf.array(); String recvText = new String(des, 0, des.length);
* System.out.println(recvText); Channel ch = e.getChannel();
* ch.write(e.getMessage());
*/
//List<Integer> data = (List<Integer>) e.getMessage();
//ByteBuf data = (ByteBuf) packet.content();
//logger.info("channelRead0! " + new String(data.));
sourceCounter.incrementEventReceivedCount();
sourceCounter.incrementAppendReceivedCount();
ByteBuf data = Unpooled.copiedBuffer(packet.content());
String remoteIp = packet.sender().getAddress().getHostAddress();
HandleTask ht = new HandleTask(data,remoteIp);
threadPool.submit(ht);
//String content = String.format("client: %d, index: %d, a: %d, b: %d", clientNo, index, a, b);
//System.out.println(content);
}
}
答案 0 :(得分:0)
对于UDP,netty使用FixedRecvByteBufAllocator
(默认缓冲区大小为2048)作为默认值。即使您使用AdaptiveRecvByteBufAllocator
,netty也不会尊重它。
Netty以不同的方式使用RecvByteBufAllocator
进行TCP和UDP。对于TCP额外工作(调用record
或readComplete
),可以猜测最佳缓冲区大小。
如果netty尊重UDP的AdaptiveRecvByteBufAllocator
,则事件可能会在猜出最佳大小之前丢失数据。