繁杂网络IO型业务的分析及探索--协程和响应式

尝试优化业务中发现,服务的心跳信息中有很多线程都是处于 waiting ,如下图所示:
thread count="608" 
daemon-count="420" 
peak-count="611" 
total-started-count="13722" 
deadlocked="0" new="0" runnable="169" blocked="0" 
waiting="314"
复制代码

然后看了CPU的使用率,从左到右分别表示CPU的任务等待数/CPU核数CPU的执行时间占比总时间(CPU执行时间+CPU空闲时间+ CPU等待时间)当前JAVA进程执行时间占比总时间

 

 

 

图中可以清晰地看到,并不是计算型业务导致了线程等待,而是极大可能由于服务到底层数据查询的网络IO等待使得排队的线程增加,因此决定考虑优化这一部分。优化的目标,在保证服务和底层存储的心跳信息在一个安全的范围内,尽可能的增加服务吞吐能力。

思路一协程

当时优化的第一时间就想到了大名鼎鼎的quasar三方库。quasar可以理解为轻量级的线程实现,熟悉go语言一定知道goroutine,我们知道Java语言中不支持协程,业务中很多场景都需要用线程池进行优化,但是使用线程池的成本也很高,无论是内存占用还是线程之间的切换消耗,都限制了一个应用不能无限制的创建线程。

好在社区开源了一款Java coroutine框架quasar,容我先吐槽一下,这个框架真的是直男程序员写的(已经被拉去写JDK的协程,十分期待JDK能早点支持协程),文档十分匮乏,导致我本地开始搞得时候就报错了一把,开局体验不是很舒服。

当然优点也十分突出,应用中网络IO耗时占比比较突出的场景中,使用quasar可以极大的提高CPU的吞吐率。简单描述就是可以在更短的时间内处理更多的请求。不会因为一个线程中的网络IO堵塞而让后面的线程处于waiting中,堵塞的时候CPU是不干活的,因此将整个系统的吞吐率拉胯。

官网的文档中提供了两种使用方式,为了节约篇幅先用第1种方式示范一下使用方式:

  1. Running the Instrumentation Java Agent(加载器织入)

  2. Ahead-of-Time (AOT) Instrumentation(预编译织入)

这里我先用Gradle项目作为🌰来详解一下怎么使用。

一、Gradle配置模块


configurations {
    quasar
}
//
tasks.withType(JavaExec) {
    jvmArgs "-javaagent:${configurations.quasar.iterator().next()}"
}
//
dependencies {
    compile "org.antlr:antlr4:4.7.2"
    compile "co.paralleluniverse:quasar-core:0.7.5"
    quasar "co.paralleluniverse:quasar-core:0.7.5:jdk8@jar"
    testCompile group: 'junit', name: 'junit', version: '4.12'
}
复制代码

复制代码

 

二、实现一个耳熟能详的echo服务器

两个Fiber(相当于是Java的Thread)相互通信,increasing发送一个int数字给echoecho收到之后返回给increasingincreasing接收到echo返回的消息,先打印,在执行++操作,然后打印出最后的结果。代码示例如下:

  1. increasing

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值