gpt4 book ai didi

java - Netty UDP 性能问题

转载 作者:行者123 更新时间:2023-12-01 09:57:03 25 4
gpt4 key购买 nike

我已经实现了三个小型 UDP 服务器。一种使用纯 Java DatagramSocket(线程),一种使用 Netty,最后一种也使用 Netty,但使用线程消息处理(因为 Netty 不支持使用 UDP 的多线程)。

经过一些测量后,我得到了每秒请求数的以下结果:

  • DatagramSocket ~30.000 请求/秒
  • Netty ~1.500 个请求/秒
  • Netty(线程):~8.000 个请求/秒

我必须实现的实际应用程序必须每秒处理 > 25.000 个请求。所以我的问题是,我是否在 Netty 上犯了错误,或者 Netty 的设计是否不能每秒处理那么多连接?

这里是实现

DatagramSocket 主要

public static void main(String... args) throws Exception {
final int port = Integer.parseInt(args[0]);
final int threads = Integer.parseInt(args[1]);
final int work = Integer.parseInt(args[2]);

DATAGRAM_SOCKET = new DatagramSocket(port);

for (int i = 0; i < threads; i++) {
new Thread(new Handler(work)).start();
}
}

DatagramSocket 处理程序

private static final class Handler implements Runnable {
private final int work;

public Handler(int work) throws SocketException {
this.work = work;
}

@Override
public void run() {
try {
while (!DATAGRAM_SOCKET.isClosed()) {
final DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
DATAGRAM_SOCKET.receive(receivePacket);
final InetAddress ip = receivePacket.getAddress();
final int port = receivePacket.getPort();
final byte[] sendData = "Hey there".getBytes();
Thread.sleep(RANDOM.nextInt(work));
final DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, ip, port);
DATAGRAM_SOCKET.send(sendPacket);
}
} catch (Exception e) {
System.out.println("ERROR: " + e.getMessage());
}
}
}

Netty 主要

public static void main(String[] args) throws Exception
{
final int port = Integer.parseInt(args[0]);
final int sleep = Integer.parseInt(args[1]);

final Bootstrap bootstrap = new Bootstrap();
bootstrap.group(new NioEventLoopGroup());
bootstrap.channel(NioDatagramChannel.class);
bootstrap.handler(new MyNettyUdpHandler(sleep));
bootstrap.bind(port).sync().channel().closeFuture().sync();
}

Netty 处理程序(线程)

public class MyNettyUdpHandler extends MessageToMessageDecoder<DatagramPacket> {
private final Random random = new Random(System.currentTimeMillis());
private final int sleep;

public MyNettyUdpHandler(int sleep) {
this.sleep = sleep;
}

@Override
protected void decode(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket, List list) throws Exception {
new Thread(() -> {
try {
Thread.sleep(random.nextInt(sleep));
} catch (InterruptedException e) {
System.out.println("ERROR while sleeping");
}

final ByteBuf buffer = Unpooled.buffer(64);
buffer.writeBytes("Hey there".getBytes());
channelHandlerContext.channel().writeAndFlush(new DatagramPacket(buffer, datagramPacket.sender()));
}).start();
}
}

非线程的 Netty Handler 是相同的,但没有线程。

最佳答案

您可以像这样更改您的 Nettydecode() 方法,使其等效于 DatagramSocket 代码:

@Override
protected void decode(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket, List list) throws Exception {
final Channel channel = channelHandlerContext.channel();
channel.eventLoop().schedule(() -> {
final ByteBuf buffer = Unpooled.buffer(64);
buffer.writeBytes("Hey there".getBytes());
channel.writeAndFlush(new DatagramPacket(buffer, datagramPacket.sender()));
}, random.nextInt(sleep), TimeUnit.MILLISECONDS);
}

但我猜测 sleep() 代码正在模拟您稍后将执行的业务代码。如果是这种情况,请确保您不在处理程序内运行阻塞代码。

编辑:

回答您的问题如下:您对 channel 有点困惑。您在 Bootstrap 中创建一个管道,并绑定(bind)到某个端口。返回的 channel 是服务器 channel 。处理程序方法中的 channel (在您的例子中是您的解码方法)就像您在传统套接字编程中 accept() 时获得的套接字。请注意,您从传入的 DatagramPacket 中提取的端口 - 它大致相同。因此,您可以通过此 channel 将数据发送回客户端。

我编写的用于安排响应的代码与您的 DatagramSocket 代码以及您编写的线程化 Netty 代码执行的操作相同。我不确定您为什么这样做,只是假设您有延迟响应的业务要求。如果不是这种情况,您可以删除计划调用,并且您的代码将运行得更快。如果您的业务逻辑是非阻塞的,并且运行时间为几毫秒,那么您就完成了。如果它是阻塞的,您需要尝试找到一个非阻塞替代方案,或者在执行器中运行它,即不在事件循环上运行。

希望这会有所帮助,即使这不是您最初问题的一部分。 Netty 很棒,我讨厌看到关于它的坏例子和不好的氛围,所以我想它值得我花时间;)

关于java - Netty UDP 性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37120249/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com