• 1. Netty介绍和应用 魏俊辉 2015.7.22
  • 2. Netty简介 Netty源码分析 Netty应用 大纲
  • 3.  Netty 是一个基于 JAVA NIO 类库的异步通信框架,它的架构特点是:异步非阻塞、基于事件驱动、高性能、高可靠性和高可定制性。 Netty 是什么
  • 4.  开发异步、非阻塞的 TCP 网络应用程序 开发异步、非阻塞的 UDP 网络应用程序 开发异步文件传输应用程序 开发异步 HTTP 服务端和客户端应用程序 Netty 的作用
  • 5. NIO:在高连接数时使用 OIO:在低连接数、需要低延迟时、阻塞时使用 Local:在同一个JVM内通信时使用 Embedded:测试ChannelHandler时使用传输支持
  • 6. Netty简介 Netty源码分析 Netty在JWS的应用 大纲
  • 7. 简单的http服务器
  • 8. EventLoopGroup右图显示一个EventLoopGroup和一个Channel关联一个单一的EventLoop,Netty中的EventLoopGroup包含一个或多个EventLoop,而EventLoop就是一个Channel执行实际工作的线程。
  • 9. EventLoop 和 Channel是一对多的关系 处理 “events” 并把它交给 ChannelPipeline 所有的任务都在EventLoop 执行 注意:任何时候都不要阻塞EventLoop EVENT-LOOP
  • 10. EventLoop和EventLoopGroup的关系EventLoop相当于一个Thread线程,而EventLoopGroup则是管理这些EventLoop的Thread线程池
  • 11. “引导”是Netty中配置程序的过程,当你需要连接客户端或服务器绑定指定端口时需要使用bootstrap 。 “引导”有两种类型,一种是用于客户端的Bootstrap(也适用于DatagramChannel),一种是用于服务端的ServerBootstrap。Bootstrap
  • 12. Bootstrap用来连接远程主机,有1个EventLoopGroup ,用于连接服务器。 ServerBootstrap用来绑定本地端口,有2个EventLoopGroup,一个接受客户端连接,一个处理客户端连接。Bootstrap和ServerBootstrap
  • 13. 引导负责客户端通道连接或断开连接,因此它将在调用 bind(...)或connect(...)后创建通道。下图显示了如何工作:Bootstrap
  • 14. Bootstrap
  • 15. 下图显示ServerBootstrap管理子通道:ServerBootstrap
  • 16. ServerBootstrap
  • 17. 前面都是引导基于TCP的SocketChannel,引导也可以用于无连接 的传输协议如UDP,Netty提供了DatagramChannel,唯一的区别 是不会connecte(...),只能bind(...)。看下面代码:DatagramChannel
  • 18. 在Netty里,Channel是通讯的载体,ChannelEvent是数据或者状态的载体,ChannelHandler负责Channel中的逻辑处理,ChannelPipeline相当于ChannelHandler的容器,所有ChannelHandler都会注册到ChannelPipeline中,并按顺序组织起来。 Channel和ChannelPipeline
  • 19. Channel接口为用户提供了: 1.   Channel的当前状态,比如:Channel是否open,或者Channel是否已经连接。 2.   Channel的参数,比如:接受的buffer大小。 3.   Channel支持的I/O操作,比如:read,write,connect,bind。 4.   注册在Channel上的ChannelPipeline,ChannelPipeline用于处理所有的I/O事件和请求。Channel
  • 20. 下面是Channel生命周期四个不同的状态: channelUnregistered channelRegistered channelActive channelInactiveChannel
  • 21. 多个channelRegistered和channelUnregistered状态,而永远只有一个channelActive和channelInactive的状态,因为一个通道在其生命周期内只能连接一次,之后就会被回收;重新连接,则是创建一个新的通道。Channel
  • 22. ChannelHandlerNetty中有3个实现了ChannelHandler接口的类,其中2个是接口,一个是抽象类。如下图:
  • 23. 承载 ChannelHandlers 的容器 所有的事件会通过它 可以随时运行中修改 Channel 和 ChannelPipeline是一对一的关系ChannelPipeLine
  • 24. ChannelPipeLine对ChannelHandler的控制下图描述了ChannelHandler在ChannelPipeline中的I/O处理,一个I/O操作可以由一个ChannelInboundHandler或ChannelOutboundHandler进行处理,并通过调用ChannelInboundHandler处理入站IO或通过ChannelOutboundHandler处理出站IO。
  • 25. 1)通知下一个ChannelHandlerChannelHandlerContext
  • 26. 2)修改channelpipeline 调用ChannelHandlerContext的pipeline()方法能访问ChannelPipeline,能在运行时动态的增加、删除、替换ChannelPipeline中的ChannelHandler。ChannelHandlerContext
  • 27. ChannelPipeline并不是直接管理ChannelHandler,而是 通过ChannelHandlerContext来间接管理:Pipeline,Context和Handler共同协作
  • 28. DefaultChannelHandlerContext和DefaultChannelPipeline 是ChannelHandlerContext和ChannelPipeline的默认实现, 下面是它们的部分代码: Pipeline,Context和Handler共同协作
  • 29. Pipeline,Context和Handler共同协作
  • 30. 在DefaultPipeline内部,DefaultChannelHandlerContext组 成了一个双向链表:Pipeline,Context和Handler共同协作
  • 31. DefaultChannelPipeline内部使用了两个特殊的Handler来表示 Handler链的头和尾:Pipeline,Context和Handler共同协作
  • 32. 事件如何在Pipeline里传播? 下面是AbstractChannel#write()方法的实现:Pipeline,Context和Handler共同协作
  • 33. DefaultChannelPipeline的write()方法实现:Pipeline,Context和Handler共同协作因为write是个outbound事件,所以DefaultChannelPipeline 直接找到tail的context,调用其write()方法:
  • 34. AbstractChannelHandlerContext的write()方法实现:Pipeline,Context和Handler共同协作
  • 35. context的write()方法沿着context链往前找,直至找到一个 outbound类型的context为止,然后调用其invokeWrite()方法:Pipeline,Context和Handler共同协作
  • 36. context的write()方法沿着context链往前找,直至找到一个 outbound类型的context为止,然后调用其invokeWrite()方法:Pipeline,Context和Handler共同协作
  • 37. Pipeline,Context和Handler共同协作context的invokeWrite()方法,调用handler()获取handler,并调 用此handler的write()方法:
  • 38. Pipeline,Context和Handler共同协作默认的实现调用了context的write()方法而不做任何处理,这样 write事件就沿着outbound链继续传播:ChannelOutboundHandlerAdapter的write()方法实现:
  • 39. Netty提供了ChannelInitializer类用来配置Handlers。 ChannelInitializer是通过ChannelPipeline来添加ChannelHandler的。 ChannelInitializer自身也是一个ChannelHandler,在添加完其他的handlers之后会自动从ChannelPipeline中删除自己。 ChannelInitializer
  • 40. Netty缓冲API提供了几个优势: 可以自定义缓冲类型 通过一个内置的复合缓冲类型实现零拷贝 扩展性好,比如StringBuffer 不需要调用flip()来切换读/写模式 读取和写入索引分开 方法链 引用计数 Pooling(池) ByteBuf
  • 41. 3种不同类型的ByteBuf Heap Buffer(堆缓冲区) Direct Buffer(直接缓冲区) Composite Buffer(复合缓冲区) ByteBuf
  • 42. 数据存储在JVM的堆空间,这是通过将数据存储在数组的实现。堆缓冲区可以快速分配,当不使用时也可以快速释放。它还提供了直接访问数组的方法,通过ByteBuf.array()来获取byte[]数据。 访问非堆缓冲区ByteBuf的数组会导致UnsupportedOperationException,可以使用ByteBuf.hasArray()来检查是否支持访问数组。Heap Buffer
  • 43. 直接缓冲区,在堆之外直接分配内存。直接缓冲区不会占用堆空间容量,使用时应该考虑到应用程序要使用的最大内存容量以及如何限制它。 直接缓冲区在使用Socket传递数据时性能很好,因为若使用间接缓冲区,JVM会先将数据复制到直接缓冲区再进行传递。 直接缓冲区的缺点是在分配内存空间和释放内存时比堆缓冲区更复杂,而Netty使用内存池来解决这样的问题,这也是Netty使用内存池的原因之一。Direct Buffer
  • 44. 复合缓冲区,我们可以创建多个不同的ByteBuf,然后提供一个这些ByteBuf组合的视图。 复合缓冲区就像一个列表,我们可以动态的添加和删除其中的ByteBuf,JDK的ByteBuffer没有这样的功能。 Netty提供了CompositeByteBuf类来处理复合缓冲区,CompositeByteBuf只是一个视图。Composite Buffer
  • 45. ByteBuf结构
  • 46. HTTP Websockets SPDY Serialization JBoss Marshalling Protobufs SSL ZlibNetty已经提供的编解码器
  • 47. ByteToMessageDecoder MessageToMessageDecoderDECODER
  • 48. MessageToByteEncoder MessageToMessageEncoderENCODER
  • 49. Red Hat Twitter Facebook Firebase Urban Airship LinkedIn Samsung Boundary ... 使用Netty的公司
  • 50. Vert.x HornetQ Infinispan Play Framework Finangle Apache Cassandra Minecraft ....使用Netty的开源项目