Kotlin协程技术在网络开发中的应用

2017-12-27 03:37黄文亮
现代计算机 2017年33期
关键词:主线线程代码

黄文亮

(湖南省妇幼保健院,长沙 410008)

Kotlin协程技术在网络开发中的应用

黄文亮

(湖南省妇幼保健院,长沙 410008)

随着互联网的发展,新的技术与开发框架不断涌现,vertx-web是较有代表性的新型网络开发框架之一,而Kotlin则是刚刚成为Android开发语言的一款新的JVM语言,并于最新版本宣布支持协程技术,将两者结合使用会有何效果,就此展开研究。

网络开发;异步编程;vertx;Kotlin

0 引言

当前,网络用户量不断增长,传统的网站架构应对高并发请求显得越来越低效,各种异步网络编程架构也应运而生,vertx-web是其中的一款优秀产品,能够支持JVM平台上的各种语言,并且完全开源。

在传统的thread per request servlet模式下,每个HTTP请求的处理函数内部的任务都是同步依次执行,而线程占用的资源和切换的带价都比较高,如果中间有阻塞任务(例如文件读写或数据库操作)就更为严重;新型的异步框架一般是在底层使用一个线程池,然后由框架对子任务进行分配,最大化地减少线程数量和切换次数。在使用异步框架进行开发的情况下,如何在一个任务完成后继续执行接下来的其他任务,而不挂起主线程,是一个重点问题,最基础的方式是使用回调函数,但有多个任务需要依次执行时,回调的嵌套层数不断增加,会大大提高维护和调试的难度。

Kotlin语言刚刚推出的协程特性是解决异步回调问题的利器,这里我们将研究它与vertx-web结合使用的效果。

1 解决思路

vertx-web已经为我们提供了基本的网络请求监听以及路由功能,现在需要做的就是在处理请求的函数中,将可能阻塞主线程的任务(例如数据库操作和文件读写)异步执行,执行完毕后再回到主线程进行下一步的处理。

vertx对这种场景提供了一种自带的使用回调函数的处理方法,即executeBlocking接口:

这里我们将使用三种不同方式来执行Web处理器中的阻塞任务:1.同步处理;2.使用vertx回调函数方式;3.使用kotlin协程。

Kotlin协程是通过编译技术实现(不需要虚拟机VM/操作系统OS的支持),通过插入相关代码来生效,与其他语言中的协程(例如golang)类似,具有相对于线程小得多的内存占用和极快的切换速度。Kotlin协程针对Java8提供了lauch函数(启动无返回值的协程),future函数(启动需要捕获返回值的协程)和await函数(挂起父协程,异步等待子协程返回的结果),这样在代码结构上就实现了类似java.util.concurrent.Future#get()的同步代码写法,而又不会阻塞父线程。

程序启动流程描述:

1.创建Verticle对象(vertx框架中的最小应用单元),设置 3个路由:/mode1,/mode2,/mode3分别对应三种不同的处理方法:同步处理函数,vertx异步回调处理函数,Kotlin协程处理函数。

2.启动HTTP服务对象,监听网络请求(使用8088端口)。

测试方式描述:

使用HTTP客户端测试工具模拟大批量并发HTTP请求,发往localhost:8088端口,查看并发量、响应时间和错误率等,并观察是否有卡死或内存溢出现象。

各处理器逻辑:

1.同步处理函数

接收到HTTP请求后,直接同步读取文件,读取完成后响应HTTP请求,向客户端输出文本。该过程会阻塞线程,实际性能相当于传统的thread per request servlet

2.vertx异步回调处理函数

接收到HTTP请求后,调用vertx.executeBlocking接口,注册回调函数,分别用于读取文件内容和获取读文件结果,响应HTTP请求,各个回调函数将被分配给vertx底层的线程池依次执行。该过程不阻塞主线程。

3.Kotlin协程处理函数

接收到HTTP请求后,创建一个父协程用于调度,然后在内部创建子协程用于读取文件,执行子协程时可以使用await方法挂起父协程,使代码逻辑结构接近同步代码。该过程不阻塞主线程。

2 实现

程序中的关键代码如下:

这里我们为了使程序执行情况更接近实际业务,使用了一个随机数来模拟真实业务中的阻塞与非阻塞任务比例(例如可以直接读缓存的查询就可以立即返回),只有25%的请求被判断为需要执行阻塞操作,阻塞操作使用线程的Thread.sleep来进行模拟,每个请求中挂起两次,每次50毫秒。

第一种实现方式代码最为简单,就是直接以同步方式执行,未作任何特殊处理,理论上该方式只能应对较低的并发数,每个任务都阻塞主线程将会大大降低vertx主线程接收请求的能力,并有超时风险。

第二种实现方式就是vertx自带的异步处理逻辑,用executeBlocking接口分配异步任务给底层线程池处理,可以看到代码中出现了两层嵌套的回调结构,当需要执行多个阻塞任务时,将会产生较复杂的嵌套,即“callback hell”,难以调试和维护,但这种方式性能要远高于第一种。

第三种方式是使用Kotlin协程。这里我们使用了父子两个协程,这是因为子任务内部有一个阻塞操作,在该阻塞操作完成之前,外部程序需要挂起等待,而Kotlin的协程挂起操作必须在一个协程的内部进行,所以在外部另启动了一个协程。父协程相当于普通程序中的主线程,而await操作则类似于线程中的join(但协程挂起的代价远远小于线程挂起)。当需要执行多个阻塞任务时,第二个或更多的子协程可以直接跟在第一个子协程后面,写法完全类似于同步代码,不会产生多层嵌套结构。

第二种和第三种实现理论上并发性能应在同一级别。

3 性能测试及分析

这里我们使用apache-jeter工具来模拟HTTP客户端进行高并发请求测试。测试参数配置如下:

线程组数量:1,线程数量:100,循环次数:10,服务器名:localhost

请求路径1:/mode1(对应同步处理器)

请求地址2:/mode2(对应vertx回调处理器

请求地址3:/mode3(对应Kotlin协程处理器)

目标端口:8088,http method:GET

流量定时器限制:target throughput(in samples per minute)=240000.0(即每秒 4000)

测试输出数据如下:

图1

图2

可以看到/mode1的最大响应时间高达6.2秒,平均响应时间和中位数响应时间都超过了2.7秒,这主要是由于每个请求都阻塞了vertx调度线程,后面的请求自然不得不浪费大量的时间用于等待。而/mode2和/mode3的表现都相当不错,最大响应时间分别控制在了300毫秒和200毫秒,/mode3的中位数响应时间甚至只有1毫秒。

图3

同时,/mode2和/mode3的CPU占用率只在极短时间内超过了90%,大部分时间维持在20%以下,内存占用率由于测试客户端提前分配了线程,测试过程中几乎没有发生变化,也就是说,服务端只使用了预分配的内存就完全响应了所有请求,由此可见vertx-web+Kot⁃lin协程组合的高并发性能是十分强劲的。

4 结语

本文对新型网络开发框架vertx-web与新型异步编程技术Kotlin协程的结合使用展开了探索,并给出了具体实现,经过实际测试对比,该方案确实能提供优异的并发性能,同时还具有协程的易于开发、调试和维护的特点,兼顾了程序性能和开发易用性,有助于快速开发高性能的网络应用。

[1]Roman Elizarov.Module Kotlinx-coroutines-jdk8[DB/OL].https://github.com/Kotlin/kotlinx.coroutines/blob/master/integration/kotlinx-coroutines-jdk8/README.md,2017-5-17.

Kotlin Coroutine in Web Development

HUANG Wen-liang
(Maternal and Child Health Hospital of Hunan,Changsha 410008)

With the development of the Internet technology and the emergence of new development framework,vertx-web is one of the representative of the new network development framework,Kotlin is Android's official language development has just become a new JVM language,which announced support Coroutine technology in the latest version,so as to study the combine effect on them.

Web Development;Async Coding;Vertx;Kotlin

1007-1423(2017)33-0080-05

10.3969/j.issn.1007-1423.2017.33.019

黄文亮(1987-),男,湖南长沙人,软件工程师,本科

2017-10-12

2017-11-20

猜你喜欢
主线线程代码
实时操作系统mbedOS 互斥量调度机制剖析
浅析体育赛事售票系统错票问题的对策研究
人物报道的多维思考、主线聚焦与故事呈现
8月汇市行情背后的三大主线
更加突出主线 落实四个到位 推动主题教育取得实实在在成效
创世代码
创世代码
创世代码
创世代码
数字主线