Netty学习

一、原理
高性能、异步事件驱动的NIO框架,基于JAVA NIO提供的API实现,它提供了对TCP、UDP和文件传输的支持,作为一个异步的NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listene机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果。

二、高性能
IO多路复用技术,系统不需要创建新的额外进程或者线程,也不需要维护这些进程和线程的运行,降低了系统的维护工作量,节省了系统资源。与Socket类和ServerSocket类相对应,NIO提供了SocketChannel和ServerSocketChannel两种不同的套接字通道实现。
Netty架构按照Reactor模式设计和实现
客户端通信步骤如下:
1、打开sockeChannel
2、设置socketchannel为非阻塞模式,同时设置TCP参数
3、异步连接服务端
4、判断连接结果,如果连接成功,调到步骤10,否则执行步骤5
5、向Reactor线程的多路复用器注册OP CONNECT事件
6、创建Selector,启动线程
7、Selector轮询就绪的key
8、handerConnect()
9、判断连接完成,完成执行步骤10
10、向多路复用器注册读事件OP_READ
11、handleRead()异步读请求消息到ByteBuffer
12、decode请求消息
13、异步写ByteBuffer到SocketChannel
服务端通信步骤如下:
1、打开ServerSocketChanner
2、绑定监听地址InetSocketAddress
3、创建Selector,启动线程
4、将ServerSocketChannel注册到Selector,监听SelecteKey,OP_ACCEPT
5、Selector轮询就绪的key
6、handleAccept()处理新的客户端接入
7、设置新建客户连接的Socket
8、向Selector注册监听读操作SelectorKey.OP_READ
9、handleRead()异步读请求消息到ByteBuffer
10、decode请求消息
11、异步写ByteBuffer到SocketChannel
IO线程NioEventLoop由于聚合了多路复用器Selector,可以同时并发处理成百上千个客户端Channel,由于读写操作都是非阻塞的,这就可以充分提升IO线程的运行效率,避免由于频繁IO阻塞导致的线程挂起

异步通信NIO
由于Netty采用异步通信模式,一个IO线程可以并发处理N个客户端连接和读写操作,从根本上解决了传统同步阻塞IO一连接一阻塞模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升

零拷贝
Netty的接收和发送ByteBuffer采用DIRECT BUFFERS,使用堆外直接内存进行Socket读写,不需要进行字节缓存区的二次拷贝。
Netty提供了组合的Buffer对象,可以聚合多个ByteBuffer对象,用户可以像操作一个Buffer那样方便的对组合Buffer进行操作,避免了传统通过内存拷贝的方式将几个小buffer合并成一个大的Buffer
Netty的文件传输采用了transferTo方法,可以直接将文件缓冲区的数据发送到目标Channel,避免了传统通过循环write方式导致的内存拷贝问题

内存池
对于堆外直接内存的分配和回收,是一件耗时的操作,为了尽量重用缓冲区,Netty提供了基于内存池的缓冲区重用机制。

高效的Reactor线程模型
单线程模型
所有的IO操作都在同一个NIO线程上面完成
作为NIO服务端,接收客户端的TCP连接
作为NIO客户端,向服务端发起TCP连接
读取通信对端的请求或者应答消息
向通信对端发送消息请求或者应答消息

多线程模型
NIO线程 acceptor线程用监听服务端,接收客户端的TCP连接请求,网络IO操作读写等由一个NIO线程池负责,线程池可以采用标准的JDK线程池实现,它包含了一个任务队列和N个可用的线程,由这些NIO线程负责消息的读取、解码、编码和发送

主从多线程模型
acceptor线程池仅仅只用于客户端的登录、握手和安全认证,一旦链路建立成功,就将链路注册到后端subReactor线程池的IO线程上,由IO线程负责后续的IO操作。
无锁设计、线程绑定:Netty采用了串行无锁化设计,在IO线程内部进行串行操作,避免多线程竞争导致的性能下降。
高性能的序列化框架:Netty默认提供了对Google Protobuf的支持,通过扩展Netty的编码解码接口,用户可以实现其他的高性能序列化框架。
小包封大包,防止网络阻塞
软中断Hash值和CPU绑定,开启RPS后可以实现软中断,提升网络吞吐量。
Netty RPC实现
RPC 远程过程调用,调用远程计算机上的服务,就像调用本地服务的一样,RPC可以很好的解耦系统,如WebService就是一种基Http协议的RPC。
关键技术:
1、服务发布与订阅:服务端使用Zookeeper注册服务地址,客户端从Zookeeper获取可用的服务地址
2、通信:使用Netty作为通信框架
3、Spring:使用Spring配置服务,加载bean,扫描注解
4、动态代理:客户端使用代理模式透明化服务调用
5、消息编解码:使用Protostuff序列化和反序列化的消息
核心流程:
1、服务消费方调用以本地调用方式调用服务
2、client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体
3、client stub找到服务地址、并将消息发送到服务端
4、server stub收到消息后进行解码
5、server stub根据解码结果调用本地的服务
6、本地服务执行并将结果返回给server stub
7、server stub将返回结果打包成消息并发送至消费方
8、client stub接收到消息,并进行解码
9、服务消费方得到最终结果
消息数据结构:
1、接口名称
2、方法名
3、参数类型和参数值
4、超时时间
5、requestID,标识唯一请求ID
6、服务端返回的消息
序列化
通讯过程
核心问题 线程暂停、消息乱序
如果使用netty的话,一般会用channel.writeAndFlush()方法来发送消息二进制串,这个方法调用后对于整个远程调用来说是一个异步的,对于当前线程来说,将请求发送出来后,线程就可以往后执行了,至于服务端的结果,是服务端处理完成后,再以消息的形式发送给客户端的。
通讯流程
requestID生成AtomicLong
存放回调对象callback到全局ConcurrentHashMap
synchronized获取回调对象callback的锁并自行wait
监听消息的线程收到消息,找到callback上的锁并唤醒

RMI实现方式
一种用于实现远程过程调用的应用程序编程接口,它是客户机上运行的程序可以调用远程服务器上的对象,远程方法调用特性使Java编程人员能够在网络环境中分布操作,尽可能简化远程接口对象的使用。
实现步骤:
1、编写远程服务接口,该接口必须竭诚remote接口,方法必须抛出RemoteException异常
2、编写远程接口实现类,该实现类必须继承UnicastRemoteObject类
3、运行RMI编译器,创建客户端stub类和服务端skeleton类
4、启动一个RMI注册表,以便驻留这些服务
5、在RMI注册表中注册服务
6、客户端查找远程对象,并调用远程方法
Protoclol Buffer
用于结构化数据串行化的灵活、高效、自动的方法。
特点:
序列化、反序列化简单、速度快
1、编码/解码 方式简单
2、采用protocol buffer自身的框架代码和编译器共同完成
数据压缩效果好
1、采用独特的编码方式,如编码方式等
2、采用T-L-V的数据存储方式,减少了分隔符的使用和数据存储得紧凑
Thrift
是fecebook实现的一种高效的、支持多种编程语言的远程服务调用的框架,本文将从java开发人员角度详细接收Apache Thrift的架构、开发和部署,并且针对不同的传输协议和服务类型给出相应的Java实例,同时详细介绍Thrift异步客户端的实现,最后提出使用Thrift需要注意的事项。
它采用接口描述语言定义并创建服务,支持可扩展的跨语言服务开发,所包含的代码生成引擎可以在多种语言中,相对XML和JSON体积更小,对于高并发、大数据量和多语言的环境更有优势。
1、多语言开发的需要
2、性能问题

你可能感兴趣的:(学习,学习,java,开发语言)