# Netty
## 一、初步
+ 异步非阻塞
+ Future-Listener机制,方便用户主动获取或者通知机制获得IO操作结果
+ 底层数据传输封装完善
+ 功能依赖 1.7+
## 二、实现
### Server
+ 创建两个线程组,一个接收,一个网络读写
+ 创建辅助工具类 `ServerBootStrap`,用于服务器通道的配置
+ `NioServerSocketChannel` 设置NIO模式
+ `ChannelOption.SO_BACKLOG` 设置 TCP 缓冲区
+ `ChannelOption.SO_SNDBUF` 设置发送缓存
+ `ChannelOption.SO_RCVBUF` 设置接收缓存
+ `ChannelOption.SO_KEEPALIVE` 保持连接
+ `ChildHandler` 真正连接时的通道
+ 数据绑定, `b.bind(8765).sync()`
+ 等待关闭, `cf1.channel().closeFuture().sync()`
+ 线程组关闭 `Close`
------
### Client
+ 创建一个线程组
+ 创建辅助类
+ 数据绑定
+ 创建通道
+ `Handler` 真正连接的通道
+ 进行绑定
+ 等待关闭
------
### 数据传输
1. 客户端发送数据并刷新数据: `cf1.channel().writeAndFlush(Unpooled.copiedBuffer(‘777‘.getBytes()));`
2. 数据处理完成以后及时清理:`ReferenceCountUtil.release(msg);`
3. 一般回写都用 `writeAndFlush` 要不然会很多内容一次发送,表现为一行
4. 在 Serverhandler 端中,增加一个监听器: `addListener(ChannelFutureListener.CLOSE);` 这会使在 Client 端通信完毕以后自动关闭,不会再存活。
5. 端口同时绑定多个端口,但是处理时使用同一个处理器,所以对于 Client 返回的数据是相同的
## 三、生产应用
### 部署
1. 生成一个maven项目,确保 jar 发布
2. 使用 Maven 打包,依赖 Maven-jar-plugin ,
3. Maven 打包,依赖插件配置在 `PluginManagement` 中
4. 在MANIFEST.MF 中有一个 Class-Main
![snipaste_20170808_220210](C:\Users\HoldDie\Desktop\snipaste_20170808_220210.png)
## 四、TCP 拆包、粘包
### 产生原因:
1. 应用程序 write 写入的字节大小大于套接口发送缓冲区的大小
2. 进行 MSS 大小的TCP分段
3. 以太网帧的 payload 大于 MTU 进行 IP 分片
当Client同时使用WriteAndFlush三次,Server端会当成一次请求。
### 解决方法:
1. 消息定长 `FixedLengthFrameDecoder` 定长
1. sc.pipeline().addLast(new FixedLengthFrameDecoder(5));
2. sc.pipeline().addLast(new StringDecoder());
3. sc.pipeline().addLast(new ServerHandler());
2. 在包的尾部加特殊字符进行分割 ``
1. ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());
2. sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf));
3. sc.pipeline().addLast(new StringDecoder());
4. sc.pipeline().addLast(new ServerHandler());
3. 消息分为消息头,消息体,
## 五、补充
### Java 序列化存在问题:
1. Java 序列化机制是 Java 内部的一种对象编解码技术,无法跨语言使用:对于异构系统之间的对接,Java 序列化后的码流需要能够通过其他语言反序列化成原始对象(副本),目前很难支持
2. 相比于其它开源的序列化框架,Java 序列化后的码流太大,无论是网络传输还是持久化到磁盘,都会导致额外的资源占用。
3. 序列化性能差(CPU资源占用高)
### 高性能(RPC)三个要素:
1. 传输:BIO、NIO、AIO,IO模型在很大程度上决定了框架的性能
2. 协议:采用什么样的通信协议,HTTP或者内部私有协议。
3. 线程:都区之后的编解码在哪个线程进行,编解码后的消息如何转发,Reactor线程模型的不同,对性能的影响也非常大。