netty主要是一个异步的nio server/client framework
它采用了event driven模式
netty主要针对异步(asynchronous)请求的处理
netty channel可以理解为传输请求的另外一种抽象, 是netty最核心的概念, 它既可以表示一个socket, 也可以表示一个file, 总之就是I/O的一个抽象.
channel提供了一个网络连接和向目标对象写数据的接口, 而对于异步方式来说, 没有读的概念(通过listener来监听返回数据), Channel的返回结果会放在ChannelFuture中
netty不仅实现异步, 也有同步实现, 不过是内部也是采用的future机制
channel分server和client两种
channel由ChannelFactory创建, 它需要提供两个线程池: boss线程池, worker线程池, boss线程池用来监听连接, 将接受到的数据传给worker线程池处理, 一般只会有一个boss thread.
worker thread应该注意的一点是千万别被block和deadlock, 否则会导致整个吞吐量上不去. 尽量保证worker thread简单专一, 剥离无关内容, 能快速完成处理.
boss thread只有一个, 但是为什么要用thread pool?
1.可能有多个channel factory, 这些factory可以共用一个boss thread pool来创建boss thread.
2.boss thread可以中途进行释放, 为了避免重复create的开销, 可以用一个小型的thread pool来管理
所有资源的分配都是通过channel factory来完成, 因此如果需要释放资源, 需要调用realseExternalResources()
channel的使用三部曲:
这里需要提到Channel另外一个组成部分, ChannelPipeline. 它主要完成对传入的内容的解析处理.为了保证这个解析的灵活性, 或包含一系列的, 各种类型的解析器, 这些解析器最后将以ChannelHandler的方式进行组织. ChannelPipeline则包含多种ChannelHandler, 一般第一个ChannelHandler接受ChannelBuffer, 最后一个ChannelHandler(通常命名为sink)用来去掉payload信息. ChannelHandler是一个标志接口, 灵活性非常强, 它一般会通过接受ChannelEvent(内含ChannelBuffer)来完成对数据的处理.
ChannelHandler主要包含两类: Encoder(将数据流转换成ChannelBuffer), Decoder
除了编解码之外, 还有一些其他类型的channelHandler, 比如将channel event丢到thread pool中处理的ExecutionHandler, 用于同步处理的BlockingReadHandler, 用于打日志的LoggingHandler
client bootstrap 是connect, server bootstrap是bind
如果让client传上来的channelbuffer经过处理之后, 再原路返回一些消息给client, 在ChannelHandler中一般这样写:
这里返回数据需要注意两点, 一个是可能返回的handler之后还有handler, 我们还需要继续将修改后的内容继续往后传递, 另外一个就是返回的数据可能不希望再被其中的某些handler处理.
handler可以分为upstream handler(channel pipeline向外面发数据), downstream handler(外面向channel pipeline发数据)和 both handler. 我觉得这个up, down名字取得不好, 应该是out=up, in=down, 不过如果将channel pipeline想象成一个口袋, 可能更好理解. 或者理解成: read up, write down
pipeline中的handler可以动态调整, 比如下面的这个, 就是根据传入的内容的大小来决定是否需要使用压缩handler来进行压缩处理
ChannelHandlerContext可以看成handler和pipeline之间的adapter. 用来方便在handler处理过程中调用pipeline
对于ObjectEncoder是无状态的, 而ObjectDecoder是有状态的. 之所有有状态是因为解码的过程中需要的ChannelBuffer是不连续的, 可能需要多次解码才能得到最终完成的对象, 而在处理的过程中需要保存一些状态信息.
如果连接数小于1000, netty推荐采用传统的OIO(blocking)模式
ChannelLocal提供了一种类似ThreadLocal的机制在一个Channel中访问共享的内容.
它采用了event driven模式
netty主要针对异步(asynchronous)请求的处理
netty channel可以理解为传输请求的另外一种抽象, 是netty最核心的概念, 它既可以表示一个socket, 也可以表示一个file, 总之就是I/O的一个抽象.
channel提供了一个网络连接和向目标对象写数据的接口, 而对于异步方式来说, 没有读的概念(通过listener来监听返回数据), Channel的返回结果会放在ChannelFuture中
netty不仅实现异步, 也有同步实现, 不过是内部也是采用的future机制
channel分server和client两种
channel由ChannelFactory创建, 它需要提供两个线程池: boss线程池, worker线程池, boss线程池用来监听连接, 将接受到的数据传给worker线程池处理, 一般只会有一个boss thread.
worker thread应该注意的一点是千万别被block和deadlock, 否则会导致整个吞吐量上不去. 尽量保证worker thread简单专一, 剥离无关内容, 能快速完成处理.
boss thread只有一个, 但是为什么要用thread pool?
1.可能有多个channel factory, 这些factory可以共用一个boss thread pool来创建boss thread.
2.boss thread可以中途进行释放, 为了避免重复create的开销, 可以用一个小型的thread pool来管理
所有资源的分配都是通过channel factory来完成, 因此如果需要释放资源, 需要调用realseExternalResources()
channel的使用三部曲:
- 创建
- 监听socket
- 调用write(Object message)接受数据. 不过这里只能接受ChannelBuffer类型的数据.
这里需要提到Channel另外一个组成部分, ChannelPipeline. 它主要完成对传入的内容的解析处理.为了保证这个解析的灵活性, 或包含一系列的, 各种类型的解析器, 这些解析器最后将以ChannelHandler的方式进行组织. ChannelPipeline则包含多种ChannelHandler, 一般第一个ChannelHandler接受ChannelBuffer, 最后一个ChannelHandler(通常命名为sink)用来去掉payload信息. ChannelHandler是一个标志接口, 灵活性非常强, 它一般会通过接受ChannelEvent(内含ChannelBuffer)来完成对数据的处理.
ChannelHandler主要包含两类: Encoder(将数据流转换成ChannelBuffer), Decoder
除了编解码之外, 还有一些其他类型的channelHandler, 比如将channel event丢到thread pool中处理的ExecutionHandler, 用于同步处理的BlockingReadHandler, 用于打日志的LoggingHandler
client bootstrap 是connect, server bootstrap是bind
如果让client传上来的channelbuffer经过处理之后, 再原路返回一些消息给client, 在ChannelHandler中一般这样写:
- Channel channel = e.getChannel();
- ChannelFuture channelFuture = Channels.future(e.getChannel());
- ChannelEvent responseEvent = new DownstreamMessageEvent(channel, channelFuture, newDate, channel.getRemoteAddress());
- ctx.sendDownstream(responseEvent);
- // But still send it upstream because there might be another handler
- super.messageReceived(ctx, e);
这里返回数据需要注意两点, 一个是可能返回的handler之后还有handler, 我们还需要继续将修改后的内容继续往后传递, 另外一个就是返回的数据可能不希望再被其中的某些handler处理.
handler可以分为upstream handler(channel pipeline向外面发数据), downstream handler(外面向channel pipeline发数据)和 both handler. 我觉得这个up, down名字取得不好, 应该是out=up, in=down, 不过如果将channel pipeline想象成一个口袋, 可能更好理解. 或者理解成: read up, write down
pipeline中的handler可以动态调整, 比如下面的这个, 就是根据传入的内容的大小来决定是否需要使用压缩handler来进行压缩处理
- public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) {
- // If the message is not a ChannelBuffer, hello ClassCastException !
- ChannelBuffer cb = (ChannelBuffer)e.getMessage();
- // Check to see if we already removed the handler
- boolean pipelineContainsCompressor = ctx.getPipeline().getContext(nameOfCompressionHandler)!=null;
- if(cb.readableBytes() < sizeThreshold) {
- if(pipelineContainsCompressor) {
- // The payload is too small to be compressed but the pipeline contains the compression handler
- // so we need to remove it.
- compressionHandler = ctx.getPipeline().remove(nameOfCompressionHandler);
- }
- } else {
- // We want to compress the payload, let's make sure the compressor is there
- if(!pipelineContainsCompressor) {
- // Oops, it's not there, so lets put it in
- ctx.getPipeline().addAfter(ctx.getName(), nameOfCompressionHandler , compressionHandler);
- }
- }
- }
ChannelHandlerContext可以看成handler和pipeline之间的adapter. 用来方便在handler处理过程中调用pipeline
对于ObjectEncoder是无状态的, 而ObjectDecoder是有状态的. 之所有有状态是因为解码的过程中需要的ChannelBuffer是不连续的, 可能需要多次解码才能得到最终完成的对象, 而在处理的过程中需要保存一些状态信息.
如果连接数小于1000, netty推荐采用传统的OIO(blocking)模式
ChannelLocal提供了一种类似ThreadLocal的机制在一个Channel中访问共享的内容.