侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130555 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

Netty源码分析-服务启动

2023-09-22 星期五 / 0 评论 / 0 点赞 / 27 阅读 / 5403 字

启动基类:AbstractBootStrap: 1. 该类主要定义了客户端和服务端启动netty均需要的字段和方法,核心字段包括: EventLoopGroup:线程池,如果是服务端则在拓展类Serv

启动基类:AbstractBootStrap:

1. 该类主要定义了客户端和服务端启动netty均需要的字段和方法,核心字段包括:

EventLoopGroup:线程池,如果是服务端则在拓展类ServerBootstrap中可以选择再定义一个chilEventLoopGroup,用于处理已建立连接的客户端的请求。该线程池在服务端主要为acceptor提供执行线程,执行客户端的连接请求,而在客户端则为建立连接提供线程。

ChannelFactory:channel生产工厂,泛型类,根据泛型类型,生产实际的channel,如NioServerSocketChannel、EpollServerSocketChannel,对应服务端来说则是生产监听客户端连接的acceptor channel,即ServerSocketChannel(即对应socket编程中的ServerSocket);对应客户端则生产发起与服务端连接的channel。

ChannelHandler:定义以上channel的事件处理器

ChannelOptions:保存以上channel的选项,如设置buffer的allocator,tcp的keepAlive等

AttributeKey:保存以上channel的属性

localAdress:绑定的地址,服务端为acceptor监听地址,客户端为建立连接的地址

2. 核心方法为bind和initAndRegister:

(1)bind为包括第一步为创建channel并从eventloopgroup线程池中获取线程,该线程负责处理该channel整个生命周期的io事件;第二步为在第一步成功之后,根据localAddress绑定到实际的ip和port;

(2)bind方法在第一步中需要调用initAndRegiter,initAndRegister调用channelFactory创建channel,并调用init(这是一个protected的abstract方法,由具体实现类负责定义)初始化该channel;然后将该channel注册到线程池eventLoopGroup中,实际为从线程池获取线程然后建立该channel和线程的绑定关系。以上注册操作为异步操作,返回ChannelFuture。该方法使用了模板设计模式,可变部分有init定义。

(3)initAndRegiter完成之后,后续的bind或connect均在该注册到的线程中进行处理。源码如下:

3. ServerBootStrap

ServerBootStrap为AbstractBootStrap的实现类,主要功能为接收客户端连接,处理已成功建立连接的客户端后续的请求。这两个功能类似于socket编程中的ServerSocket和Socket,即接收连接的channel为parent channel,而由他接收和建立连接生成的channel为child channel。为了拓展性,即提供区分对待这两种channel的拓展性,在ServerBootStrap中,定义了childHandler, childGroup, childOptions, childAttrs用于处理child channel。

核心逻辑为:init方法的实现和内部类ServerBootstrapAcceptor,该内部类是一个ChannelInBoundHandler,用于处理监听channel的事件,即处理客户端连接请求。

(1)init方法:源码核心逻辑如下:

即初始化为监听客户端请求的channel,其中添加了两个channelHandler,首先为其添加由用户初始化指定的channelHandler,然后在添加ServerBootStrapAcceptor,同时构造参数为child系列group,childHandler,options,attrs,因为child系列的,是为新创建的child channel服务。

(2)ServerBootstrapAcceptor:源码如下:

ServerBootstrapAcceptor为ChannelnBoundHandlerAdapter的实现类,在监听channel的pipeline中为第二个或第一个channelInBoundHandler,在监听channel有数据可读时,即有新的客户端连接到来时,调用channelRead方法处理。源码如下:

将msg转为channel(为什么可以知道是channel),为该channel设置child系列options,attrs等,然后将该child channel注册到childGroup,childGroup和监听channel可为同一个线程池,也可以是不同的两个线程池,由用户代码指定(即调用group(group)或group(parentGroup, childGroup))。childGroup为该child channel分配一个线程,该child channel的整个生命周期的IO事件均在这个线程中处理,而不会切换到其他线程,所以没有线程安全问题,不需要使用到线程同步。

4. BootStrap

BootStrap为定义客户端连接服务器逻辑,也是AbstractBootStrap类的实现类,由于连接服务端和接收服务端发送的数据为同一个channel,所以不需要额外定义child系列字段,但是客户端需要进行域名解析,故定义了AddressResolveGroup,用于进行域名解析。处于线程安全的考虑,每个eventLoop对应一个addressResolve。

核心方法为:connect和doResolveAndConnect0

doResolveAndConnect0核心逻辑为分为地址解析和connect服务端两步,均在该channel绑定的同一线程执行。

在地址解析为异步操作,返回Future。阻塞该future直到解析完成后,从该future获取remotAddress,则调用doConnect进行实际服务端的连接操作。核心源码如下:

广告 广告

评论区