Netty:
1、总体描述,
应用场景Netty是一个高性能、异步事件驱动的NIO框架。封装了Java NIO那些复杂的底层细节,给你提供简单好用的抽象概念来编程。应用场景:首先它是个框架,是个“半成品”,不能开箱即用,你必须得拿过来做点定制,利用它开发出自己的应用程序,然后才能运行(就像使用Spring那样)。 高性能基础通信组件。
2、Netty VS NIO
1)跨平台与兼容性:NIO算是底层的APIs需依赖系统的IO APIs。但Java NIO发现在不同系统平台会出现问题。 NIO2只支持JDK1.7+,而且没提供DatagramSocket,故NIO2不支持UDP协议。 而Netty提供统一接口,同一语句无论在JDK6.X 还是JDK7.X 都可运行,无需关心底层架构功能!2)JAVA NIO的ByteBuffer构造函数私有,无法扩展。Netty提供了自己的ByteBuffer实现,通过简单APIs对其进行构造、使用和操作,一此解决NIO的一些限制。
3)NIO对缓冲区的聚合与分散操作可能会导致内存泄漏。直到JDK1.7才解决此问题。
4)NIO的类库和API繁杂,使用麻烦,你需要熟练掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等。
5)使用JAVA NIO需要具备其他的额外技能做铺垫,例如熟悉Java多线程编程。这是因为NIO编程涉及到Reactor模式,你必须对多线程和网路编程非常熟悉,才能编写出高质量的NIO程序。
6)可靠性能力补齐,工作量和难度都非常大。例如客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常码流的处理等问题。7)JDK NIO的BUG,例如臭名昭著的epoll bug,它会导致Selector空轮询,最终导致CPU 100%。3、epoll bugJDK的NIO类库有一个epoll死循环bug,它会导致Selector空轮询,IO线程CPU达到100%,严重影响系统运行。
netty从api使用层面对该bug进行了规避解决:1)对Selector的select操作周期进行统计。每完成一次空的select操作进行一次计数。2)在某个周期内如果连续N次空轮询,则说明触发了JDK NIO的epoll死循环bug。3)创建新的Selector,将出现bug的Selector上的channel重新注册到新的Selector上。4)关闭bug的Selector,使用新的Selector进行替换。
5、启动Demo与线程池模型
EchoServer:
public void run() {
// 创建一个ServerBootstrap启动工具类 // 构造方法里传入NioServerSocketChannelFactory
ExecutorService boss = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerBoss", true));
ExecutorService worker = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerWorker", true));
ServerBootstrap bootstrap = new ServerBootstrap(
//构建一个创建NioServerSocketChannel的工厂类NioServerSocketChannelFactory
new NioServerSocketChannelFactory( boss, worker));
// Set up the ChannelPipelineFactory.pipeline主要负责管理channel和netty之间消息的传递
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
//传入echoServerHandler
return Channels.pipeline(new EchoServerHandler());
} });
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));}
boss pool:处理Acceptor事件,负责连接的建立,连接建立后将交由worker pool处理,默认一个线程
worker pool:处理I/O读写事件,线程池默认大小,netty=处理器个数*2,dubbo=处理器个数 + 1
在真正的业务中,还应该添加自己的业务线程池,而不应该把业务处理放在netty的worker pool中。
NioEventLoopGroup:线程池
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer() { ..
ChannelPipeline:
ChannelPipline:包含一系列handler,如编解码handler处理器,addLast,利用事件传输机制,handler按顺序触发
网友评论