上文《Netty框架入门》说到:如果业务处理handler耗时长,将严重影响可支持的并发数。
针对这一问题,经过学习,发现了可以使用ExecutionHandler来优化。
先来回顾一下没有使用ExecutionHandler优化的流程:
    1)Boss线程(接收到客户端连接)->生成Channel->交给Worker线程池处理。
    2)某个被分配到任务的Worker线程->读完已接收的数据到ChannelBuffer->触发ChannelPipeline中的ChannelHandler链来处理业务逻辑。
    注意:执行ChannelHandler链的整个过程是同步的,如果业务逻辑的耗时较长,会将导致Work线程长时间被占用得不到释放,从而影响了整个服务器的并发处理能力。
 
一、引入ExecutionHandler优化
//HttpServerPipelineFactory.java
private final ExecutionHandler executionHandler = new ExecutionHandler(
new OrderedMemoryAwareThreadPoolExecutor(16, 1048576, 1048576));
public class HttpServerPipelineFactory implements ChannelPipelineFactory {
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("encoder", new HttpResponseEncoder());
pipeline.addLast("execution", executionHandler);
pipeline.addLast("handler", new HttpServerHandler());
return pipeline;
}
}
    当我们引入ExecutionHandler后,原本同步的ChannelHandler链在经过 ExecutionHandler后就结束了,它会被ChannelFactory的worker线程池所回收,而剩下的ChannelHandler链将由ExecutionHandler的线程池接手处理。
    对于ExecutionHandler需要的线程池模型,Netty提供了两种可选:
        1) MemoryAwareThreadPoolExecutor 通过对线程池内存的使用控制,可控制Executor中待处理任务的上限(超过上限时,后续进来的任务将被阻塞),并可控制单个Channel待处理任务的上限,防止内存溢出错误。但是它不维持同一Channel的ChannelEvents秩序,当经过ExecutionHandler后的ChannelHandler链中有不止一个Handler时,这些事件驱动存在混乱的可能。例如:
 ----------------------------------------> Timeline ------------------------------------->
Thread X: --- Channel A (Event 2) --- Channel A (Event 1) ----------------------------->
Thread Y: --- Channel A (Event 3) --- Channel B (Event 2) --- Channel B (Event 3) --->
Thread Z: --- Channel B (Event 1) --- Channel B (Event 4) --- Channel A (Event 4) --->
        2) OrderedMemoryAwareThreadPoolExecutor 是 MemoryAwareThreadPoolExecutor 的子类。除了MemoryAwareThreadPoolExecutor 的功能之外,它还可以保证同一Channel中处理的事件流的顺序性(不同Channel使用不同的key保持事件顺序),这主要是控制事件在异步处理模式下可能出现的错误事件顺序,但它并不保证同一 Channel中的事件都在一个线程中执行(通常也没必要)。例如:

----------------------------------------> Timeline ---------------------------------------->
Thread X: --- Channel A (Event 1) --. .-- Channel B (Event 2) --- Channel B (Event 3) --->
\ /
X
/ \
Thread Y: --- Channel B (Event 1) --' '-- Channel A (Event 2) --- Channel A (Event 3) --->
二、具有可伸缩性的OrderedMemoryAwareThreadPoolExecutor使用策略
    在大多数情况下,我们会使用OrderedMemoryAwareThreadPoolExecutor,它的构造函数要求我们提供线程池的大小,在上面的代码中,我们使用了16这个具体的值,是一种很不好的写法,通常情况下,我们会使用配置文件使之可变,但是在实际部署时,并不能保证实施人员能很好的去调整,故提供如下的一种写法:
double coefficient = 0.8;  //系数
int numberOfCores = Runtime.getRuntime().availableProcessors();
int poolSize = (int)(numberOfCores / (1 - coefficient));

我们可以使用poolSize取代OrderedMemoryAwareThreadPoolExecutor(16, 1048576, 1048576)中的那个16,因为当一个系统被开发出来后,它是CPU密集型还是IO密集型是可评估的,通过评估其密集型,调整系数即可:CPU密集型接近0,IO密集型接近1。

Netty并发优化之ExecutionHandler的更多相关文章

  1. Nginx 之六: Nginx十万并发优化

    操作 操作 Nginx 之六: Nginx十万并发优化

  2. 性能调优之MYSQL高并发优化

    性能调优之MYSQL高并发优化   一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之 ...

  3. 【JAVA】高并发优化细节点

    高并发优化细节点: 微服务化 如何发现系统瓶颈?   如何高效利用有限内存: 使用基本类型 使用数组,不用集合 自定义map与数据结构   Integer—>int, Set<Intege ...

  4. LNMP环境并发优化

    LNMP环境并发优化 服务器 8核32Gx3 如图是一条http请求的生命周期,共经过nginx,php-fpm,PHP三个模块 所以我们可以从nginx,php-fpm,PHP三个维度去优化 一.p ...

  5. Tomcat并发优化和缓存优化

    Tomcat并发优化 1.调整连接器connector的并发处理能力 在Tomcat 配置文件 server.xml 中的 <Connector ... /> 配置中 1.参数说明 max ...

  6. Java高并发秒杀API之高并发优化

    ---恢复内容开始--- 第1章 秒杀系统高并发优化分析   1.为什么要单独获得系统时间 访问cdn这些静态资源不用请求系统服务器 而CDN上没有系统时间,需要单独获取,获取系统时间不用优化,只是n ...

  7. SSM实战——秒杀系统之高并发优化

    一:高并发点 高并发出现在秒杀详情页,主要可能出现高并发问题的地方有:秒杀地址暴露.执行秒杀操作. 二:静态资源访问(页面)优化——CDN CDN,内容分发网络.我们把静态的资源(html/css/j ...

  8. netty 并发访问测试配置

    linux – 1.查看有关的选项 /sbin/sysctl -a|grep net.ipv4.tcp_tw     net.ipv4.tcp_tw_reuse = 0     #表示开启重用.允许将 ...

  9. Java 进阶7 并发优化 5 并发控制板方法

    Java 进阶7 并发优化 5 并发控制板方法 20131114 前言:          Java 中多线程并发程序中存在线程安全的问题,之前学习 Java的同步机制,掌握的同步方法只有一种就是使用 ...

随机推荐

  1. 【数据库_Mysql】<foreach>标签在Mysql中的使用

    foreach属性 属性 描述 item 循环体中的具体对象.支持属性的点路径访问,如item.age,item.info.details.具体说明:在list和数组中是其中的对象,在map中是val ...

  2. BZOJ4892 Tjoi2017dna(后缀数组)

    对每个子串暴力匹配至失配三次即可.可以用SA查lcp.然而在bzoj上被卡常了.当然也可以二分+哈希或者SAM甚至FFT. #include<iostream> #include<c ...

  3. 题解 P1334 【瑞瑞的木板】

    声明:本题解已经与其他题解重合, ### 且存在压行情况. 首先,这个题解是我有了惨痛的教训:全部WA... 先发一个CODE做声明: #include <bits/stdc++.h> / ...

  4. mysql互为主从复制配置笔记--未读,稍后学习

    MySQL-master1:192.168.72.128 MySQL-master2:192.168.72.129 OS版本:CentOS 5.4MySQL版本:5.5.9(主从复制的master和s ...

  5. Linux(六)shell操作实用技巧

    一.shell操作日期时间 linux 系统为我们提供了一个命令 date,专门用来显示或者设置系统日期时间的.      语法格式为:      date [OPTION]... [+FORMAT] ...

  6. bzoj2956: 模积和(数论)

    先算出无限制的情况,再减去i==j的情况. 无限制的情况很好算,有限制的情况需要将式子拆开. 注意最后的地方要用平方和公式,模数+1是6的倍数,于是逆元就是(模数+1)/6 #include<i ...

  7. NOIP计划与展望

        进入高中一个月了,NOIP这项尤为重要的赛事也即将到来.     这一个月来,烦恼多过一切,文化课的压力,作业的压力,老师的压力,需要自己一一去克服,前一个问题刚解决,后一个问题又出现,每天走 ...

  8. Linux之GDB调试介绍与应用20170601

    一.GDB调试命令   描述 backtrace(或bt) 查看各级函数调用及参数 finish 连续运行到当前函数返回为止,然后停下来等待命令 frame(或f) 帧编号 选择栈帧 info(或i) ...

  9. CentOS 7网络故障

    By francis_hao    Nov 2,2017   在像往常一样打开了虚拟机后,打开xshell准备连接到centos,可是连不上,发现连接的网卡没有启动,使用systemctl启动netw ...

  10. Spring使用注解方式就行事务管理

    使用步骤: 步骤一.在spring配置文件中引入<tx:>命名空间<beans xmlns="http://www.springframework.org/schema/b ...