1.Netty概念
- 异步事件驱动框架,用于快速开发高性能服务端和客户端
- 封装了JDK底层BIO和NIO模型,提供高度可用的API
- 自带编解码器解决拆包粘包问题,用户只用关心业务逻辑
- 精心设计的reactor线程模型支持高并发海量连接
- 自带各种协议栈让你处理任何一种通用协议都几乎不用亲自动手
- 各大开源项目选择Netty作为底层通信框架
2.Netty使用场景
- 高性能领域
- 多线程并发领域
- 异步通信领域
3.IO通信
(1)BIO通信
- 一个线程负责连接:一个独立的Acceptor线程负责监听客户端的连接,它接收到客户端的请求连接之后,为每个客户端创建一个新的线程进行链路处理,处理完成之后通过输出流应答给客户端,此时线程销毁。
- 一请求一应答通信模型。
- 缺陷:缺乏弹性伸缩能力。当客户端的并发访问量增加以后,服务端的线程个数和客户端的并发访问数呈1:1的正比关系,由于线程是java虚拟机非常宝贵的系统资源,当线程数膨胀之后,系统的性能将急剧下降,随着并发访问量的逐渐增大,系统将会发生线程堆栈溢出,创建新线程失败等问题,最终导致进程宕机或者僵死,不能对外提供服务。
- 当有N个客户端接入的时候,服务端用一个Acceptor线程监听,它在服务端创建N个线程来对客户端的请求进行处理(客户端的个数=服务端创建的线程个数)
(2)伪异步IO通信
- 线程池负责连接:当有新的客户端接入时,将客户端的socket封装成一个task投递到后端的线程池中进行处理。
- M请求N应答:JDK的线程池维护一个消息队列和N个活跃的线程,对消息队列中的任务进行相关的处理。当有M个客户端接入的时候,服务端将会创建一个具有N个线程的线程池来对客户端的请求进行处理。
- 线程池阻塞:由于线程池可以设置消息队列的大小和最大线程数,因此它的资源占用是可控的,无论多少个客户端并发访问,都不会导致资源的耗尽和宕机。不足之处就是当有大量的客户端接入时,随着并发访问量的不断增加,异步IO通信可能会造成线程池阻塞。
- 伪异步IO通信模型与BIO通信模型最大的区别:伪异步IO不再针对每一个客户端创建一个独立的线程,而是由一个线程池统一处理所有客户端的接入。
(3)NIO通信(重点)
- 缓冲区Buffer:它是一个对象,包含一些要写入或读出的数据,在NIO类库中加入Buffer对象体现了新库与原IO的一个重要区别,在面向流的IO中可以将数据直接写入或者将数据直接读到Stream对象中,在NIO库中所有数据都是用缓冲区处理的,在读取数据时,它直接读到缓冲区中;在写入数据时,也是写入到缓冲区中。任何时候访问NIO中的数据都是通过缓冲区进行操作。
- 通道Channel:它是一个通道,像是自来水管,网络数据通过Channel读取和写入,通道与流的不同之处在于通道是双向的,流只是在一个方向上移动,一个流必须是InputStream或者OutputStream的子类, 而通道可以用于读写或者二者同时进行。
- 多路复用器Selector:它是javaNIO编程的基础,它提供了选择已经就绪的任务的能力,Selector会不断地轮询出Channel,如果某个Channel上发生读或者写事件,这个Channel就处于就绪状态,会被Selector轮询出来,然后通过SelectionKey可以获取就绪Channel的集合进行后续的IO操作,由于JDK使用了epoll代替了传统select的实现,所以它没有最大连接数的限制,可以接入成千上万的客户端,在IO通信领域是一个巨大的进步。
(4)AIO通信
- 连接注册读写事件和回调函数
- 读写方法异步
- 主动通知程序AIO异步通道提供了两种方式获取操作结果。(1)通过Java.util.concurrent.Future类来表示异步操作的结果; (2)在执行异步操作的时候传入一个Java.nio.channels. CompletionHandler接口的实现类作为操作完成的回调。 AIO的异步套接字通道是真正的异步非阻塞IO,对应于UNIX网络编程中的事件驱动IO(AIO),它不需要通过多路复用器(Selector)对注册的通道进行轮询操作即可实现异步读写,从而简化了NIO的编程模型。
(5)四种IO对比
4.NIO与Netty
(1)原生NIO的缺陷
- 类库和API繁杂
- 入门门槛高
- 工作量和难度大
- JDK NIO存在Bug
(2)Netty的优势
- API简单
- 入门门槛低
- 性能高
- 成熟稳定
5.WebSocket
(1)WebSocket概念
- H5协议规范
- 握手机制:客户端和服务器可以建立一个类似TCP的连接,从而方便客户端和服务器之间的通信。在WebSocket出现之前,Web交互基于http之间的短连接或者长连接。
- 解决客户端与服务端实时通信而产生的技术。WebSocket协议本质上是基于TCP的协议,是先通过http https协议发起一条特殊的http请求,进行握手后创建一个用于交换数据的TCP连接,此后服务端和客户端通过此TCP连接进行实时通信。注意,当WebSocket的客户端与服务器端进行通信以后,此时就不再需要之前进行握手请求的http协议的参与了。
(2)WebSocket优点
- 节省通信开销。以前的WebServer实现推送技术或者即时通讯用的都是轮询,在特定的时间间隔比如1s,由浏览器自动发起请求,将服务器的消息主动拉回来,在这种情况下,我们需要不断地向服务器发送请求,然而http的request的header是非常长的,里面包含的数据可能只是一个很小的值,这样会占用很多的带宽和服务器资源。
- 服务器主动传送数据给客户端。WebSocket可以使服务器和客户端在给定的时间范围内任意时刻相互推送信息,浏览器和服务器只需要做一个握手的动作,在建立连接之后,服务器可以主动传送数据给客户端,客户端也可以随时向服务器发送数据,此外服务器和客户端直接交换的标头信息也是非常小的。
- 实时通信。WebSocket不仅限以Adjax方式进行通信,因为Adjax技术需要客户端发起请求,而WebSocket服务器和客户端可以彼此相互推送信息,从而实现实时通信。
(3)WebSocket建立连接
- 客户端发起握手请求
- 服务端响应请求
- 连接建立
(4)WebSocket生命周期
打开事件:@OnOpen 此事件发生在端点上建立新连接时并且在任何其他事件发生之前
消息事件:@OnMessage 此事件接收WebSocket对话中另一端发送的消息。
错误事件:@OnError 此事件在WebSocket连接或者端点发生错误时产生
关闭事件:@OnClose 此事件表示WebSocket端点的连接目前部分地关闭,它可以由参与连接的任意一个端点发出
(5)WebSocket关闭连接
- 服务器关闭底层TCP连接
- 客户端发起TCP Close