黃文亮
(湖南省婦幼保健院,長沙 410008)
Kotlin協(xié)程技術在網絡開發(fā)中的應用
黃文亮
(湖南省婦幼保健院,長沙 410008)
隨著互聯網的發(fā)展,新的技術與開發(fā)框架不斷涌現,vertx-web是較有代表性的新型網絡開發(fā)框架之一,而Kotlin則是剛剛成為Android開發(fā)語言的一款新的JVM語言,并于最新版本宣布支持協(xié)程技術,將兩者結合使用會有何效果,就此展開研究。
網絡開發(fā);異步編程;vertx;Kotlin
當前,網絡用戶量不斷增長,傳統(tǒng)的網站架構應對高并發(fā)請求顯得越來越低效,各種異步網絡編程架構也應運而生,vertx-web是其中的一款優(yōu)秀產品,能夠支持JVM平臺上的各種語言,并且完全開源。
在傳統(tǒng)的thread per request servlet模式下,每個HTTP請求的處理函數內部的任務都是同步依次執(zhí)行,而線程占用的資源和切換的帶價都比較高,如果中間有阻塞任務(例如文件讀寫或數據庫操作)就更為嚴重;新型的異步框架一般是在底層使用一個線程池,然后由框架對子任務進行分配,最大化地減少線程數量和切換次數。在使用異步框架進行開發(fā)的情況下,如何在一個任務完成后繼續(xù)執(zhí)行接下來的其他任務,而不掛起主線程,是一個重點問題,最基礎的方式是使用回調函數,但有多個任務需要依次執(zhí)行時,回調的嵌套層數不斷增加,會大大提高維護和調試的難度。
Kotlin語言剛剛推出的協(xié)程特性是解決異步回調問題的利器,這里我們將研究它與vertx-web結合使用的效果。
vertx-web已經為我們提供了基本的網絡請求監(jiān)聽以及路由功能,現在需要做的就是在處理請求的函數中,將可能阻塞主線程的任務(例如數據庫操作和文件讀寫)異步執(zhí)行,執(zhí)行完畢后再回到主線程進行下一步的處理。
vertx對這種場景提供了一種自帶的使用回調函數的處理方法,即executeBlocking接口:
這里我們將使用三種不同方式來執(zhí)行Web處理器中的阻塞任務:1.同步處理;2.使用vertx回調函數方式;3.使用kotlin協(xié)程。
Kotlin協(xié)程是通過編譯技術實現(不需要虛擬機VM/操作系統(tǒng)OS的支持),通過插入相關代碼來生效,與其他語言中的協(xié)程(例如golang)類似,具有相對于線程小得多的內存占用和極快的切換速度。Kotlin協(xié)程針對Java8提供了lauch函數(啟動無返回值的協(xié)程),future函數(啟動需要捕獲返回值的協(xié)程)和await函數(掛起父協(xié)程,異步等待子協(xié)程返回的結果),這樣在代碼結構上就實現了類似java.util.concurrent.Future#get()的同步代碼寫法,而又不會阻塞父線程。
程序啟動流程描述:
1.創(chuàng)建Verticle對象(vertx框架中的最小應用單元),設置 3個路由:/mode1,/mode2,/mode3分別對應三種不同的處理方法:同步處理函數,vertx異步回調處理函數,Kotlin協(xié)程處理函數。
2.啟動HTTP服務對象,監(jiān)聽網絡請求(使用8088端口)。
測試方式描述:
使用HTTP客戶端測試工具模擬大批量并發(fā)HTTP請求,發(fā)往localhost:8088端口,查看并發(fā)量、響應時間和錯誤率等,并觀察是否有卡死或內存溢出現象。
各處理器邏輯:
1.同步處理函數
接收到HTTP請求后,直接同步讀取文件,讀取完成后響應HTTP請求,向客戶端輸出文本。該過程會阻塞線程,實際性能相當于傳統(tǒng)的thread per request servlet
2.vertx異步回調處理函數
接收到HTTP請求后,調用vertx.executeBlocking接口,注冊回調函數,分別用于讀取文件內容和獲取讀文件結果,響應HTTP請求,各個回調函數將被分配給vertx底層的線程池依次執(zhí)行。該過程不阻塞主線程。
3.Kotlin協(xié)程處理函數
接收到HTTP請求后,創(chuàng)建一個父協(xié)程用于調度,然后在內部創(chuàng)建子協(xié)程用于讀取文件,執(zhí)行子協(xié)程時可以使用await方法掛起父協(xié)程,使代碼邏輯結構接近同步代碼。該過程不阻塞主線程。
程序中的關鍵代碼如下:
這里我們?yōu)榱耸钩绦驁?zhí)行情況更接近實際業(yè)務,使用了一個隨機數來模擬真實業(yè)務中的阻塞與非阻塞任務比例(例如可以直接讀緩存的查詢就可以立即返回),只有25%的請求被判斷為需要執(zhí)行阻塞操作,阻塞操作使用線程的Thread.sleep來進行模擬,每個請求中掛起兩次,每次50毫秒。
第一種實現方式代碼最為簡單,就是直接以同步方式執(zhí)行,未作任何特殊處理,理論上該方式只能應對較低的并發(fā)數,每個任務都阻塞主線程將會大大降低vertx主線程接收請求的能力,并有超時風險。
第二種實現方式就是vertx自帶的異步處理邏輯,用executeBlocking接口分配異步任務給底層線程池處理,可以看到代碼中出現了兩層嵌套的回調結構,當需要執(zhí)行多個阻塞任務時,將會產生較復雜的嵌套,即“callback hell”,難以調試和維護,但這種方式性能要遠高于第一種。
第三種方式是使用Kotlin協(xié)程。這里我們使用了父子兩個協(xié)程,這是因為子任務內部有一個阻塞操作,在該阻塞操作完成之前,外部程序需要掛起等待,而Kotlin的協(xié)程掛起操作必須在一個協(xié)程的內部進行,所以在外部另啟動了一個協(xié)程。父協(xié)程相當于普通程序中的主線程,而await操作則類似于線程中的join(但協(xié)程掛起的代價遠遠小于線程掛起)。當需要執(zhí)行多個阻塞任務時,第二個或更多的子協(xié)程可以直接跟在第一個子協(xié)程后面,寫法完全類似于同步代碼,不會產生多層嵌套結構。
第二種和第三種實現理論上并發(fā)性能應在同一級別。
這里我們使用apache-jeter工具來模擬HTTP客戶端進行高并發(fā)請求測試。測試參數配置如下:
線程組數量:1,線程數量:100,循環(huán)次數:10,服務器名:localhost
請求路徑1:/mode1(對應同步處理器)
請求地址2:/mode2(對應vertx回調處理器
請求地址3:/mode3(對應Kotlin協(xié)程處理器)
目標端口: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%以下,內存占用率由于測試客戶端提前分配了線程,測試過程中幾乎沒有發(fā)生變化,也就是說,服務端只使用了預分配的內存就完全響應了所有請求,由此可見vertx-web+Kot?lin協(xié)程組合的高并發(fā)性能是十分強勁的。
本文對新型網絡開發(fā)框架vertx-web與新型異步編程技術Kotlin協(xié)程的結合使用展開了探索,并給出了具體實現,經過實際測試對比,該方案確實能提供優(yōu)異的并發(fā)性能,同時還具有協(xié)程的易于開發(fā)、調試和維護的特點,兼顧了程序性能和開發(fā)易用性,有助于快速開發(fā)高性能的網絡應用。
[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