Netty架构设计

949 阅读3分钟

这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战

前言

Netty.png

Netty作为异步事件驱动的网络,高性能之处主要来自于其I/O模型和线程处理模型,前者决定如何收发数据,后者决定如何处理数据。前面了解了一下Netty相关的基础知识,我们从Netty整体架构设计去了解一下,Netty的功能设计初衷。

我们主要从Netty功能特性、模块组件、运作过程来了解Netty的架构设计

功能特性

image.png

  • 传输服务 支持BIO和NIO
  • 容器集成 支持OSGI、JBossMC、Spring、Guice容器
  • 协议支持 HTTP、Protobuf、二进制、文本、WebSocket等一系列常见协议都支持。 还支持通过实行编码解码逻辑来实现自定义协议
  • Core核心 可扩展事件模型、通用通信API、支持零拷贝的ByteBuf缓冲对象

模块组件

这边就不介绍了后面梳理源码的时候在介绍。

工作基本原理

介绍服务端Netty的工作架构图: image.png

1. 服务端

public static void main(String[] args) throws Exception {
    //创建两个线程组bossGroup和workerGroup, 含有的子线程NioEventLoop的个数默认为cpu核数的两倍
    // bossGroup只是处理连接请求 ,真正的和客户端业务处理,会交给workerGroup完成
    EventLoopGroup bossGroup = new NioEventLoopGroup(10);
    EventLoopGroup workerGroup = new NioEventLoopGroup(100000);
    try {
        //创建服务器端的启动对象
        ServerBootstrap bootstrap = new ServerBootstrap();
        //使用链式编程来配置参数
        bootstrap.group(bossGroup, workerGroup) //设置两个线程组
                .channel(NioServerSocketChannel.class) //使用NioServerSocketChannel作为服务器的通道实现
                // 初始化服务器连接队列大小,服务端处理客户端连接请求是顺序处理的,所以同一时间只能处理一个客户端连接。
                // 多个客户端同时来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理
                .option(ChannelOption.SO_BACKLOG, 1024)
                .childHandler(new ChannelInitializer<SocketChannel>() {//创建通道初始化对象,设置初始化参数

                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        //对workerGroup的SocketChannel设置处理器
                        ch.pipeline().addLast(new NettyServerHandler());
                    }
                });
        System.out.println("netty server start。。");
        //绑定一个端口并且同步, 生成了一个ChannelFuture异步对象,通过isDone()等方法可以判断异步事件的执行情况
        //启动服务器(并绑定端口),bind是异步操作,sync方法是等待异步操作执行完毕
        ChannelFuture cf = bootstrap.bind(9000).sync();
        //给cf注册监听器,监听我们关心的事件
        // 通过sync方法同步等待通道关闭处理完毕,这里会阻塞等待通道关闭完成
        cf.channel().closeFuture().sync();
    } finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}

2. 客户端

public static void main(String[] args) throws Exception {
    //客户端需要一个事件循环组
    EventLoopGroup group = new NioEventLoopGroup();
    try {
        //创建客户端启动对象
        //注意客户端使用的不是ServerBootstrap而是Bootstrap
        Bootstrap bootstrap = new Bootstrap();
        //设置相关参数
        bootstrap.group(group) //设置线程组
                .channel(NioSocketChannel.class) // 使用NioSocketChannel作为客户端的通道实现
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        //加入处理器
                        ch.pipeline().addLast(new NettyClientHandler());
                    }
                });

        System.out.println("netty client start。。");
        //启动客户端去连接服务器端
        ChannelFuture cf = bootstrap.connect("127.0.0.1", 9000).sync();
        //对通道关闭进行监听
        cf.channel().closeFuture().sync();
    } finally {
        group.shutdownGracefully();
    }
}