这一节咱们将确认Netty提供的核心功能是什么,以及它们怎么构成一个完整的网络应用开发堆栈。java
Netty使用它本身的缓存API来表示字节序列而不是NIO的ByteBuffer。Netty的新缓存类——ChannelBuffer,完全解决了ByteBuffer的问题,知足了网络应用开发者的平常需求。这里列举几个很酷的特色:web
当在通讯层传输数据时,数据常常须要被组合或者切分。好比一次装载被分红多个包,可是常常须要组合起来解码。
传统方式来讲,多个包的数据经过复制到一个新的字节缓存而组合起来。
Netty支持零复制实现,经过让一个新的ChannelBuffer“指向”全部要求组合的缓存,从而避免了复制操做。浏览器
传统Java的I/O API对不一样的传输类型提供不一样的类和方法。举个例子,java.net.Socket和java.net.DatagramSocket没有公共父类所以它们在执行socket I/O的方式彻底不同。缓存
这种不匹配的结果就是使得应用程序从一种传输方式移植成另外一种变得十分困难。也就是说你须要支持额外的传输方式由于应用程序的网络层常常涉及到重写。逻辑上,许多协议能够在不仅一种传输方式,好比TCP/IP、UDO/IP、SCTP和串行通讯上运行。安全
更糟的是,Java的新I/O(NIO)API继承了老阻塞I/O(OIO)API的不兼容性,而且在下一个版本NIO.2(AIO)继续这样作。由于这些API在设计和表现特色上彻底不一样,你常常被迫在应用程序开始实现以前就须要肯定好依赖那种API。网络
举个例子,你可能想用OIO方式开始由于你服务的客户数量很小且用OIO写一个socket服务比用NIO要简单得多。可是,当你的业务呈指数级上升而后你须要同时服务成千上万的客户时,麻烦就大了。你也能够用NIO方式开始,可是这可能会阻碍开发速度,毕竟NIO的选择器API很复杂。数据结构
Netty拥有统一的异步I/O接口——Channel,它抽象了点对点通讯要求的全部操做。只要你用一种Netty传输写的应用程序,能够在其余Netty传输上运行。Nett经过统一的API提供了必要的传输方式:架构
要从一种传输方式切换到另外一种,只须要改动几行代码,好比选择另外一个ChannelFactory实现。框架
你甚至可使用还没发布的新传输方式,好比串行通讯传输,一样替换几行构造器调用的代码。再者,你也能够经过继承核心API实现本身的传输方式。异步
一个定义良好的并可扩展性高的事件模型是一个事件驱动应用程序的前提。Netty针对I/O有一个定义良好的事件模型。你能够在不破坏已有代码的状况下实现你本身的事件类,由于每个事件类都根据一个严格的类层次体系区别于其余事件类。这是另外一个和其余框架的不一样点。不少NIO框架都没有或者颇有限的事件模型概念。若是它们提供了扩展,就会常常在尝试增长自定义事件类时破坏已有代码。
一个ChannelEvent由一个ChannelPipeline里的一列ChannelHandler来处理。这个管道实现了一个过滤链模式的高级形式,让使用者彻底控制一个事件如何被处理以及管道内的handler如何相互联系。举个例子,你能够规定数据从socket读取时作点什么:
public class MyReadHandler implements SimpleChannelHandler { public void messageReceived(ChannelHandlerContext ctx, MessageEvent evt) { Object message = evt.getMessage(); // Do something with the received message. ... // And forward the event to the next handler. ctx.sendUpstream(evt); } }
你也能够规定一个handler在接收一个写请求时作点什么:
public class MyWriteHandler implements SimpleChannelHandler { public void writeRequested(ChannelHandlerContext ctx, MessageEvent evt) { Object message = evt.getMessage(); // Do something with the message to be written. ... // And forward the event to the next handler. ctx.sendDownstream(evt); } }
以前“用POJO替代ChannelBuffer”那一节证明了,把协议编解码从业务逻辑中分离出来一般是一个好主意。可是从零开始实现有一些困难。你须要处理信息分片。有一些协议是多层的(创建在其余低级协议基础上)。还有一些协议在单机系统上实现特别困难。
所以,一个好的网络应用框架须要提供一个可扩展的、可重用的、可单元测试的和多层级的编解码器框架,产生可维护的用户编解码器。
Netty提供了一系列基础和高级的编解码器,能够解决你在写一个协议编解码器是遭遇的大多数问题,不管编解码器是否简单,是二进制的仍是文本的。
不像阻塞I/O,在NIO支持SSL是个值得正视对任务。你不能简单得包装一个流对数据进行加密解密,你必需要用到javax.net.ssl.SSLEngine。SSLEngine是一个跟SSL自己同样复杂的状态机。你须要处理全部可能的状态,如密码套件、加密密钥协商、证书交换以及验证。此外,SSL甚至不是彻底线程安全的。
在Netty,SslHandler负责对外屏蔽SSLEngine全部细枝末节,你只须要配置SslHandler而后添加到你的ChannelPipeline中。SslHandler同时让你能够很容易实现相似StartTLS的高级特性。
HTTP绝对是互联网最流行的协议。如今已经有一系列HTTP实现,好比Servlet容器。那么为何Netty还要本身实现HTTP呢?
Netty的HTTP支持和现有的HTTP库很不同。它让你能够彻底控制HTTP在底层的消息交换。由于从根本上来讲,它就是一个HTTP编解码器和HTTP消息类的结合,没有相似强制线程模型这样的限制。也就是说,你能够按照你但愿的工做方式来实现HTTP客户端和服务端。你拥有全部HTTP规范内的控制权,包括线程模型、链接生命周期和分块编码。
基于它的高可定制性,你能够写一个高效的HTTP服务:
WebSocket在单TCP socket上实现一个双向全双工通讯通道,用于web浏览器和web服务端端数据交互。
WebSocket协议由IETF标准化为RFC 6455。
Netty实现了RFC 6455和一系列旧版本规范。
Google Protocal Buffers是一个高效二进制协议的快速实现。凭借ProtobufEncoder和ProtobufDecoder,你能够将Goodgle Protocal Buffers编译程序生成的信息类转化为Netty编解码器。
这一节,咱们从特色出发回顾了Netty的整体架构。Netty拥有一个简单且至今仍强大的架构。它由三个组件组成——buffer,channel和事件模型,全部高级特性都是在这三个组件的基础上创建的。只要你理解了这三个组件是如何一块儿工做的,你就不难理解这节简要说起的那些高级特性。