核心知识

  • 高性能RPC框架的3个要素:IO模型、数据协议(http、protobuf、thrift)、线程模型
  • EventLoop好比一个线程,1个EventLoop可以服务多个Channel(轮询找是否有请求),1个Channel只有一个EventLoop

可以创建多 个 EventLoop 来优化资源利用,也就是EventLoopGroup

  • EventLoopGroup 负责分配 EventLoop 到新创建的 Channel,里面包含多个EventLoop
    • EventLoopGroup -> 多个 EventLoop , EventLoop -> 维护一个 Selector -》轮询多个channel
    • Selector 学习资料:http://ifeve.com/selectors/
  • 源码分析默认线程池数量 (2×核数)

sector工作模式
image.png

image.png

EventLoop和EventLoopGroup

EventLoop -> 维护一个 Selector ()
image.png
image.png
观看源码可以得到一个结论:别看了,看不懂的 = =,看代码+百度半天也没搞懂这两个的作用与区别
知道EventLoop -> 维护一个 Selector (),然后这个sector轮询多个channel,维护多个连接就行了。别的源码跟优化有关

当没有指定线程数的时候,netty如何建立线程数。
观察源码可以看到当为0返回第一个,默认线程池数量 :cpu核数✖2
NioEventLoopGroup()源码
image.png

启动引导类servebootstap

之前的例子里两个线程组相一个接待连接,一个处理。相当于一个主从reactor模型。
我们也可以改变参数实现别的线程模型
单线程
image.png

源码:
image.png
单Reactor多线程:把接收线程设为1
image.png

channel

设置io类型,现在都是nio

https://www.cnblogs.com/ZhuChangwu/p/11204057.htmlimage.png
设置子通道因为一个接收,一个处理么,另一个负责处理的也需要设置下,进行初始化操作,加handler等一系列操作

option

option: 作用于每个新建立的channel,设置TCP连接中的一些参数,如下(tcp知识详加网络基础tcp部分)
这块应用与连接数多需要优化的情况,可以不重点讲

  • ChannelOption.SO_BACKLOG: 存放已完成三次握手的请求的等待队列的最大长度;
  • Linux服务器TCP连接底层知识:
    • syn queue:半连接队列,洪水攻击,tcp_max_syn_backlog
    • accept queue:全连接队列, net.core.somaxconn
  • 系统默认的somaxconn参数要足够大 ,如果backlog比somaxconn大,则会优先用后者 ,可以通过改变backlog来改变前者 https://g ithub.com/netty/netty/blob/4.1/common/src/main/java/io/netty/util/NetUtil.java#L250
  • ChannelOption.TCP_NODELAY: 为了解决Nagle的算法问题,默认是false, 要求高实时性,有 数据时马上发送,就将该选项设置为true关闭Nagle算法;如果要减少发送次数,就设置为 false,会累积一定大小后再发送

知识拓展: https://baike.baidu.com/item/Nagle%E7%AE%97%E6%B3%95/5645172 https://w
ww.2cto.com/article/201309/241096.html
image.png
image.png

childHandler

用于对每个通道里面的数据处理

childOption

作用于被accept之后的连接

绑定端口与等待

//绑定端口,同步等待成功
ChannelFuture channelFuture = serverBootstrap.bind(port).sync();

//等待服务端监听端口关闭
channelFuture.channel().closeFuture().sync();

客户端启动引导类Bootstrap

remoteAddress: 服务端地址
handler:和服务端通信的处理器

  1. // 略
  2. .remoteAddress(new InetSocketAddress(host, port))
  3. .handler(new ChannelInitializer<SocketChannel>() {
  4. protected void initChannel(SocketChannel ch) throws Exception {
  5. ch.pipeline().addLast(new EchoClientHandler());
  6. }
  7. })
  8. // 略
  9. //连接到服务端,connect是异步连接,在调用同步等待sync,等待连接成功
  10. ChannelFuture channelFuture = bootstrap.connect().sync();
  11. //阻塞直到客户端通道关闭
  12. channelFuture.channel().closeFuture().sync();

注意
客户端为handler,服务端为childhandler