劉健 黃才勝
摘要:本文運用goroutine的簡便特點研發了webgo架構,通過對比webgo架構和beego架構可以看出融入協程思想的高并發架構更有優勢。
關鍵詞:計算機;軟件;協程;高并發結構
中圖分類號:TP311.52 文獻標識碼:A 文章編號:1007-9416(2018)04-0085-02
隨著我國網絡建設的不斷發展,軟件研發產業也進入了發展的快車道,越來越多的網頁以及應用軟件應運而生,如何提高網絡的效率和便捷性日益成為人們關注的焦點。相比于傳統網絡來說,如今網民對網絡的要求更高,使用頻率也更高,為了滿足廣大網民對計算機系統的高要求,軟件工程師們加大了對計算機高并發架構的研發力度。雖然物理結構上的改變能夠高并發,但是這種改變需要大量的服務器,運行成本將大幅度增加,另外,由于線程的數量有限,因此,本文利用協程的思想進行多線程的程序設計。
1 協程
1.1 協程定義
所謂協程,其實是一套簡便程序組件,協程比傳統的線程使用起來更為簡單輕巧[1]。進程與線程是操作系統中的兩種結構,通過交叉結合使用進程與線程可以讓計算機的操作系統出于多種運行模式下。對于單核CPU來說,每次僅調用單個進程或線程。調度內核能夠使進程與線程交替獲得CPU資源,從而把使用者所提交的作業化整為零。
協程與進程、線程有著明顯的不同:協程提出于編譯器層面,而進程、線程提出于操作系統層面;協程是通過提議一種語言來做編譯器的標準,再由編譯器的制造者實現這種機制,而進程、線程是通過操作系統來進行分配與調度的;協程是通過引入相關代碼使代碼段可以分段運行,重啟處由yield關鍵字決定,而進程、線程是通過保存、恢復等中段的形式來完成的,其本質仍舊是利用CPU時間片[2]。
1.2 協程編程
函數在軟件程序進行調用的過程與遞歸思想很相似,要等到被調用者給出數據時調用者才能開始調用,例如,函數A若想調用函數B,那么只有在函數B執行完畢并將結果返回以后,函數A方能開始執行。所以,系統內部是通過棧完成調用函數,即函數執行就是線程執行[3]。調用函數時要有輸入與輸出,是按順序運行,但是協程調用不需要像程序調用那樣等待結果,可直接運行下去,當收到協程反饋回的結果后,再繼續對上訴結果進行處理。若需用多核來進行多協程編程,那么就要用多進程與多線程結合的形式,這是由于協程仍然占用單個CPU核[4]。
綜上所述,進程的堆棧都不共享,調度是由操作系統來完成的;線程只是共享堆,但不共享棧,調度仍是由操作系統來完成的;協程也只是共享堆,但不共享找,調度是由編程人員來完成的。
2 REST簡介
最初提出的REST(Representational State Transfer)只定義了部分編程的規范與準則,當設計符合這些規范與準則時,就將這些設計稱為RESTful設計[5]。這種以資源為核心的編程方式給編程留下了通用接口,且能夠在高效使用HTTP協議時簡化web的編程框架。Google提出的golang語言僅僅支持的是底層REST。
對于REST來說,資源是最重要最寶貴的,這些資源能夠利用URI定位到服務器上,其中URI能夠在http的前部信息里通過特定的字段來展現資源。REST中涉及到的表現層是通過json格式的數據來展現資源的,通常web涉及采用的是json多的前后端交互。在訪問網站時,數據會在瀏覽器和服務器之間進行不斷的交互,但http協議是無狀態的,只是明確了訪問規范。在進行狀態保存時,在服務器端進行的編程會發揮作用,因此,仍舊要通過http來訪問服務器端。總之,RESTful的特點可以概括為三點:(1)資源用URI來表示;(2)在資源表現層進行數據交換;(3)客戶端通過http來操作服務器資源。
由于REST減少了交互延遲,精簡了框架設計,降低了系統冗余度,能夠大量擴展,因此,REST不僅使客戶端與服務器端的交流變得更為簡便,而且使系統能夠進一步得到擴展。本文所研究的高并發架構可以通過對REST的稍加改造來達到golang的REST標準。本文只實現了3個層次,在實際應用中,可以根據實際需要來選擇要實現的規范。
3 webgo框架的設計與實現
本文所設計的webgo框架能夠迅速構建golang語言應用的HTTP框架,能夠迅速開發各種web應用,該框架是一個融合了golang特性的RestFul框架。
3.1 路由模塊
HTTP的請求通過路由組件發送給相應函數進行處理,路由相當于框架中的事件處理器,用戶請求路徑(path)與查詢串信息HTTP請求方法(method)均包含在事件中,路由器的作用其實是將用戶請求信息傳到了一個處理函數。路由的設置思路主要是路由信息的添加與要執行函數的轉發:路由信息的添加是用http.Handle與http.HandleFunc等函數實現的,均在底層調用DefaultServeMux函數,該函數能夠將路由信息儲藏于map信息中;要執行函數的轉發是通過監聽端口Go將接收到的tcp連接交由Handler進行處理。
雖然當前的Web應用路由均是基于http默認路由器來實現的,但有三點限制:(1)參數無法自行設定;(2)對REST模式無法完美支持且不能限制訪問;(3)路由規則多,程序編寫復雜。為了克服上訴限制,設計了一種考慮存儲路由與轉發路由的REST方式路由。本文設計的高并發架構含有controllerInfo和controllerRegistor兩個數據類型。
3.2 業務邏輯模塊
本文在現有REST準則規范的基礎上設計了新型MVC格式的框架,在本文中將其命名為controller,這提高了web應用開發效率,相比于以前基于Action的MVC框架更為簡單高效。MVC式的架構模式十分普遍,M是指模型(Model),V是指視圖(View),C是指控制器(Controller)。MVC式的架構模式實質是利用了分層思想,即分開業務邏輯與展示,模型表示的是服務器端的數據結構,視圖表示的是前端表現層(網頁、模板等),控制器是實現業務邏輯的。對于前面http里的handler來說,handler其實是一個控制器。MVC式的架構模式核心是控制器,這是展示與加工數據的來源,而且一個正常系統可以沒有模型和視圖,但不能沒有控制器。本文設計的高并發架構包含struct和interface兩個類型。
3.3 日志模塊
在程序設計人員編寫程序的過程中,日志的正確使用是十分重要的,這是因為調試信息是記錄在日志中的。webgo的日志模塊是在seelog的基礎上開發的,它是依據level的類型來輸出各種類型的日志,這樣做能夠使開發程序和部署程序變得更為簡單,實用性更強。通常在開發程序時設置一個較低的level值,在部署程序的時候再將原本較低的level值調高,此做法能夠屏蔽掉開發過程里的調試信息。
本文將seelog部署程序的思想融入設計webgo日志中,依據level的不同值來記錄相關的日志,然而webgo的日志系統的級別較輕,使用了系統自帶的log.Logger接口,默認將信息傳送至os.Stdout,用戶能夠利用這個接口,再用webgo.SetLogger對輸出進行自定義設定。
4 webgo和beego的比較分析
beego框架大量的應用到Golang的web框架中,相比于其它webgo框架,本文所設計的主要優勢體現在對路由的轉發以及業務邏輯的處理封裝方面。
4.1 webgo和beego的路由對比
本文是通過map在webgo框架的底層存儲路由的,雖然beego里樹狀結構的存儲空間較少,但是其比map更為高效。beego框架的優勢能夠在具有許多路由的時候體現出來,這使得高并發且少量路由時的webgo更占優勢。
4.2 webgo和beego的業務邏輯處理對比
程序段中的Ctx字段存儲了大量上下文中所包含的信息,例如,含有各種數據的清單表格、客戶端輸入的各類參數以及URI等。這些字段存儲在beego的map中。當有多個路由的時候,存儲上下文中的信息變得更為簡單。然而當并發量異常巨大時,存儲起來的上下文中的信息將占用大量的空間,因此,本文所設計的基于協程的高并發架構webgo將會去掉存儲模塊。
5 結語
beego作為golang的web框架,它主要針對的是那些量級很高的研發項目,傾向于開發API,但是本文所研發設計的webgo框架主要針對的是那些量級很低且高并發的快速研發項目。當處于項目研發的前期階段時,要在盡可能匹配考慮項目應用環境的前提下選擇適合的框架,只有應用了合適的框架才能在提高效率的同時大幅度壓縮研發周期。
通過分析測試以及對比的結果可以發現,本文提出的基于協程的高并發架構大大改善了原有的性能指標:(1)服務器端的負載量級從百萬級提高至千萬級;(2)成倍擴大單位時間內需要建立的連接數量(qbs),最終能夠比處于同樣應用環境的多線程高10倍;(3)相同并發量的運行時間減少約68%,當并發量在1000萬的時候,基于協程的高并發架構運行時間從3.7s縮減到2.2s;(4)內存消耗下降了約140%,當并發量在1000萬的時候,基于協程的高并發架構消耗內存從240M縮減到100M。
參考文獻
[1]李中躍.一種低成本的C語言協程實現[J].遼寧省交通高等專科學校學報,2012,(4):23-26.
[2]石剛,王生原,董淵,等.同步數據流語言可信編譯器的構造[J].軟件學報,2014,(2):341-356.
[3]諶衛軍.C程序設計課程中的堆與棧[J].計算機教育,2015(5):98-102.
[4]鄒昌偉,王林.面向嵌入式的協程與腳本化機制[J].計算機應用,2014,(5):1408-1412.
[5]章武媚.基于RESTfulWeb技術的資源管理系統設計與實現[J].計算機應用與軟件,2014,(5):23-28.