Go使用grpc+http打造高效能微服務

後開啟撒打發了發表於2018-05-16

大家可以發現,Go越來越流行,其一是目前雲端計算領域基本是使用Go作為底層開發語言;其二是隨著區塊鏈的火爆,引申出了其背後很多開源專案,很多都是使用Go語言進行開發;其三就是在微服務方面,Go也展示很大的優勢性。那麼微服務是什麼,如何將其與Go做一個整合,來提升整體開發生產效率,下面會進行詳細講解。

什麼是微服務

微服務的概念最早由 Martin Fowler 提出,在他的理論當中,微服務是一整套小的服務,其中每一個服務互相之間都是獨立的,它們之間通過 lightweight 機制進行互動。

640?wx_fmt=png&wxfrom=5&wx_lazy=1

圖 1

圖 1 所示是最傳統的一個應用軟體架構,最頂層是 load balancer ,下面佈局很多cuisine,這些cuisine共享一個資料庫。

640?wx_fmt=png&wxfrom=5&wx_lazy=1

圖 2

圖 2 是微服務的架構圖,由圖中我們可以看出整體架構分佈的改變,一個服務被分成A、B、C三種服務,每個服務有自己的資料庫,前面都會有一個 API Gateway將其三者連結起來。顯而易見,微服務的難點也就在服務的劃分上,通俗點講就是如何服務其中的微服務。

在之前我與一些公司朋友做線下交流時曾提到他們對微服務劃分的經驗,有些部門是按照模組進行劃分的,簡單的比如會員認證模組、評論模組、點贊模組等,有些則分的比較細的,會將一個很小的功能(函式級別)分成一個模組;在國外盛行一種“披薩分法”,比如一個團隊所有的開發、部署、運維人員能夠將一個披薩吃完,那麼整個團隊就被稱之為一個微服務團隊(基本三到四人能夠完成整套工作)。

這裡大概介紹了微服務的基本概念,但是微服務並非良藥,很多架構並非剛開始就會採用微服務的方式,後續會對這方面做更加詳細的介紹。

GRPC介紹

gRPC是由Google主導開發的RPC框架,使用HTTP/2協議並用Protobuf作為序列化工具。與REST不同的是,REST是基於HTTP1.1 JOSN格式的一種輕量級服務模式,那麼從這兩方面來對比gRPC與REST就比較容易了。

首先可以從JOSN與Protobuf之間的差別入手進行對比,Protobuf很難讀,它是面向機器的文字格式,而JOSN則是面向人的;Protobuf相對於JOSN而言編解碼速度都非常快;最後就是相容性,現在基本所有瀏覽器都支援JOSN格式,而Protobuf目前僅部分語言支援。

接下來可以對比一下http1.1與http2。http1.1是文字方式,因此http的請求我們都可以很清楚的讀懂;http1.1中每一個請求會有一個新的connection,但是http2 是一個持續的http connection;http1是持續repetitive,http2是compressed;http1.1所有瀏覽器都預設支援,而http2只是部分支援。綜上,就是gRPC和REST在支援協議上的不同。

0?wx_fmt=png

圖 3

圖 3 所示是一個 REST API 的程式碼示例,其中validate是一個校驗函式,可以校驗input的內容是否合法,如果校驗失敗輸出false,反之則輸出”200“ 那麼同樣功能的一個API,圖 5 展示了gRPC API 當中的內容。

0?wx_fmt=png

圖 4

因為先前有提到,使用gRPC時,傳遞的是 Protobuf 那麼首先我們就需要去定義一個Protobuf檔案,,如圖 4。

0?wx_fmt=png

圖 5

圖 5 當中定義的引數如 InfoRequest 等在圖 4 描述的定義檔案中都有詳細的引數說明。那麼通過gRPC與REST的介面內容對比我們可以看出,gRPC的程式碼更加簡潔。那麼這是介面程式碼的對比,效能上它們有什麼差異性呢?

0?wx_fmt=png

圖 6

如圖 6 所示,是gRPC與REST之間效能方面的對比,我們可以看出來效能差異還是比較大的,在請求相同內容時,差異性也是比較大的,gRPC會跑1000000次,每次時長大致為2063ns/op,但是REST在同等情況下只會跑3000次,每次耗時為40493772ns/op。

以上是兩者的對比,從前面的對比我們也可以看出,兩者之間的差異性,那麼問題很明顯,兩者之間的轉換就揹負著很大的歷史包袱,所以,今天會著重去介紹如何使用gRPC+HTTP去打造一個微服務。

如何使用 GRPC+HTTP 打造微服務

0?wx_fmt=png圖7   

圖 7 所示是現在常見的微服務架構方式,由圖中我們可以看出,最前面試load balance,後面緊接著是API gateway,主要做一些聚合的工作。對外採用REST API方式相互呼叫,對內則採用gGPC API的方式相互進行呼叫。

0?wx_fmt=png

圖 8

圖 8 所示舉了一個例子,比如我擁有一個www的網站,這個網站頁面使用的是react,現在不論是那種頁面框架都會遵循以上的方式去呼叫API,那麼呼叫的API是基於JOSN+HTTP,後面緊跟四個gRPC的service,參照圖 8 所示的流程,每個呼叫都是循序漸進的。

0?wx_fmt=png

圖 9

圖 9 所示是以上流程圖所提供的五個服務的程式碼架構,其中包含API服務,認證(auth)服務,geo服務(根據當天的位置反饋定位經緯度),profile服務(獲取經緯度周邊資訊)以及rate服務(獲取酒店排名資訊)。由圖中所示,可以看出對外統一是採取REST的方式,而對內則都使用Protobuf,只需要定義一些檔案的內容即關於service是什麼即可。最後可以在API當中註冊service,那麼之後API在被呼叫的時候,去呼叫相應服務即可。

接下來會介紹我們在內部做整個微服務框架時的一些想法和實踐。微服務看似簡單,如上述例子,在呼叫一個函式的時候,可以完成五個函式的工作,但是一旦進行拆分就會變成五個服務,複雜度也會升高,所以我一直在思考微服務框架到底解決了哪些問題,因此我在beego 中也產生了很多思考。

0?wx_fmt=png

圖 10

首先是測試,測試包括兩個方面:單元測試和整合測試。所謂的單元測試(圖 10)在Go中是比較被推崇的一種方式,在單元測試當中要生成一個stract就必須要宣告其中的輸入和輸出,對於需要測試的函式只需要增加一個for迴圈,那麼每當增加一行程式碼需要進行測試時,只需要增加一行要測試的input和outout即可。

但是今天著重會介紹整合測試,整合測試相對會比較麻煩一點,因為需要去模擬http或者是gRPC請求,例如測試檔案array.request中的內容,其中test-fixtures(包含3000多個測試服務)這裡面我只需要完成array.request的內容,response的內容可以自動生成。

其次是Tracing,當微服務被引入後,每個服務的執行時長會變得很難追蹤,當除錯一個問題時,因為微服務很多(尤其是上千個時)此時去找問題就會很麻煩,那麼通過Tracing的方式就可以很容易的找到呼叫的東西從而大大降低了尋找問題的時間成本。

0?wx_fmt=png

圖 11

圖 11 所示是Opentracing,它是一個分散式Tracing標準(Kubernetes成立了一個雲端計算基金會CNCF,這個就是其中的一個專案)。

0?wx_fmt=png

圖 12

圖 12 所示是chrome中進行追蹤的一個工具(chrome://tracing/),它最主要的是為了調多執行緒、多程式、多goroutine所存在的。

0?wx_fmt=png

圖 13

在講完Tracing之後,大家會比較關注Monitoring(監控系統)這裡我主要會舉prometheus(圖 13)的例子進行說明,在prometheus中有三種型別:基礎型、上下標準差型以及時間型別。這裡我採用的是標準差型別,因為需要判斷當前伺服器時間與NTP時間的差值。prometheus中有很多定義好的函式(引數) 當然我這邊定義了三個函式(引數)比如Collectors、GoCollector(監控了Go中所有的資訊)剛才說的 Monitoring 的專案,可以關注https://prometheus.io/ 以及 https://grafana.com 這兩個網址的內容進行了解。

最後講一下Debug,其實應該改成logging。在微服務當中一直在講三個東西,一是Tracing,其次是prometheus需要收集的東西,最後就要介紹一下logging。現在寫log經常會分不同的level,比如infor、running、debug等,實際上其實我們去查log時並不會太過於關注這些東西,Dave之前寫了這篇blog:https://dave.cheney.net/2015/11/05/lets-talk-about-logging 有興趣的朋友可以去看一下,裡面就提到兩種真正要的level。

0?wx_fmt=png

圖 14

圖 14 所示是微服務架構的核心。那麼講了這麼多,微服務架構到底是不是最完美的架構,答案當然是否定的,如果一個公司的團隊要上微服務架構前提是需要考慮你們團隊的整體實力,如果有能力,那麼我建議大家上微服務,如果沒有,我不建議大家去遷微服務的架構。

為什麼 Go 適合微服務

首先是考慮到語言的複雜程度,一些靜態語言效率的確很高,可是非常複雜,比如C++,複雜性太高,大家都喜歡簡單的東西,所以複雜的都被排除在外。其次考慮到效能問題。最後考慮到併發程式設計環境,一般來說併發的程式設計環境很難處理,因為要考慮執行緒、鎖等問題。所以,一般提到這些,都會提及速度、簡單、可讀這三個關鍵指標去評判一項語言,那麼Go是不是可以三者兼併呢?大家在程式設計時都希望越簡單越好,簡單就意味著”小“,說到小,微服務的概念似乎更小。我個人認為,Go之所以適合做微服務,是因為它本身就很小,這個小蘊含兩層意思:其一,編譯出來的東西小;其二,關鍵字小導致核心小,學起來也比較簡單。

總而言之,Go相對其他所有語言來說,它是簡單易讀的,Go是工程性的語言,它們都是從工程上的東西出發,完全按照工程師的思路,從工程師思路出發,去輔助你完成工作,這樣在接觸Go的時候就會有很大的親切感。

我覺得,相對於其他語言來說,Go最大的優點:其一是高併發,但是其實Go的併發並沒有C好,但是在多層情況下,C需要多核使用,對程式設計師要求很高;其二是Team協作,Go由將近一萬人在共同協作,程式碼當然也可以從一千萬行協作;其三是高效能,因為它的效能以及簡單性,讓其在PHP與C之間找到了平衡點,PHP可以快速開發,但是效能說到底比C還是差一點,但是C的學習成本又很高,所以Go剛好在兩者之間找到了平衡點;四是對執行非常友好,所有寫的東西編譯之後就是二進位制的檔案,部署時直接就可以使用。

綜上,也就是我對於Go為何適用於微服務的一些看法,當然任何技術也在不斷迭代更新,我們也仍需要去不斷更新自己的知識庫。



ECUG 走過了十年,今年,我們在上海帶來一場行業內最高水準的技術交流與分享,年底最不容錯過的一場技術盛典(點選“閱讀原文”報名參加 ECUG 十年高峰盛會)

海蔘到底怎麼吃更有營養.首頁網路 · 頂新
孩子長不高,原因怪家長。後悔才知道!雅思 · 頂新
undefined

沒有更多推薦了,返回首頁

相關文章