技术点描述

本文主要研究NioServerSocketChannelFactory类和NioDatagramChannelFactory类,

以及这两个类的各自作用。

由于基于pipelineFactory的线程池的配置已在前一节(Netty中execution包功能详解 )中做了详细说明,而channelFactory中的线程池的配置并未做说明,本文档重点阐述channelFactory的线程池配置。NioServerSocketChannelFactory主要应用于TCP协议的数据处理,NioDatagramChannelFactory主要应用于UDP协议的数据处理。

实现方案

简单介绍一下实现该功能,使用了哪些技术或知识点

参考源码包

以下是对这两个类的具体说明以及相关类,重要的常用的方法的说明

  1. NioServerSocketChannelFactory

此类常用于创建TCP的ServerBootstrap时作为构造方法的参数使用。

调用方式及设置如下:

 ChannelFactory TCPCHANNEL_FACTORY = new NioServerSocketChannelFactory(

 Executors.newCachedThreadPool(), Executors.newCachedThreadPool());

 ServerBootstrap TCPSERVER_BOOTSTRAP = new ServerBootstrap(TCPCHANNEL_FACTORY);

基于NIO的用于创建服务器端channel的channelFactory,这个类利用非阻塞I/O模式引入NIO,这样可以有效地向多个并发连接提供Channel

线程的工作模式:

在此类中,有两种类型的线程,一种是boss线程,另一种是worker线程

Boss线程:

每个server服务器都会有一个boss线程,每绑定一个InetSocketAddress都会产生一个boss线程,比如:我们开启了两个服务器端口80和443,则我们会有两个boss线程。一个boss线程在端口绑定后,会接收传进来的连接,一旦连接接收成功,boss线程会指派一个worker线程处理连接。

Worker线程:

一个NioServerSocketChannelFactory会有一个或者多个worker线程。一个worker线程在非阻塞模式下为一个或多个Channels提供非阻塞 读或写

线程的生命周期和优雅的关闭

在NioServerSocketChannelFactory被创建的时候,所有的线程都会从指定的Executors中获取。Boss线程从bossExecutor中获取,worker线程从workerExecutor中获取。因此,我们应该准确的指定Executors可以提供足够数量的线程,最好的选择就是指定一个cached线程池(It is the best bet to specify a cached thread pool)。

此处发现所有源码中的例子(example)中均设置为Executors.newCachedThreadPool()

Boss线程和worker线程都是懒加载,没有程序使用的时候要释放掉。当boss线程和worker线程释放掉的时候,所有的相关资源如Selector也要释放掉。因此,如果想要优雅的关闭一个服务,需要做一下事情:

  1. 对factory创建的channels执行解绑(unbind)操作
  2. 关闭所有的由解绑的channels处理的子channels(这两步目前通常通过ChannelGroup.close()来操作)
  3. 调用releaseExternalResources()方法

请确保在所有的channels都关闭前不要关闭executor,否则,会报RejectedExecutionException异常而且相关资源可能不会被释放掉。

在此类中,最关键的构造方法:

 public NioServerSocketChannelFactory(

 Executor bossExecutor, WorkerPool<NioWorker> workerPool) {

 if (bossExecutor == null) {

 throw new NullPointerException("bossExecutor");

 }

 if (workerPool == null) {

 throw new NullPointerException("workerPool");

 }

 this.bossExecutor = bossExecutor;

 this.workerPool = workerPool;

 sink = new NioServerSocketPipelineSink(workerPool);

 }

参数说明:

bossExecutor:默认推荐设置为Executors.newCachedThreadPool()

workerPool:可通过new NioWorkerPool(workerExecutor, workerCount, true)创建,workerExecutor默认推荐设置为Executors.newCachedThreadPool(),workerCount可设置为Runtime.getRuntime().availableProcessors() * 2(默认)

关于其中的NioWorkerPool类和NioServerSocketPipelineSink类,将在下文给予说明。

  1. NioWorkerPool

此类的关键方法是super的AbstractNioWorkerPool,

构造方法:

 AbstractNioWorkerPool(Executor workerExecutor, int workerCount, boolean allowShutDownOnIdle) {

 …

 }

参数说明:

workerExecutor:worker线程的Executor

workerCount:最多创建的worker线程数

allowShutDownOnldle:空闲时是否关闭线程

  1. NioServerSocketPipelineSink

内部组件,传输服务的一个实现类,大多数情况下,不对用户开放。

  1. NioDatagramChannelFactory

此类常用于创建UDP的ServerBootstrap时作为构造方法的参数使用。

调用方式及设置如下:

 ChannelFactory UDPCHANNEL_FACTORY = new NioDatagramChannelFactory()

 ConnectionlessBootstrap UDPSERVER_BOOTSTRAP = new ConnectionlessBootstrap(UDPCHANNEL_FACTORY);

这个类利用非阻塞I/O模式引入NIO,这样可以有效地向多个并发连接提供Channel

此类仅有一种线程类型:worker线程。一个NioDatagramChannelFactory可创建一个或多个worker线程,一个worker线程在非阻塞模式下为一个或多个Channels提供非阻塞 读或写

在NioDatagramChannelFactory被创建的时候,所有的线程都会从指定的Executors中获取

因此,我们应该准确的指定Executors可以提供足够数量的线程,最好的选择就是指定一个cached线程池(It is the best bet to specify a cached thread pool)。

所有的worker线程都是懒加载,没有程序使用的时候要释放掉。当worker线程释放掉的时候,所有的相关资源如Selector也要释放掉。因此,如果想要优雅的关闭一个服务,需要做一下事情:

通常通过ChannelGroup.close()来关闭所有的由此factory创建的channels

调用releaseExternalResources()方法

请确保在所有的channels都关闭前不要关闭executor,否则,会报RejectedExecutionException异常而且相关资源可能不会被释放掉。

不支持多播模式,如果需要多播模式支持,采用OioDatagramChannelFactory替代

以下是此类中的最重要的构造方法:

public NioDatagramChannelFactory(WorkerPool<NioDatagramWorker> workerPool, InternetProtocolFamily family) {

…

}

参数说明:

workerPool:参考NioServerSocketChannelFactory

family:网络协议系列,这个参数是为了UDP的多播模式的,此参数只在java7+版本才有效。默认为null,可通过StandardProtocolFamily.INET(Ipv4)或者StandardProtocolFamily.INET6(Ipv6)设置

Netty多线程处理机制的更多相关文章

  1. Netty 超时机制及心跳程序实现

    Netty 超时机制的介绍 Netty 的超时类型 IdleState 主要分为: ALL_IDLE : 一段时间内没有数据接收或者发送 READER_IDLE : 一段时间内没有数据接收 WRITE ...

  2. netty心跳机制测试

    netty中有比较完善的心跳机制,(在基础server版本基础上[netty基础--基本收发])添加少量代码即可实现对心跳的监测和处理. 1 server端channel中加入心跳处理机制 // Id ...

  3. 连接管理 与 Netty 心跳机制

    一.前言 踏踏实实,动手去做,talk is cheap, show me the code.先介绍下基础知识,然后做个心跳机制的Demo. 二.连接 长连接:在整个通讯过程,客户端和服务端只用一个S ...

  4. Netty心跳机制

    一.概念介绍网络中的接收和发送数据都是使用操作系统中的SOCKET进行实现.但是如果此套接字已经断开,那发送数据和接收数据的时候就一定会有问题.可是如何判断这个套接字是否还可以使用呢?这个就需要在系统 ...

  5. NETTY 心跳机制

    最近工作比较忙,但闲暇之余还是看了阿里的冯家春(fengjiachun)的github上的开源代码Jupiter,写的RPC框架让我感叹人外有人,废话不多说,下面的代码全部截取自Jupiter,写了一 ...

  6. 数据库的设计:深入理解 Realm 的多线程处理机制

    你已经阅读过 Realm 关于线程的基础知识.你已经知道了在处理多线程的时候你不需要关心太多东西了,因为强大的 Realm 会帮你处理好这些,但是你还是很想知道更多细节…… 你想知道在 Realm 的 ...

  7. 浅谈利用PLSQL的多线程处理机制,加快处理大数据表的效率

    我们在处理大数据表的时候经常会感觉的处理速度不够快,效率不够高,那么今天下面我就来简单实现下PLSQL的多线程编程处理数据: 我模拟一个简单的场景,把某一张表中的数据(当然这张表的数据非常大)同步到目 ...

  8. netty心跳机制和断线重连(四)

    心跳是为了保证客户端和服务端的通信可用.因为各种原因客户端和服务端不能及时响应和接收信息.比如网络断开,停电 或者是客户端/服务端 高负载. 所以每隔一段时间 客户端发送心跳包到客户端  服务端做出心 ...

  9. netty心跳机制解决

    直接看别个的源码:https://blog.csdn.net/xt8469/article/details/84827443>>https://blog.csdn.net/xt8469/a ...

随机推荐

  1. 自定义HBase的协处理器(Observer)

    自定义一个Observer... 总共分五步: 1°.继承BaseMasterObserver  (写代码  具体看博客....) 案例(当在HBase中创建表的时候在日志中有相关输出): impor ...

  2. 转: Android开发中的MVP架构详解(附加链接比较不错)

    转: http://www.codeceo.com/article/android-mvp-artch.html 最近越来越多的人开始谈论架构.我周围的同事和工程师也是如此.尽管我还不是特别深入理解M ...

  3. Flexible 弹性盒子模型之CSS flex-direction

    实例 设置 <div> 元素内弹性盒元素的方向为相反的顺序: div { display:flex; flex-direction:row-reverse; } 复制 效果预览 浏览器支持 ...

  4. BZOJ 2962

    2962: 序列操作 Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 618  Solved: 225[Submit][Status][Discuss] ...

  5. 【改进】用Log4net建立日志记录

    上一篇随笔中只使用了普通的文件读写来进行日志的写入,正如很多朋友说的,频繁的对文件进行读写会造成很多的问题,代码缺少边界控制和操作控制,没有对资源进行管理,是非常典型的bad code. 然后经过前辈 ...

  6. Java Concurrency - Lock

    Lock 是 Java API 提供的另一种线程同步机制,它提供了比 synchronized 关键字更为灵活.强大的锁定操作. 锁是控制多个线程对共享资源进行访问的工具.通常,所提供了对共享资源的独 ...

  7. 整合Spring与Hibernate

    在学习spring的时候,要整合hibernate,本来是看起来挺简单的,但是遇到的远要比想到了多,而且多很多,期间几天一个bug实在难调,几度放弃,但终究柳暗花明,抑制不住喜悦就想着分享一下成果吧. ...

  8. android NDK 开发步骤

    NDK开发一般分为一下几个步骤:(默认你已经安装好了NDK和android开发环境) 1.创建一个项目 2.创建JNI目录 3.编写nativejava层方法 4.生成JNI头文件 (1)编写java ...

  9. 改变UITextField placeHolder 字体 颜色

    [_textSearchField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"]; ...

  10. 20141015--for语句2

    for语句,打印等腰三角形: 第一种方法:(使用for语句嵌套) 第二种方法:(定义string型变量) 以下是其他形状的等腰三角形: (穿插使用了for语句嵌套,定义string型)