Netty每次读取客户端数量

当许多客户端同时连接服务端时, Netty默认每次读取多少连接呢? 接下来我们 就结合源码和实战分析下.

在前面的文章我们讲到NioEventLoop在进行三部曲之后(创建-启动-执行), 就会一直无限循环在执行过程. 而执行过程又分为三个步骤(轮询IO事件-处理IO事件-执行队列任务). 那么在轮询到有IO事件, 准确说当有客户端连接的事件时, 接下来就是处理IO事件, 也就是在处理IO事件的过程中, 读取客户端连接, 那么每次读取多少个呢?

说明一点, 我们使用的Netty版本如下. 因为不同的版本(尤其是最新的版本)会有差异.

<dependency>
      <groupId>io.netty</groupId>
      <artifactId>netty-all</artifactId>
      <version>4.1.5.Final</version>
</dependency>

当服务端一直循环在以下代码时

io.netty.channel.nio.NioEventLoop#run

它会监听客户端请求. 我们假如此时通过telnet 127.0.0.1 8080连接到服务器共19个客户端.

服务器监听到ACCEPT事件后, 便会处理这些事件.

io.netty.channel.nio.NioEventLoop#processSelectedKeys

进而调用到如下主要代码

io.netty.channel.nio.AbstractNioMessageChannel.NioMessageUnsafe#read

此方法内会有一个循环

do {
    int localRead = doReadMessages(readBuf);
    if (localRead == 0) {
        break;
    }
    if (localRead < 0) {
        closed = true;
        break;
    }
    allocHandle.incMessagesRead(localRead);
} while (allocHandle.continueReading());

我们通过debug方式调试. 为了模拟实现并发同时有19个客户端到达, 我们先在轮询IO事件地方打个断点, 让服务端线程’停止’. 当我们通过telnet执行了19个命令后再’放行’服务端线程.

image

断点打好之后, 我们便通过telnet 连接到服务器, 共连接19次.

连接好之后, 我们’放行’服务端线程.

我们在上面说的代码中打个断点

image

此时还没有读取客户端连接, 目前size = 0

当我们继续’放行’

image

可以看到size = 16

我们先继续’放行’, 最后分析

服务器处理完上一波之后, 会再次轮询IO事件, 结果又轮询到ACCEPT事件, 继续处理IO事件. 这一次的size = 3

image

第一次size = 16 第二次size = 3 两个加起来正好等于我们的客户端连接数19. 于是我们猜测, 服务器每次读取客户端连接数是16. 虽然客户端同一时刻有19个客户端连接到服务器, 服务器也监听轮询到有客户端连接请求, 于是服务器在第一次循环过程只读取16个客户端. 剩下的3个客户端等到第二次轮询的时候再读取. 我们进入

allocHandle.continueReading()

查询一下.

io.netty.channel.DefaultMaxMessagesRecvByteBufAllocator.MaxMessageHandle#continueReading
public boolean continueReading() {
    return config.isAutoRead() &&
           attemptedBytesRead == lastBytesRead &&
           totalMessages < maxMessagePerRead &&
           totalBytesRead < Integer.MAX_VALUE;
}

我们可以看到有个maxMessagePerRead属性, 它就是控制每次读取客户端数量. 我们通过debug追踪下这个值. 我们在如下代码中打个断点.

io.netty.channel.DefaultMaxMessagesRecvByteBufAllocator#maxMessagesPerRead(int)

image

重启服务器

image

我们发现它最后被赋值16, 我们通过堆栈可以追踪到它的来源.

image

最后我们发现, 在创建NioServerSocketChannel的时候, 同时创建config(每个Channel对应一个Config). 每个Config对应一个RecvByteBufAllocator. 而maxMessagesPerRead属性属于RecvByteBufAllocator类. 而那个具体的16是在哪里呢?

image

image

每个Channel都有meta

image

源码中可知, 将这个16赋值给了RecvByteBufAllocator的maxMessagesPerRead属性.

结论: 服务端每次读取16个客户端请求

微信公众号

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Netty是一个基于Java的网络通信框架,提供了一种高性能、异步事件驱动的编程模型。在Netty中,可以使用同步方式来读取客户端发送的内容。 为了实现同步读取客户端内容,需要完成以下几个步骤: 1. 创建一个ServerBootstrap对象,并进行一系列的配置,包括设置线程模型、指定端口号等。 2. 创建一个ChannelPipeline对象,并设置用于处理网络消息的ChannelHandler链。在这个链中,需要添加一个用于读取客户端消息的ChannelInboundHandler。 3. 在ChannelInboundHandler中,可以通过重写channelRead方法来处理接收到的客户端消息。在这个方法中,可以通过channel参数获取客户端发送的具体内容。 4. 调用Bootstrap的bind方法,将服务器绑定到指定的端口,开始监听客户端连接。 5. 当有客户端连接进来时,Netty会自动调用ChannelInboundHandler的channelRead方法,并将接收到的消息作为参数传递给这个方法。我们可以在这个方法中进行同步读取客户端内容的处理逻辑。 6. 在channelRead方法中,可以通过调用ChannelHandlerContext的write方法将响应消息回写给客户端。 通过上述步骤,Netty可以实现同步读取客户端内容。当有客户端连接进来时,服务器会自动触发相应的事件,并将接收到的消息传递给ChannelInboundHandler。在这个处理器中,我们可以同步地读取和处理客户端发送的内容,并将响应消息返回给客户端Netty强大的异步事件驱动模型,使得同步读取客户端内容的实现变得简单而高效。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值