Netty 服务器 - TCP 上的慢消费者
Netty server - slow consumer over TCP
我正在使用 Netty v4 编写一个 TCP 服务器。服务器将处理来自客户端的多个连接,并将数据流式传输给它们。
我希望能够检测到客户端何时以低速消耗数据。我基本上想避免 TCP 缓冲区因为客户端速度慢而变满!
这基本上就是 ZeroMQ 所做的(称为 "Slow Subscriber Detection (Suicidal Snail Pattern)")。如何使用 Netty 完成?
我当前的代码是(我将只显示服务器设置):
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1000)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new Handler());
}
});
ChannelFuture f = b.bind(8000).sync();
f.channel().closeFuture().sync();
这就是 SO_BACKLOG
选项的作用吗?它说这是用于排队的连接,但我对为特定连接排队的数据包感兴趣。
Is that what the SO_BACKLOG option does?
SO_BACKLOG选项的作用是什么?
It says it's for connections being queued
正确。
but I'm interested in packets being queued for a specific connection
所以你对SO_BACKLOG不感兴趣。
您可以这样做的一种方法是使用 WriteBufferWaterMarks。引用自 javadoc:
WriteBufferWaterMark is used to set low water mark and high water mark
for the write buffer. If the number of bytes queued in the write
buffer exceeds the high water mark, Channel.isWritable() will start to
return false. If the number of bytes queued in the write buffer
exceeds the high water mark and then dropped down below the low water
mark, Channel.isWritable() will start to return true again.
在您的子频道 configs 上设置适当的水印,慢速消费者会在 not-writable 时间段内标记频道 "long" 与敏捷消费者相比。因此,监听通道 write-ability 状态变化并跟踪通道的时间量 non-writable 应该可以识别缓慢的消费者和积压的相对严重性,然后如果他们的迟缓达到某个阈值,您可以断开客户端.
如果您的唯一目标是避免缓冲区溢出(背压),这种方法就足够了:
if (ctx.channel().isWritable()) {
ctx.writeAndFlush(msg);
}
我正在使用 Netty v4 编写一个 TCP 服务器。服务器将处理来自客户端的多个连接,并将数据流式传输给它们。
我希望能够检测到客户端何时以低速消耗数据。我基本上想避免 TCP 缓冲区因为客户端速度慢而变满!
这基本上就是 ZeroMQ 所做的(称为 "Slow Subscriber Detection (Suicidal Snail Pattern)")。如何使用 Netty 完成?
我当前的代码是(我将只显示服务器设置):
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1000)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new Handler());
}
});
ChannelFuture f = b.bind(8000).sync();
f.channel().closeFuture().sync();
这就是 SO_BACKLOG
选项的作用吗?它说这是用于排队的连接,但我对为特定连接排队的数据包感兴趣。
Is that what the SO_BACKLOG option does?
SO_BACKLOG选项的作用是什么?
It says it's for connections being queued
正确。
but I'm interested in packets being queued for a specific connection
所以你对SO_BACKLOG不感兴趣。
您可以这样做的一种方法是使用 WriteBufferWaterMarks。引用自 javadoc:
WriteBufferWaterMark is used to set low water mark and high water mark for the write buffer. If the number of bytes queued in the write buffer exceeds the high water mark, Channel.isWritable() will start to return false. If the number of bytes queued in the write buffer exceeds the high water mark and then dropped down below the low water mark, Channel.isWritable() will start to return true again.
在您的子频道 configs 上设置适当的水印,慢速消费者会在 not-writable 时间段内标记频道 "long" 与敏捷消费者相比。因此,监听通道 write-ability 状态变化并跟踪通道的时间量 non-writable 应该可以识别缓慢的消费者和积压的相对严重性,然后如果他们的迟缓达到某个阈值,您可以断开客户端.
如果您的唯一目标是避免缓冲区溢出(背压),这种方法就足够了:
if (ctx.channel().isWritable()) {
ctx.writeAndFlush(msg);
}