Transport & Buffer
Transport
传输API的核心是Channel接口,用于所有的出站操作。
每个Channel都会分配一个ChannelPipeline和ChannelConfig。ChannelConfig负责设置并存储设置,并允许在运行期间更新它们。ChannelPipeline容纳了使用的ChannelHandler实例,这些ChannelHandler将处理通道传递的“入站”和“出站”数据、ChannelHandler允许你改变数据状态和传输数据。
ChannelHandler处理以下事情
传输数据时,将数据从一种格式转换到另一种格式
异常通知
Channel变为有效或无效时通知
Channel被注册或从EventLoop中注销时获得通知
通知用户特定事件
ChannelHandler实例添加到ChannelPipeline中,在ChannelPipeline中按顺序逐条执行。它类似于一个链条。
ChannelPipeline实现了拦截过滤器模式,这意味着我们连接不通的ChannelHandler来拦截并处理经过ChannelPipeline的数据或事件。
Channel提供如下方法
eventLoop():返回分配给Channel的EventLoop
pipeline():返回分配给Channel的ChannelPipeline
isActive():返回Channel是否已经激活,已激活说明与远程连接对接
localAddress():返回已绑定的本地SocketAddress
remoteAddress():返回已绑定的远程的SocketAddress
write():写数据到远程客户端,数据通过ChannelPipeline传输过去
Channel是线程安全的,他可以被多个不同的线程安全的操作。
Netty中的传输方式有如下4种:
NIO, io.netty.channel.socket.nio —— 基于java.nio.channels工具包。使用选择器作为基础的方法。在高连接数时使用
OIO, io.netty.channel.socket.oio —— 基于java.net工具包,使用阻塞流。在低连接数,需要低延迟时,阻塞时使用
Local,io.netty,channel.local —— 用于在虚拟机间进行本地通信。在同一个JVM内通信使用
Embedded,io.netty.channel.embedded,嵌入传输 —— 允许在没有真正网络的运输中使用ChannelHandler,可以用来测试ChannelHandler的实现。测试ChannelHandler时使用
NIO
NIO通过使用选择器提供了完全异步地方式操作所有的IO。
通道状态一般有4种:一个新的Channel被接受并已准备好;Channel连接完成;Channel中有数据并已准备好读取;Channel发送数据出去。
我们可以注册一个通道或获得某个通道的改变的状态,处理完改变的状态后需要重新设置他们的状态,用一个线程来检查是否有已准备好的Channel,若有则执行相关状态。
选择器所支持的操作在SelectionKey中定义:
OP_ACCEPT:有新连接时得到通知
OP_CONNECT:连接完成后得到通知
OP_READ:准备好读取数据时得到通知
OP_WRITE:写入数据到通道时得到通知
NIO在处理过程中有一定的延迟,若连接数不大,延迟一般在毫秒级。Netty中的NIO传输是“zero-file-copy”。
Netty本地传输,这个传输实现使用相同的API用于虚拟机之间的通信,传输是完全异步地。每个Channel使用唯一的SocketAddress,客户端通过使用SocketAddress进行连接,在吴福气会被注册为长期运行,一旦通道关闭,它会自动注销。本地传输只能在本地的服务器和客户端上使用它们。Local未绑定任何的Socket,值提供JVM进程间的通信。
Netty嵌入传输,这个传输允许使用不同的ChannelHandler之间交互。
Buffer
Netty的缓冲API有两个接口:ByteBuf和ByteBufHolder。
Netty缓冲提供了以下优势:可以自定义缓冲类型;通过一个内置的复合缓冲类型实现零拷贝;扩张性好;不需要调用flip()来切换读/写模式;读取和写入索引分开;方法链;引用计数和Pooling(池)
ByteBuf
写入数据到ByteBuf后,写入索引是增加的字节数量。开始读字节后,读取索引增加,知道写入索引和读取索引处理相同的位置,若继续读,则抛出IndexOutOfBoundsException。调用ByteBuf的任何方法开始读/写都会单独维护读索引和写索引。ByteBuf的默认最大容量限制是Integer.MAX_VALUE,写入时若超出这个值将会导致一个异常。
Netty有3种类型的ByteBuf:Heap Buffer,Direct Buffer和Composite Buffer。
最常用的类型是ByteBuf将数据存储在JVM的堆空间,这是通过将数据存储在数组实现的。对缓冲区可以快速分配,当不使用时也可以快速释放。还提供了直接访问数据的方法,通过ByteBuf.array()来获取byte[]数据。访问非堆缓冲区ByteBuf的数组会导致UnsupportedOperationException,可以使用gByteBuf.hasArray()来检查是否支持访问数组。
直接缓冲区在堆之外直接分配内存。直接缓冲区不会占用堆空间容量,使用时应该考虑到应用程序要使用的最大内存容量以及如何限制它。直接缓冲区在使用Socket传递数据时性能很好,若使间接缓冲区,JVM会先将数据复制到直接缓冲区再进行传递。但直接缓冲区的缺点是在分配内存空间和释放内存时比堆缓冲区复杂。Netty使用内存池解决这个问题。直接缓冲区不支持数组访问数据。
ByteBuf directBuf = Unpooled.directBuffer(16);
if(!directBuf.hasArray){
int len = directBuf.readableBytes();
byte[] arr = new byte[len];
directBuf.getBytes(0, arr);
}
复合缓冲区使我们可以创建多个不同的ByteBuf,然后提供一个ByteBuf组合的视图。复合缓冲区就像一个列表,可以动态添加和删除其中的ByteBuf。
CompositeByteBuf comBuf = Unpooled.compositeBuffer();
ByteBuf heapBuf = Unpooled.buffer(8);
ByteBuf directBuf = Unpooled.directBuffer(16);
comBuf.addComponents(heapBuf, directBuf);
comBuf.removeComponent(0);
Iterator<ByteBuf> iter = comBuf.iterator();
while(iter.hasNext())
System.out.println(iter.nex().toString()); if(!comBuf.hasArray()){
int len = comBuf.readableBytes();
byte[] arr = new byte[len];
comBuf.getBytes(0, arr);
}
ByteBuf使用zero-based-indexing(从0开始的索引),第一个字节的索引是0,最后一个字节的索引是ByteBuf的capacity-1。
ByteBuf buf = Unpooled.buffer(16);
for(int i = 0; i < buf.capacity(); i ++){
byf.writeByte(i+1);
}
// 通过索引访问时不会推进读索引和写索引
for(int i = 0; i < buf.capacity(); i++){
System.out.println(buf.getByte(i));
}
ByteBuf提供两个指针变量支持读和写操作。读操作使用readIndex(),写操作使用writeIndex()。可以使用ByteBuf.discardReadBytes()来回收已经读取过的字节。discardReadBytes()将丢弃从索引0到readerIndex之间的字节。ByteBuf.discardReadBytes()可以用来清空ByteBuf中已读取的数据,从而使ByteBuf有多余的空间容纳新数据。但是discardReadBytes()涉及内存复制,会影响性能,一般在需要马上释放内存的时候使用收益会比较大。
任何读操作会增加readerIndex,若读取操作的参数也是一个ByteBuf而没有指定目的索引。指定的目的缓冲区的writeIndex会一直增加。新分配,包装,复制的缓冲区的readerIndex的默认值都是0。
任何写操作会增加writeIndex。若写操作的参数也是一个ByteBuf并没有指定数据源索引,那么指定缓冲区的readerIndex也会一起增加。若没有足够的可写字节会抛出IndexOutOfBoundException。
调用ByteBuf.clear()可以设置readerIndex和writeIndex为0.clear不会清楚缓冲区的内容,只是将两个索引值设置为0。
ByteBufProcessor可以实现搜索。
每个ByteBuf有两个标注索引,一个存储readerIndex,一个存储writerIndex。可以通过调用readerIndex(int readerIndex)和writeIndex(int writerIndex)移动读索引和写索引到指定位置,调用这两个方法设置指定索引位置时可抛出IndexOutOfBoundException。
调用duplicate(),slice(),slice(int index, int length),order(ByteOrder endianness)会创建一个现有缓冲区的视图。衍生的缓冲区有独立的readerIndex,writeIndex和标注索引。若需要现有缓冲区的副本,可以使用copy()或copy(int index, int length)获得。
ByteBufHolder
ByteBufHolder是一个辅助类,是一个接口,其实现类是DefaultByteBufHolder。ByteBufHolder的作用是方便访问ByteBuf中的数据,当缓冲区没用了之后,可以用ByteBufHolder释放资源。若想实现一个“消息对象”有效负载在ByteBuf,可以使用ByteBufHolder。
ByteBufAllocator
ByteBufAllocatior负责分配ByteBuf实例。ByteBufAllocator提供了各种分配不同ByteBuf方法。如ByteBufAllocator.heapBuffer();ByteBufAllocator.directBuffer();ByteBufAllocation.compositeBuffer();Netty有两种不同的ByteBufAllocator实现,一个实现ByteBuf实例池将分配和回收成本以及内存使用降低到最低;另一种实现是每次使用都创建一个新的ByteBuf实例。Netty默认使用PooledByteBufAllocator。可以通过ChannelConfig或引动设置一个不同的实现。
ServerBootstrap b = new ServerBootstrap();
EventLoopGroup group = new EventLoopGroup();
b.group(group).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port))
.childHandler(new ChannelInitializer<SocketChannel>()){
proctectd void initChannel(SocketChannel ch) throws Exception{
ByteBufAllocator alloc0 = ch.alloc();
ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){
public void channelActive(ChannelHandlerContext ctx) throws Exception{
ByteBufAllocator alloc1 = ctx.alloc();
ctx.writeAndFlush(buf.duplicate()).addListener(ChannelFutureListener.CLOST);
}
});
}
});
Transport & Buffer的更多相关文章
- 使用zeebe DebugHttpExporter 查看zeebe 工作流信息
zeebe 提供了一个DebugHttpExporter 可以方便的查看部署以及wokrflow 运行信息 以下是一个简单的运行试用,同时集成了prometheus,添加了一个简单的grafana d ...
- socket-详细分析No buffer space available
关键词:socket,tcp三次握手,tcp四次握手,2MSL最大报文生存时间,LVS,负载均衡 新年上班第一天,突然遇到一个socket连接No buffer space available的问题, ...
- [Network]Transport Layer
1 Principles behind Transport Layer Services 1.1 Multiplexing/Demultiplexing Multiplexing at sender ...
- socket-详细分析No buffer space available(转)
新年上班第一天,突然遇到一个socket连接No buffer space available的问题,导致接口大面积调用(webservice,httpclient)失败的问题,重启服务器后又恢复了正 ...
- ActiveMQ in Action(2) - Transport
关键字: activemq 2.2 Transport ActiveMQ目前支持的transport有:VM Transport.TCP Transport.SSL Transport.Peer ...
- org.elasticsearch.transport.ReceiveTimeoutTransportException[cluster:monitor/nodes/liveness] request_id [31] timed out after [5000ms]
ES连接超时,异常信息 2017-09-07 10:42:45.042 [elasticsearch[Bantam][transport_client_worker][T#17]{New I/O wo ...
- Kestrel.Transport.Sockets分析与使用
相信大家都清楚asp core有着非常出色的性能,它出色的性能也源于网络服务模块Kestrel:在techempower测试中Kestrel基础核心达到了700万级别的RPS吞吐能力,具备这样的能力那 ...
- HttpClient exception:ExceptionType:System.Threading.Tasks.TaskCanceledException: The operation was canceled. ---> System.IO.IOException: Unable to read data from the transport connection: Operation ca
error msg: System.Threading.Tasks.TaskCanceledException: The operation was canceled. ---> System. ...
- java socket / No buffer space available
s https://www.cnblogs.com/yiwangzhibujian/p/7107785.html Socket用在哪呢,主要用在进程间,网络间通信. https://www.cnblo ...
随机推荐
- 函数使用八:BP_EVENT_RAISE
此函数是关联触发一个已经定义的事件,这个事件可以放到SM36里设置JOB,这样就做成了一个事件触发JOB的东西. Import EVENTID 事件ID ,对应S ...
- Django之路由分配系统
前言: Django大致工作流程 1.客户端发送请求(get/post)经过web服务器.Django中间件. 到达路由分配系统 2.路由分配系统根据提取 request中携带的的url路径(path ...
- ssl tls 证书链 根证书和叶证书查询
你基本上需要做的是构建一个证书链,如果你没有得到它作为一个链.证书链基本上由第零个位置的最终实体证书(也是叶证书,链中最重要的证书)组成,其次是次要证书. CA证书是最不重要的. 所以这是通常的X.5 ...
- JBoss/WildFly 初步安装配置教程
1.下载 Redhat的JBoss与Oracle的Weblogic.IBM的WebSphere并称三大JAVA EE中间件. JBoss AS是JBoss的开源版本,JBoss EAP是JBoss的企 ...
- 【Java算法】输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数
import java.util.Scanner; public class CountZimuShuzi { public static void main(String[] args) { Sys ...
- 逆袭之旅DAY31.XIA.JDBC
2018-07-31 MySQL package oop_emp.com.neusoft.dao; import java.sql.Connection; import java.sql.Driver ...
- Win10系列:JavaScript综合实例4
实现主页面和分类页面的之后,最后来看一下菜肴页面的实现,这个页面用于详细介绍某项菜肴或主食,如名称.图片和具体做法等.在pages文件夹里面添加一个名为foodDetail的文件夹,并在foodDet ...
- tocat 域名绑定
修改tomcat/conf/server.xml配置文件,新增部分如下 <Service name="Catalina1"> <Connector port=&q ...
- Android 音视频深入 三 MP4解码播放视频 (附源码下载)
本篇项目地址,名字是媒体解码MediaCodec,MediaExtractor,求starhttps://github.com/979451341/Audio-and-video-learning-m ...
- Uva LA 3177 - Beijing Guards 贪心,特例分析,判断器+二分,记录区间内状态数目来染色 难度: 3
题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...