0%

SourceAnalysis-Netty-Component

阅读更多

1 源码Maven坐标

1
2
3
4
5
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.17.Final</version>
</dependency>

2 Echo Server示例

Handler代码清单如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package org.liuyehcf.protocol.echo;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
* Created by HCF on 2017/12/2.
*/
public class EchoServerHandler extends ChannelInboundHandlerAdapter { //(1)

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) { //(2)
ctx.write(msg); //(1)
ctx.flush(); //(2)
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { //(4)
//Close the connection when an exception is raised.
cause.printStackTrace();
ctx.close();
}
}

Server代码清单如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package org.liuyehcf.protocol.echo;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
* Created by HCF on 2017/12/2.
*/
public class EchoServer {
private int port;

public EchoServer(int port) {
this.port = port;
}

public void run() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(); //(1)
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap(); //(2)
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class) //(3)
.childHandler(new ChannelInitializer<SocketChannel>() { //(4)
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new EchoServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128) //(5)
.childOption(ChannelOption.SO_KEEPALIVE, true); //(6)

//Bind and start to accept incoming connections.
ChannelFuture f = b.bind(port).sync(); //(7)

//Wait until the server socket is closed.
//In this example, this does not happen, but you can do that to gracefully
//shut down your server.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}

public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new EchoServer(port).run();
}
}

从示例代码中,我们找出几个核心的类型

  1. ServerBootstrap
  2. NioEventLoopGroup
  3. NioServerSocketChannel
  4. ChannelInitializer

3 ServerBootstrap

由于Netty启动涉及到很多复杂的步骤,因此提供了一个辅助类ServerBootstrap来帮助用户启动Netty,由于可配置参数种类繁多,为了保持较好的可伸缩性以及可扩展性,ServerBootstrap采用了建造者模式

ServerBootstrap的继承关系如下

ServerBootstrap

其中ServerBootstrap包含如下字段

  1. Map<ChannelOption<?>, Object> childOptions:一个Map
  2. Map<AttributeKey<?>, Object> childAttrs:一个Map
  3. ServerBootstrapConfig config:该字段用于获取ServerBootstrap的各项参数
  4. EventLoopGroup childGroup
  5. ChannelHandler childHandler

这里涉及到两个概念,parent以及child

  • parent:用于accept连接的那些组件
  • child:用于客户端连接的那些组件

3.1 ServerBootstrapConfig

ServerBootstrapConfig用于获取ServerBootstrap的各项参数,即使ServerBootstrap的功能趋于单一

ServerBootstrapConfig的继承结构图如下

ServerBootstrapConfig

  • AbstractBootstrapConfig
    • 用于返回AbstractBootstrap的各项参数
  • ServerBootstrapConfig
    • 用于返回ServerBootstrap相比于AbstractBootstrap所额外提供的参数(child相关的参数)

4 NioEventLoopGroup

NioEventLoopGroup管理了一组线程池,而其本身又可以被抽象成一个线程池,对NioEventLoopGroup执行的操作会通过相应策略,从其管理的线程池组中选择一个线程池进行执行

NioEventLoopGroup的继承结构图如下

NioEventLoopGroup

  • EventExecutorGroup
    • 管理了一组Executor(一个Executor可以理解为一个线程池)
    • 另一方面,由于EventExecutorGroup接口间接继承自ExecutorService接口,因此EventExecutorGroup也可以看成是一个Executor,这是比较奇特的一个地方
    • 提供了一个重要的方法next
  • EventLoopGroup
    • EventExecutorGroup基础之上,提供了异步的register方法
  • AbstractEventExecutorGroup
    • 为那些从JDK接口中继承而来的方法提供基础实现,就是调用next()方法然后调用对应的方法
    • next()方法依据不同策略从管理的所有Executor中选出下一个
  • MultithreadEventExecutorGroup
    • 该类主要作用就是进行一些关键的初始化动作
    • 该类定义了关键字段children(EventExecutor数组)以及chooser(依据children的大小选择不同的next的策略)
  • MultithreadEventLoopGroup
    • EventLoopGroup接口提供的方法提供基础实现

4.1 NioEventLoop

NioEventLoop本质上就是一个线程池,被NioEventLoopGroup管理

NioEventLoop的继承结构图如下

NioEventLoop

  • EventExecutor
    • 增加了几个新的方法,包括parentinEventLoop、以及创建Future和Promise的方法
  • AbstractEventExecutor
    • EventExecutor接口以及EventLoopGroup接口提供的方法提供基础实现
  • AbstractScheduledEventExecutor
    • ScheduledExecutorService接口提供的方法提供基础实现
  • OrderedEventExecutor
    • 空接口
  • EventLoop
    • 修改parent方法的返回值
  • SingleThreadEventExecutor
    • 实现了线程池的主要逻辑
  • SingleThreadEventLoop
    • 综合两条继承链路
    • EventLoopGroup接口提供的方法提供基础实现

5 ChannelInitializer

ChannelInitializer的继承结构图如下

ChannelInitializer

  • ChannelHandler
    • 提供了添加和移除Handler的方法
  • ChannelHandlerAdapter
    • ChannelHandler接口提供基本的“骨架”实现
  • ChannelInboundHandler
    • 在channel状态改变时插入相应的hook method,用于回调
  • ChannelInboundHandlerAdapter
    • ChannelInboundHandler接口提供的方法提供基础实现,以便让用户自行选择是否覆盖某个hook method

6 DefaultChannelPipeline

DefaultChannelPipeline继承结构图如下

DefaultChannelPipeline

  • ChannelInboundInvoker
    • 将接收数据这一个过程抽象出多个生命周期,用于用户自定义处理逻辑
  • ChannelOutboundInvoker
    • 将发送数据这一个过程抽象出多个生命周期,用于用户自定义处理逻辑
  • ChannelPipeline
    • ChannelInboundInvokerChannelOutboundInvoker进行合并
    • 添加了一系列add以及remove方法用于添加handler

那么这些生命周期由谁触发呢?大部分IO的底层操作由AbstractChannel完成,因此这些生命周期会在这些底层操作之中显式触发。这些触发的操作大致由AbstractChannelHandlerContextDefaultChannelPipeline以及AbstractChannel协作完成,在此先不深究细节

7 NioServerSocketChannel

NioServerSocketChannel继承结构图如下

NioServerSocketChannel

  • AttributeMap
    • 用于存放属性值的Map
  • DefaultAttributeMap
    • AttributeMap接口提供基础实现
  • Channel
    • 定义Netty中Channel的一系列方法
    • 此外,还定义了Unsafe接口(不是sun实现中的Unsafe)
  • AbstractChannel
    • Channel接口提供基础实现
    • 基本上所有底层的IO操作都在这个类中实现
  • AbstractNioChannel
    • Netty中底层的NIO操作,都在这个类中实现,包括Selector等
  • AbstractNioMessageChannel
    • 相比于AbstractNioChannelAbstractNioMessageChannel提供更高一层的抽象,提供可以处理Message的抽象方法
  • ServerChannel
    • 空接口,仅用于标记
  • ServerSocketChannel
    • 定义用于监听连接的ServerChannel

8 DefaultChannelPromise

DefaultChannelPromise继承结构图如下

DefaultChannelPromise

  • Future
    • 该Future继承自JUC中的同名Future接口
    • 增加了添加和删除监听器的方法,以及sync方法和await方法等
  • AbstractFuture
    • 为JUC中的Future接口的get方法提供基础实现
  • Promise
    • 增加了setSuccess/setFailuretrySuccess/tryFailure等方法
  • ChannelFuture
    • 增加了返回Channel的方法,以及判断是否为Void型的channel的方法
  • ChannelPromise
    • 结合了ChannelFuture以及Promise接口
  • DefaultPromise
    • Promise以及Future接口提供了基础实现
  • DefaultChannelPromise
    • ChannelPromise接口提供默认实现

9 SocketUtils

该类封装了一系列底层Java NIO API的基本操作