解讀|TARS開源項目發佈Go語言版本

文章轉自開源中國node

導語:近日,Tars 開源項目在上海發佈並開源了 Go 語言版本,其性能與 C++ 版本至關,比 gRPC 的性能高 5 倍。 ——編者git

Tars 是騰訊開源的一款微服務框架,它於去年 4 月份開源,並於今年 6 月捐贈給了 Linux 基金會。Tars 爲用戶提供了涉及到開發和運維的一整套解決方案,幫助一個產品或者服務快速開發、發佈、部署、上線和維護。它集可擴展協議編解碼、高性能 RPC 通訊框架、名字路由與發現、發佈監控、日誌統計、配置管理等於一體,經過它能夠快速用微服務的方式構建穩定可靠的分佈式應用,並實現完整有效的服務治理。通過一年多的發展,目前 Tars 已經被許多企業使用,如閱文集團、虎牙直播、科大訊飛,優品財富、龍圖遊戲和金太陽教育等。github

據悉,9 月 15 日,騰訊宣佈正式開源 Tars 的 Golang 版本 Tars-Go。編者從 Tars 的開源公告中瞭解到 Tars 與當前市面上其它微服務框架的差別、技術架構、性能數據與相關技術細節,本文將詳細介紹 Tars 這次釋出的 Golang 版本。算法

項目地址:編程

https://github.com/TarsCloud/...後端

支持服務治理、多語言,只 Tars 一家性能優化

微服務架構這兩年變得格外火熱,它已經成爲當前最主流的架構模式。提起微服務框架,咱們能夠天然地舉出 Dubbo、gRPC 與 Spring Cloud 等衆多的知名項目,依據是否支持服務治理和是否支持多語言兩個維度可將這些微服務框架分爲如下四類:服務器

clipboard.png

只有服務調用沒有服務治理類的框架。典型的表明有 gRPC、Thrift 等,他們很好地解決了服務間通訊的問題,大部分也支持多語言,但使用這類框架時須要本身去解決服務治理問題。微信

帶服務治理但支持單一語言的框架。典型的表明有 Spring Cloud 和 Dubbo,它們都是用 Java 實現的框架,用戶整合多個開源項目一塊兒並能知足服務治理等的需求。網絡

Service Mesh。它支持服務治理,並經過 Sidecar 模式解決框架對多語言支持,業務須要再封裝一套通信組件去解決通信問題,以及異步調用等問題,同時會增長架構和維護的複雜度。

帶服務治理並支持多語言的框架。目前業界比較少,除了 Tars 目前尚未發現其它具備表明性的框架。

從上面的分析大概能夠發現,Tars 是支持服務治理的同時又提供多語言支持的微服務框架,這是 Tars 的獨特之處,也是其優點。

Tars 能夠運行在物理機、虛擬機和容器,其協議主打的是基於 IDL 實現的 Tars 協議,它是一種二進制解析協議,與 pb 相似,同時 Tars 還擴展支持其它協議,乃至用戶自定義。

調用方式主要以 RPC 爲主,支持同步、異步和單向調用幾種方式。在服務治理方面除了支持服務註冊、發現等業界常說的能力以外,還提供面對海量訪問的一些其它治理能力,如 Set 模型、自動區域感知、過載保護等,語言上除了這次新支持的 Golang,目前已經支持了 C++、Java、NodeJS 與 PHP,同時總體框架能夠和 DevOps 很好地協同工做。

Tars 總體分爲三個部分:Registry、服務節點和基礎服務集羣。

clipboard.png

Registry

Registry 是微服務集羣的管理和控制節點,提供服務註冊和發現等功能。

服務節點

服務節點是 Tars 運行的原子單元,能夠是一個容器也能夠是一個虛機或物理機,一個業務服務經過部署多個服務節點來解決容量和容錯問題。服務節點上包括一個 node 管理服務和一個或多個業務服務,node 服務對本節點的服務進行統一管理,提供啓停、監控服務節點等功能,同時接收業務服務節點上報過來的心跳,上報給 Registry 做爲服務發現的數據來源。

基礎服務集羣

基礎服務集羣是爲解決微服務治理而設計的一系列服務,服務節點數量不定,爲了自身的容錯容災,通常也要求在多個服務器上進行部署,具體的節點數量與業務規模有關,好比,若是業務規模大須要打較多的日誌,就須要部署更多的日誌服務節點。基礎服務主要包括監控統計、配置中心、日誌聚合、認證鑑權和分佈式調用鏈等。Tars 具備很是完善的服務治理能力。

clipboard.png

Tars 經過 Registry、服務節點和基礎服務集羣協同工做,透明完成服務發現/註冊、負載均衡、鑑權、分佈式跟蹤等服務治理相關工做。如框架經過 Registry 來註冊 xxxsvr,Client 經過訪問 Registry 獲取到被調服務的地址信息列表,Client 再根據須要選擇合適的負載均衡方式來調用服務。負載均衡支持輪詢、hash、權重等多種方式。

爲了更及時地屏蔽故障節點,Client 根據調用被調服務的異常狀況判斷是否有故障來更快地進行故障屏蔽。具體策略是,當 Client 調用某個服務器出現調用連續超時超過設置閾值,或者調用的超時比率超過必定百分比閾值,Client 就會對此服務器節點進行屏蔽,讓流量分發到正常的節點上去。對屏蔽的服務器節點,每隔必定時間進行重連,若是正常,則進行正常的流量分發。

隨着業務增加,服務的部署不免會跨機房或者地域,常規的負載均衡方式面對跨地區或者跨機房部署的服務會由於網絡緣由形成延時增大,爲了加快服務間的訪問速度,減小因建設跨地區、跨機房調用帶來的網絡資源消耗,減小網絡故障帶來的影響,Tars 提供自動區域感知的服務治理功能。

clipboard.png

經過 Registry 和開發框架配合實現自動區域感知,這樣的優點有:

運維簡單

下降延時減小帶寬消耗

更強的容災能力

此外 Tars 還提供 Set 模型。

Set 模型是根據業務功能特徵對部署進行規範化和標準化,以 Set 爲單元進行部署。Set 模型的優勢有:

有效防止故障擴散

方便進行容量管理

對於流量控制,服務發佈上線主要面對的問題是「如何作對業務無損的服務變動」與「如何作灰度驗證」,在 Tars 中,可經過 Registry 和開發框架配合實現按需進行流量控
clipboard.png
的目的。

![圖片上傳中...]

語言支持方面,除了此前已經支持的 PHP、C++、NodeJS 與 Java,這次還加入了 Golang 支持。

此外,Tars 還提供一個 OSS 平臺,可以使運營可視化、Web 化。

clipboard.png

它主要包含如下特色:

業務管理:包括已部署的服務,以及服務管理、發佈管理、服務配置、服務監控、特性監控等

運維管理:包括服務部署、擴容、模版管理等

提供 Open API ,可定製本身的 OSS 系統

Tars-Go,Tars Go!

多語言支持是 Tars 的一大優點,在此以前 Tars 已經推出了 C++、Java、PHP、NodeJS 版本。Go 語言的協程併發機制使它很是適用於大規模高併發後端服務器程序開發,同時隨着容器化技術的飛速發展,諸如 Docker、Kubernetes 與 Etcd 等項目興起,使得 Go 語言愈來愈流行,併成爲雲原生的首選語言。Tars 的 Go 語言版本也所以應運而生,這次 Tars-Go 的推出,在大環境總體逐漸走向雲原生的當下,意義非凡。

這次新推出的 Go 版本 Tars-Go 總體架構主要能夠分爲三個部分,以下圖所示:

clipboard.png

左邊是 tars2go 工具,tars2go 基於巴科斯範式(BNF),這是一種描述程序語言結構的形式化方法,用來對 Tars 文件進行語法和詞法分析,生成相應的代碼,供客戶端和服務端使用。同時它提供 Tars 協議二進制流的編解碼功能,將二進制包轉成相應的 Go 數據結構。

右邊部分是 package tars,它包含了 Client 和 Server 兩部分的功能:

Client 由 Servantproxy、Communicator、ObjProxy、adapterproxy 等邏輯結構組成,這些邏輯結構用來管理 servant,obj 對應到的服務端節點的 ip 端口,和 C++ 的邏輯保持一致。底層使用 net.Conn 來創建具體的鏈接,並用 SendQueue chan 來控制併發數量。Client 還包含一些 Goroutine,用來作特性監控和 stat 監控上報。

Server 使用 package net 的 listener 來管理 TCP 和 UDP 鏈接,使用多個 Goroutine 進行 accept,並將 accept 以後的 net.Conn 通過 SendQueue chan 交給後端的 Handler 進行處理。Handler 由一堆 woker Goroutine 組成,每一個 Goroutine 基於 net.Conn 進行收發包、Tars 協議解碼,並通過 dispatcher(由 tars2go 生成) 來調用用戶的代碼實現,而後將結果編碼成二進制流返回給 Client。Server 也包含一些 Goroutine 實現遠程日誌異步上報等功能,防止同步調用阻塞請求。

編者瞭解到,Tars 開源團隊在研發 Tars-Go 的過程當中經歷的對其各個方面的性能調優改造,Tars-Go 在早先的版本注重於功能的開發和完善,沒有體系化地進行壓測和性能分析。在業務使用一段時間後,開始注重性能優化。Tars 開源團隊對 tars2go 工具先進行了一輪優化,在生成語樹的時候生成好了類型信息,避免使用反射進行類型判斷,編解碼的效率提高了 2 倍,而後對再對總體 servant 進行了一輪輪壓測,並進行 CPU profile 性能分析。

下面是性能提高優化的幾個實例:

Timer 性能問題

每一個請求進來,Tars-Go 會建立一個協程進行處理,由於要處理調用超時,會建立一個 timer,在結束的時候會刪掉 timer,當併發量一上來,就會頻繁建立和刪除 timer,佔用服務大量 CPU 時間。

clipboard.png

研發團隊在一個 issue 中發現 ,在多 CPU 的場景下,若是存在大量的 timer,性能就會大量損耗,優化方式是每一個 p 有本身的 timer,這樣能夠大幅提高總體併發性能。因而 Tars-Go 將編譯環境升級至 1.10.3,從 profile 來看,性能獲得了很大的提高,而且基於時間輪詢算法實現了本身的 timer,以精度換取性能和效率。

net 包的 SetDeadline 調用性能問題

爲了設置網絡鏈接的讀寫超時,Tars-Go 使用了 net 包的 SetReadDeadline/SetWriteDeadline 等相關調用,但從 profile 發現,當併發很是大的時候,會致使這兩個調用佔用了大量的 CPU 時間。爲了繞開這兩個相關調用,使用了 Sysfd 進行 Socket 讀寫超時的設置。

bytes 的 Buffer 帶來的性能問題

從下圖能夠看出,有至關大的一部分時間耗在了 slice 相關的操做上,原來在包的編解碼過程當中,使用 bytes.Buffer 進行臨時存放,當 bytes.Buffer 底層用的 byte slice 大小不夠的時候,就會分配必定的內存空間,頻繁地分配效率很低,因此致使大包狀況下性能降低比較明顯。

clipboard.png

聯想到了 Redis 的內存模型和 Linux 的 slab 機制,對於頻繁建立銷燬的對象,採用預先建立和重複利用的方式。而 Go 自己提供了一種 sync.Pool 機制,供臨時對象的複用,以減小 GC,Tars-Go 在此基礎上,實現了相似 Linux slab 機制分配的 buffer 管理方案,經過這種方案,性能大幅提升。

其餘方面的優化

clipboard.png

通過上面的性能優化後,Tars-Go 在小包的並發表現提高了 5 倍。

clipboard.png

壓測機型:4 核/8線程 CPU 3.3Ghz 主頻 16G 內存

壓測邏輯:客戶端帶着必定大小的數據給服務端,服務端原樣返回給客戶端

服務端單進程,多個客戶端發起測試

Tars-Go 編程示例

clipboard.png

Tars 協議是一個二進制協議,它是與語言無關的IDL語言,由工具自動生成服務端和客戶端代碼,下邊是一個 Tars 協議的示例:

具體編程的時候,首先須要定義一個 Tars 文件,以下所示:定義接口 Mult ,a 和 b 爲入參,c 爲出參,均爲整型。

clipboard.png

接着生成接口代碼。使用 tars2go JesseTest.tars 便可自動生成 pacakge Prajna JesseTest 的 servant 和 Mult 方法的框架實現,業務無需關心實現細節:

clipboard.png

最後,實現接口代碼,將入參 a、b相乘後的結果放到 c 返回給客戶端:

clipboard.png

以後 go build 就能夠進行編譯。

而客戶端只需關注出入參,引入由 Tars 文件轉化成的包便可完成一次 RPC 調用。

clipboard.png

將來,Linux 基金會將增強 Tars 項目的社區運做機制,讓 Tars 的影響力從中國走向國際。

Tars:https://github.com/TarsCloud

Tars-Go:https://github.com/TarsCloud/...

微信掃碼加入TARS-GO官方交流羣:

clipboard.png

以上內容參考 Tars 開源團隊核心成員陳明傑的演講 PPT 《億級規模高可用架構源碼剖析——騰訊 Go 語言開發框架 TARS-GO》。

相關文章
相關標籤/搜索