netty-server端学习总结

本文详细介绍了Netty基于NIO的服务器端实现,包括REACTOR模型、零拷贝技术及其在Netty中的应用。Netty简化了NIO的处理逻辑,使用多响应器模型提高并发性能。通过ServerBootstrap配置线程池、处理器链路,实现服务启动和绑定。通过事件驱动和NIO的selector处理accept和read事件,高效地管理通道。
摘要由CSDN通过智能技术生成

NIO基础概念

REACTOR 模型

reactor 模型是基于事件驱动的, 它将不同的事件分配给不同的处理器执行.
Multiple reactors
Multiple reactors

  1. reactor 模型中的事件驱动, 是基于 i/o 多路复用机制实现的. 1 2
  2. selector, nio 中的多路复用器, 负责注册、处理事件.
  3. netty中, 基于 Multiple reactors , 即多响应器模型. 部分 reactor 只负责响应连接事件, 其它负责响应处理读写事件.

零拷贝

零拷贝技术减少了文件、socket 数据的读写过程, 这里只讨论 nio 中, 对零拷贝对使用.
linux 中的零拷贝的实现主要通过 mmap 与 sendfile 两种方式, mmap 简单说就是将内核态中的数据地址, 直接映射到用户态中, 从而用户可以跳过数据从内核态复制到用户态的过程, 而直接操作. sendfile 相较于 mmap 更进一步精简了功能, 它没有对数据地址进行映射, 通过这种方式, 只能将读取的数据存储到磁盘或soket发送出去, 性能进一步提升, 但也不能操作数据.

  1. nio 中, 使用直接内存实现 mmap 的零拷贝方式, MappedByteBuffer/DirectByteBuffer, DirectByteBuffer 是 MappedByteBuffer (abstract) 的子类, MappedByteBuffer 提供了它的实例方法 (直接内存不使用在JVM中申请的内存, 它只有在 full gc 时, 才会被清理. 使用直接内存, 一般会创建一个内存池, 用来重复使用).
  2. nio 中, FileChannel.transferTo()/transferFrom 都使用了 sendfile 的方式.

NETTY

netty 在 nio 的基础上进行了封装, 简化了 nio 复杂的处理逻辑与异常捕捉. 依据 multi reactors 模型, netty 的连接并发理论上可以做到极大(超出网络带宽的限制).

netty模版代码

public static void main(String[] args) throws InterruptedException {
   
            EventLoopGroup master = new NioEventLoopGroup(1);
            EventLoopGroup works = new NioEventLoopGroup();
        try {
   
            ServerBootstrap server = new ServerBootstrap();

            server.group(master,works)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG,1024)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
   
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
   
                            socketChannel.pipeline().addLast(new Encode());
                            socketChannel.pipeline().addLast(new Decode());
                            socketChannel.pipeline().addLast(new ServerChannelHandler());
                        }
                    });
            ChannelFuture sync = server.bind(12321).sync();
            sync.channel().closeFuture().sync();
        }finally {
   
            master.shutdownGracefully();
            master.shutdownGracefully();
        }
    }

netty 的服务代码非常简单. 下面是流程的概述:

  1. 首先创建两个线程池(NioEventLoopGroup, 参数为线程数量, 默认为两倍核数), 它们分别用来处理 accept 事件和 read 事件. 用来处理 accept 事件的线程池, 如果没有多个不同端口的 ServerSocketChannel 需要处理, 参数配置为 1 即可.
  2. 新建一个引导对象(ServerBootstrap). 将第一步创建的两个线程池作为参数传给它. option 方法用来添加网络编程的相关参数, childHandler 中添加通道处理器, 这些处理器是有方向的, read/write 分别对应实现了 channelInboundHandler/channelOutboundHandler 接口的处理器. 方向正确的处理器才会被调用. 通道中的所有处理器, 采用责任链统一处理.
  3. 所有参数添加完成后, 调用 server 的 bind() 方法, 这里会调用 nio 中 selector 的 select 方法, 服务开始正式运行. sync 方法, 会同步 bind 方法, 保证继续执行代码时, 绑定已经成功. closeFuture 方法是一个回调方法, 当 serverSocketChannel 关闭时, 才会被调用, 其后的 sync 同步方法, 将在它被正式调用前, 阻塞线程.
  4. netty 工作流程图
    在这里插入图片描述

源码流程

  1. 创建 NioEventLoopGroup对象.
	// nioeventLoopGroup 新建对象(无参), 最终会进入这个方法.
	//  nThread 是 0, executor 是 null, 
	// selectorProvider 是 nio 方法 SelectorProvider.provider() 创建的. 
	// selectStrategyFactory 是一个自定义的策略工厂 创建方法: DefaultSelectStrategyFactory.INSTANCE . 
	// RejectedExecutionHandlers.reject() 是线程池的拒绝策略, 它会简单的抛出异常
	public NioEventLoopGroup(int nThreads, Executor executor, SelectorProvider selectorProvider, SelectStrategyFactory selectStrategyFactory) {
   
		super(nThreads, executor, new Object[]{
   selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject()});
    }
	// 当 nThreads 为 0 时, 会使用 DEFAULT_EVENT_LOOP_THREADS, 它的值等于两倍核数
	protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
   
        super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
    }
	// 多线程事件执行组对象创建方法
	protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                            EventExecutorChooserFactory chooserFactory, Object... args) {
   
        if (nThreads <= 0) {
   
            throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
        }
		// 这里创建了执行器, 它主要负责创建新线程, 并对新的线程进行了一系列的复制, 添加组 等操作
        if (executor == null) {
   
            executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
        }
		// 这里根据 参数确定线程池的线程数量.每一个EventExecutor也是一个“线程池”,不过它只有一个线程
        children = new EventExecutor[nThreads];
		// 为每一个事件执行器实例化对象
        for (int i = 0; i < nThreads; i ++) {
   
            boolean success = false;
            try {
   
            	// 类似线程池中的 worker 对象, 但有些不同. 任务队列不在group中统一维护, 而是将任务直接交给child,child中维护了一个queue,用来存储无法及时处理但任务.
            	// newChild 方法有多个实现, 这里是 NioEventLoopGroup 的实现. 如果确认服务器支持 epoll, 可以使用 EpollEventLoopGroup
                children[i] = newChild(executor, args);
                success = true;
            } catch (Exception e) {
   
                // TODO: Think about if this is a good exception type
                throw new IllegalStateException("failed to create a child event loop", e);
            } finally {
   
                if (!success) {
   
                	... // 略
                }
            }
        }
	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Netty-socketio是一个用于构建实时通信应用程序的开源框架。它基于Netty框架,通过使用WebSocket协议来实现异步、高性能的网络通信。Netty-socketio具有以下特点: 1. 强大的异步处理能力:Netty-socketio采用事件驱动的方式处理客户请求,能够高效地处理大量并发连接。 2. 完善的消息传递机制:Netty-socketio提供了灵活的消息传递方式,支持广播、点对点、房间等不同的消息发送方式,满足不同场景下的通信需求。 3. 多协议支持:Netty-socketio不仅支持WebSocket协议,还支持其他常用的协议,如TCP、HTTP等,便于与现有的系统集成。 4. 可扩展性强:Netty-socketio提供了丰富的拓展接口,用户可以根据自己的需求定制和扩展框架的功能。 5. 易于使用:Netty-socketio提供了简洁的API和丰富的文档,可以快速上手使用,并提供了相应的示例代码,方便开发者学习和理解。 对于客服应用来说,Netty-socketio作为一个实时通信框架,可以用于构建在线客服聊天系统。通过使用Netty-socketio,我们可以实现客户与客服人员之间的实时消息传递,支持文字、图片、文件等多种类型的消息。客户可以通过网页或移动应用与客服人员进行沟通,实时解决问题,提升用户体验。 Netty-socketio提供了强大的异步处理能力和全双工通信机制,能够处理大量并发连接,并保持连接的稳定性和可靠性。同时,它的多协议支持和可扩展性强的特点,使得我们可以根据自己的业务需求进行定制和拓展,满足不同客服场景下的通信需求。 总之,Netty-socketio作为一个强大的实时通信框架,为客服应用提供了一种高效、稳定的解决方案,帮助企业构建更好的客服系统,并提升客户的满意度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值