Netty介绍
Netty是一个网络应用框架,Netty提供异步事件驱动的方式,使用它可以快速地开发出高性能的网络应用程序,比如客户端/服务器自定义协议程序,大大简化了网络程序的开发过程。
Netty架构总览
Netty主要分为三部分:
一是底层的零拷贝技术和统一通信模型;
二是基于JVM实现的传输层;
三是常用协议支持;
![b4dc9e666bd9a1876c3e3d361e682d29.png](https://i-blog.csdnimg.cn/blog_migrate/eb2ce410a793268c201cd4a1ea8ad234.jpeg)
1、重新实现ByteBuffer
Netty使用自己重新实现的buffer API,而不是使用NIO的ByteBuffer来表示一个连续的字节序列。重新实现的ByteBuf特性包括允许使用自定义的缓存类型、透明的零拷贝实现、比ByteBuffer更快的相应速度。
字节缓存在网络通信中会被频繁地使用,ByteBuf实现的是一个非常轻量级的字节数组包装器。ByteBuf有读操作和写操作,为了方便用户使用,该缓冲区维护了读索引和写索引。
ByteBuf由三个片段组成:废弃段、可读段和可写段。可读段表示缓冲区实际存储的可用数据。
当用户使用read或者skip方法时,将会增加读索引。读索引之前的数据将进入可废弃段,表示该数据已被使用过。
用户可以主动使用discardReadBytes清空废弃段得到更多的可写空间。
2、统一的异步I/O接口
Netty Channel的统一异步I/O编程接口,这个接口抽象了所有点对点的通信操作。如果应用基于Netty的某一种传输方式来实现的,可以快速迁移到另一种传输实现上。
Netty提供了集中拥有相同编程接口的基本传输实现:
- 基于NIO的TCP/IP传输:io.netty.channel.nio
- 基于OIO的TCP/IP传输:io.netty.channel.oio
- 基于OIO的UDP/IP传输:io.netty.channel.oio
- 本地传输:io.netty.channel.local
Netty用法示例
1、Discard服务器
DiscardServerHandler继承自ChannelInboundHandlerAdapter,覆盖channelRead()时间处理方法,每当从客户端收到新的数据时,这个方法会在收到消息时被调用。
ByteBuf是一个引用计数对象,必须显式地调用realease()方法来释放。
在出现Throwable对象,即当Netty由于IO错误或者处理器在处理事件抛出异常时,exceptionCaught()时间处理方法会被调用。
![985484b732021fcea895b2037be00af5.png](https://i-blog.csdnimg.cn/blog_migrate/d142c2ed00299c193829d600e5d5be39.jpeg)
NioEventLoopGroup是用来处理I/O操作的多线程事件循环器,Netty提供了许多不同的EventLoopGroup的实现来处理不同的传输类型。bossGroup用来接收进来的数据,workerGroup用来处理已经被接收的连接。
ServerBootstrap是一个启动NOP服务的辅助启动类。
![a6f71ef6343e9afc0bd1899e9b08b76b.png](https://i-blog.csdnimg.cn/blog_migrate/b12ad1b106d010cbd21e847e24b569a7.jpeg)
2、查看收到的数据
![d11bc6a86aaf92250be442bd23562ea1.png](https://i-blog.csdnimg.cn/blog_migrate/677e9e458e309cbedb3d7cb1cde8dd0b.jpeg)
RocketMQ基于Netty的通信功能实现
RocketMQ底层通信的实现是在Remoting模块里,用Netty实现了一个自定义协议的客户端/服务器程序。
1、顶层抽象类
RemotingServer类中比较重要的是:localListenPort、registerProcess、registerDefaultProcessor,registerDefaultProcessor用来设置接收到消息后的处理方法。
![e9c48255f621c13369d4c4bb58c4104d.png](https://i-blog.csdnimg.cn/blog_migrate/9822ec614f3796c40f606c911571e0ff.jpeg)
RemotingClient类中比较重要的是:updateNameServerAddressList、invokeSync、invokeOneway,updateNameServerAddressList用来获取有效的NameServer地址,invokeSync与invokeOneway用来向Server端发送请求。
![8e039e12e00732b8e0614703ef3abf0e.png](https://i-blog.csdnimg.cn/blog_migrate/a85ff605e4a18ef54d662c43ceba65cc.jpeg)
2、自定义协议
NettyRemotingServer和NettyRemotingClient分别实现了RemotingServer与RemotingClient接口,共同继承类NettyRemotingAbstract父类。
处理请求消息
![7b7380923317f2d12de2d6bf23d99734.png](https://i-blog.csdnimg.cn/blog_migrate/74d18a7368c06cfc16cf3a694ca7fa60.jpeg)
RemotingCommand成员变量
RemotingCommand是RocketMQ自定义的协议。
![279379a59f7db2b90239ab0b91ca636e.png](https://i-blog.csdnimg.cn/blog_migrate/70296c94be8956645778aa2cfbc9107d.jpeg)
同步方式发送
函数的RemotingCommand来自对发送消息的封装,输入参数Channel来自io.netty.channel。Channel是通信的入口,Channel对象的获取,对于服务端你和客户端来说差别很大。
对于客户端来说,是主动获取消息的一方,需要向哪个地址发送消息,通过Netty的Bootstrap方法创建一个连接(同时把连接后的Channel保存起来,避免每发送一个消息都要重新创建连接)。
对于服务端来说,很少主动发送消息,服务端一直在监听某个端口,当有一个连接请求进入后,服务端会把的创建的Channel对象保存下来,供偶尔需要向客户端主动发消息的时候使用。
![1a4b6f8e72a099522d4a604039483e0d.png](https://i-blog.csdnimg.cn/blog_migrate/f2cd22a9b8f246dbdc186697f082c79c.jpeg)
3、基于Netty的Server和Client
基于Netty实现的Server或Client程序,具体代码在NettyRemotingServer和NettyRemotingClient类中,从ServerBootstrap的初始化是如何实现的。
![0ffc6e7c025bd659fc9a9bff9c5ba4f1.png](https://i-blog.csdnimg.cn/blog_migrate/f2adbfca73b25bc0161464ed693dd7bc.jpeg)
ServerBootstrap的BossEventLoop使用的是单线程的NioEventLoopGroup,writeEventLoop在Linux平台使用的是默认3个线程的EpollEventLoopGroup,在非Linux平台上使用的是3个线程的NioEventLoopGroup。
还可以看到添加了NettyEncoder和NettyDecoder这两个Handler。这些Handler执行在一个8线程的DefaultEventExecutorGroup中。
注册Processor
RocketMQ对通信过程的另一个抽象是Processor和Executor,当接收到一个消息后,直接根据消息的类型调用对应的Processor和Executor,把通信过程和业务逻辑分离开。
![66c4aeba0af8adc7f31d0333e14b30e2.png](https://i-blog.csdnimg.cn/blog_migrate/77d9bf9e9a5c756169c1784698546e8a.jpeg)