• Netty---相关


    http://www.infoq.com/cn/articles/netty-million-level-push-service-design-points/

    ChannelOption用到的socket的标准参数

    • ChannelOption.SO_BACKLOG, 1024

           BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度。如果未设置或所设置的值小于1,Java将使用默认值50。

    • ChannelOption.SO_KEEPALIVE, true

          是否启用心跳保活机制。在双方TCP套接字建立连接后(即都进入ESTABLISHED状态)并且在两个小时左右上层没有任何数据传输的情况下,这套机制才会被激活。

    • ChannelOption.TCP_NODELAY, true

     在TCP/IP协议中,无论发送多少数据,总是要在数据前面加上协议头,同时,对方接收到数据,也需要发送ACK表示确认。为了尽可能的利用网络带宽,TCP总是希望尽可能的发送足够大的数据。这里就涉及到一个名为Nagle的算法,该算法的目的就是为了尽可能发送大块数据,避免网络中充斥着许多小数据块。

     TCP_NODELAY就是用于启用或关于Nagle算法。如果要求高实时性,有数据发送时就马上发送,就将该选项设置为true关闭Nagle算法;如果要减少发送次数减少网络交互,就设置为false等累积一定大小后再发送。默认为false。

    4.ChannelOption.SO_REUSEADDR, true

    SO_REUSEADDR允许启动一个监听服务器并捆绑其众所周知端口,即使以前建立的将此端口用做他们的本地端口的连接仍存在。这通常是重启监听服务器时出现,若不设置此选项,则bind时将出错。
    SO_REUSEADDR允许在同一端口上启动同一服务器的多个实例,只要每个实例捆绑一个不同的本地IP地址即可。对于TCP,我们根本不可能启动捆绑相同IP地址和相同端口号的多个服务器。
    SO_REUSEADDR允许单个进程捆绑同一端口到多个套接口上,只要每个捆绑指定不同的本地IP地址即可。这一般不用于TCP服务器。
    SO_REUSEADDR允许完全重复的捆绑:当一个IP地址和端口绑定到某个套接口上时,还允许此IP地址和端口捆绑到另一个套接口上。一般来说,这个特性仅在支持多播的系统上才有,而且只对UDP套接口而言(TCP不支持多播)

    5.ChannelOption.SO_RCVBUF AND ChannelOption.SO_SNDBUF
    定义接收或者传输的系统缓冲区buf的大小,

    6.ChannelOption.ALLOCATOR
    Netty4使用对象池,重用缓冲区
    bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
    bootstrap.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);

    ByteBuf

    http://blog.csdn.net/SpiderDog/article/category/1800249

    ByteBuf是Netty框架里最重要的类之一,简单的说,ByteBuf就是Java.nio.ByteBuffer的Netty版。

    ByteBuf逻辑结构

    正如类名所反映出来的,ByteBuf逻辑上就是一个byte容器。ByteBuf里的数据被两个指针划分为三个部分,如下图所示:

    • reader index前面的数据是已经读过的数据,这些数据可以扔掉
    • 从reader index开始,到writer index之前的数据是可读数据
    • 从writer index开始,为可写区域

    正是因为这样的设计,ByteBuf可以同时读写数据(只要可读区域和可写区域都还有空闲空间),而java.nio.ByteBuffer则必须调用flip()方法才能从写状态切换到读状态。

    ByteBuf API

    ByteBuf提供了大量的方法,比较常用的有下面这些:

    • writeXxx(xxx value) 这组方法将不同类型的数据写到buf里,同时将writerIndex往前移适当的距离
    • readXxx() 这组方法从buf里读出某种类型的数据,同时将readerIndex往前移适当的距离
    • skipBytes(int length) 将readerIndex往前移指定的距离
    • setXxx(int index, xxx value) 这组方法将不同类型的数据写到buf的指定位置
    • getXxx(int index) 这组方法从buf的指定位置读出一个某种类型的数据
    • readerIndex()/writerIndex() 访问readerIndex和writerIndex
    • readerIndex(int)/writerIndex(int) 设置readerIndex和writerIndex
    • readableBytes() 返回可读区域的字节数
    • writableBytes() 返回可写区域的字节数
    • clear() 清除buf(把readerIndex和writerIndex都设为0)
    • discardReadBytes() 扔掉已读数据

    值得一提的是,discardReadBytes()方法需要把可读数据移动到buf的开头,因此是个比较慢的操作。而clear()方法只是将两个指针清0,所以相对而言速度很快。

    ByteBufAllocator - 抽象工厂模式

    在Netty的世界里,ByteBuf实例通常应该由ByteBufAllocator来创建。ByteBuf和Allocator的关系如下图所示:

    Allocator的buffer()方法创建ByteBuf实例,ByteBuf的alloc()方法返回创建自己的Allocator。ByteBufAllocator的实现使用了抽象工厂模式,如下图所示:

    CompositeByteBuf - 组合模式

    CompositeByteBuf可以让我们把多个ByteBuf当成一个大Buf来处理,ByteBufAllocator提供了compositeBuffer()工厂方法来创建CompositeByteBuf。CompositeByteBuf的实现使用了组合模式,如下图所示:

    ByteBufInputStream - 适配器模式

    ByteBufInputStream使用适配器模式,使我们可以把ByteBuf当做Java的InputStream来使用。同理,ByteBufOutputStream允许我们把ByteBuf当做OutputStream来使用。

    比如说我们要实现一个自定义的消息协议,消息包括header和body两部分内容,body里放的是JSON字符串。那么就可以使用ByteBufInputStream来避免把ByteBuf里的字节拷贝到字节数组的开销:

    [java] view plain copy
     
    1. private Object decodeMessage(ByteBuf bb) {  
    2.     // read header  
    3.     // bb.readXxx()...  
    4.       
    5.     // read body  
    6.     InputStreamReader reader = new InputStreamReader(new ByteBufInputStream(bb));  
    7.     return new Gson().fromJson(reader, JsonObject.class);  
    8. }  

    ReadOnlyByteBuf - 装饰器模式

    ReadOnlyByteBuf用适配器模式把一个ByteBuf变为只读,ReadOnlyByteBuf通过调用Unpooled.unmodifiableBuffer(ByteBuf)方法获得:

    类似的ByteBuf适配器还包括:

    ByteBuf - 工厂方法模式

    前面也提到过了,我们很少需要直接通过构造函数来创建ByteBuf实例,而是通过Allocator来创建。从装饰器模式可以看出另外一种获得ByteBuf的方式是调用ByteBuf的工厂方法,比如:

    • ByteBuf#duplicate() 
    • ByteBuf#slice()

    ByteBufProcessor - 访问者模式还是迭代器模式?

    最后,ByteBuf提供了4个forEachByte()方法来对ByteBuf里的数据进行某种处理或查找,看起来像是访问者模式迭代器模式的混合:

    • public abstract int forEachByte(ByteBufProcessor processor);
    • public abstract int forEachByte(int index, int length, ByteBufProcessor processor);
    • public abstract int forEachByteDesc(ByteBufProcessor processor);
    • public abstract int forEachByteDesc(int index, int length, ByteBufProcessor processor);

     
     
    哔哔叭哔哄
  • 相关阅读:
    node.js抓取数据(fake小爬虫)
    认识mongoDB数据库
    node.js基础:数据存储
    mysql语句在node.js中的写法
    node.js基础:HTTP服务器
    node.js基础:模块的创建和引入
    认识node.js:express(一)
    认识Require
    认识Backbone (五)
    认识Backbone (四)
  • 原文地址:https://www.cnblogs.com/he-px/p/7365068.html
Copyright © 2020-2023  润新知