# Netty-study
**Repository Path**: debugzt/netty-study
## Basic Information
- **Project Name**: Netty-study
- **Description**: 记录学习netty过程中的代码实现(包括传统bio、nio以及netty)
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 0
- **Created**: 2021-09-09
- **Last Updated**: 2022-01-24
## Categories & Tags
**Categories**: Uncategorized
**Tags**: 学习
## README
# 为什么学习netty
Netty是一个高性能、异步事件驱动的NIO框架,基于JAVA NIO提供的API实现。Netty提供异步的、[事件驱动](https://baike.baidu.com/item/事件驱动/9597519)的网络应用程序框架和工具,**用以快速开发高性能、高可靠性的[网络服务器](https://baike.baidu.com/item/网络服务器/99096)和客户端程序。**
参考:https://blog.csdn.net/bjweimengshu/article/details/78786315
# **netty高性能的原因**
## 基于主从Reactors多线程模型
reactor线程模型有三种:
### **Reactor单线程模型**
只有一个线程处理所有的【连接请求】、【接收消息】、【发送消息】等IO操作(缺点明显)
### **Reactor多线程模型**
与单线程模型不同点在于:使用线程池来处理【连接请求】、【接收消息】、【发送消息】等IO操作,提高并发能力。但是,在一些特殊的应用场景下,单独的一个Acceptor线程可能会存在性能不足的问题。
### **主从Reactor多线程模型**
与第二种多线程模型相比,将Reactor分为两部分:
1.mainReactor负责监听server socket,accept新连接;并将建立的socket分派给subReactor;
2.subReactor负责多路分离已连接的socket,读写网络数据,对业务处理功能,其扔给worker线程池完成。
## 同步非阻塞通信
**Netty 的IO 线程NioEventLoop 聚合了多路复用器Selector**,可以同时并发处理成百上千个客户端Channel,由于读写操作都是非阻塞的,这就可以充分提升IO 线程的运行效率,避免由于频繁IO 阻塞导致的线程挂起,(Netty对应操作系统层面的IO模型应是IO多路复用的epoll)。
服务端通信序列图:

客户端通信序列图:

另外,由于**Netty采用了异步通信模式**(事件驱动),一个IO 线程可以并发处理N 个客户端连接和读写操作,这从根本上解决了传统同步阻塞IO 一连接一线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。
## 零拷贝(Zero copy)
Netty 的“零拷贝”主要体现在如下三个方面:
- Netty 的接收和发送ByteBuffer 采用DIRECT BUFFERS,使用堆外直接内存进行Socket 读写,不需要进行字节缓冲区的二次拷贝。如果使用传统的堆内存(HEAP BUFFERS)进行Socket 读写,JVM 会将堆内存Buffer 拷贝一份到直接内存中,然后才写入Socket 中。**相比于堆外直接内存,多了将数据从操作系统内核缓冲区拷贝到用户缓冲区这个过程**。
- Netty 提供了组合Buffer 对象,可以聚合多个ByteBuffer 对象,用户可以像操作一个Buffer 那样方便的对组合Buffer进行操作,避免了传统通过内存拷贝的方式将几个小Buffer 合并成一个大的Buffer。
- Netty 的文件传输采用了**transferTo()**方法,它可以直接将文件缓冲区的数据发送到目标Channel,避免了传统通过循环write()方式导致的内存拷贝问题。对于很多操作系统它直接将文件缓冲区的内容发送到目标Channel 中,而不需要通过拷贝的方式,这是一种更加高效的传输方式,它实现了文件传输的“零拷贝”
零拷贝原理参考:https://zhuanlan.zhihu.com/p/258513662
## 内存池
## 无锁化的串行设计理念
参考:https://www.cnblogs.com/wuzhenzhao/p/11202952.html
https://blog.csdn.net/mazhongjia/article/details/108417761
# 对netty组件的一些理解
netty的核心组件包括bootstrap、channel、eventLoopGroup、channelHandler、channelPipeline
## (1)bootstrap
分为服务器端的ServerBootstrap和客户端的bootstrap,是整个程序的启动引导类,用于配置整个netty程序,串联各个组件
## (2)channel
可理解为通道,即服务器端在和客户端连接之后会生成channel,分为服务器端的NioServerSocketChannel和客户端的SocketChannel(可理解为
传统BIO当中的ServerSocket和socket)。用于提供网络IO操作
## (3)eventLoopGroup & eventLoop
eventLoop:每个eventLoopGroup当中有若干个eventLoop同时工作,每个eventLoop维护着一个selector选择器\
eventLoopGroup:可理解为线程组,一般服务器端会有两个group:bossGroup和workerGroup,连接过程如下:

**1.bossGroup当中的eventLoop不断轮询selector 用来查看是否有新连接产生;-->
2.一旦有新连接产生那么会为其生成一个SocketChannel,并注册到workerGroup当中的eventLoop中的selector上;-->
3.每一个生成的channel都会关联上一个pipeline,用于处理channel的入站和出站操作;-->
4.workerGroup当中的eventLoop轮询selector查询这些注册的channel是否有已就绪的IO事件发生,若有则调用pipeline当中的handler进行操作**
## (4)channelHandler & channelPipeline
channelHandler:handler类 用来处理IO事件或是拦截IO操作,(比如在有数据可读时、数据读取完毕时)执行相应的操作
channelPipeline:一个channel有且仅有一个channelPipeline与之对应,channelPipeline当中维护着一个由channelHandlerContext组成的双向链表,
每个channelHandlerContext中又关联着一个channelHandler
**!!channelHandler实际上就是一个事件回调函数,程序员并不会主动的去调用这些方法,而是当某些事件发生时自动触发这些方法;
!!因为一个channelPipeline当中是一个有很多个channelHandler的双向链表,所以当事件发生时,会按链表的顺序执行到这些handler当中的方法
(一个handler执行完,会将其转发到pipeline中的下一个handler)**
# 基于netty+zookeeper实现rpc框架
## 1.关键技术
- 服务发布与订阅:服务端使用Zookeeper注册服务地址,客户端从Zookeeper获取可用的服务地址。
- 通信:使用Netty作为通信框架
- Spring:使用Spring配置服务,加载Bean,扫描注解。
- 动态代理:客户端使用代理模式透明化服务调用。
- 消息编解码(序列化):使用Protostuff序列化和反序列化消息
## 2.核心流程
1. 生产者server:加载服务接口,并缓存;服务注册,将服务接口以及服务主机信息写入注册中心(本例使用的是 zookeeper),启动网络服务器并监听。消费方(client)调用以本地调用方式调用服务;
2. client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;代理服务接口生成代理对象,服务发现(连接 zookeeper,拿到服务地址列表,通过客户端负载策略获取合适的服务地址)。
3. client stub找到服务地址,并将消息发送到服务端;
4. server stub收到消息后进行解码;
5. server stub根据解码结果调用本地的服务;
6. 本地服务执行并将结果返回给server stub;
7. server stub将返回结果打包成消息并发送至消费方;
8. client stub接收到消息,并进行解码;
9. 服务消费方得到最终结果。
## 3.学习路线
详情见另一个仓库:
一款基于 Netty+Kyro+Zookeeper 实现的自定义 RPC 框架(fork from [SnailClimb](https://gitee.com/SnailClimb) / [guide-rpc-framework](https://gitee.com/SnailClimb/guide-rpc-framework))
guide-rpc-framework:https://gitee.com/debugzt/guide-rpc-framework