從TARS小白到熟練工的進階實戰

做者丨唐靖凱
編輯丨TARS小助手

做爲一個應屆畢業生,進入閱文集團,加入到通用平臺中心以後,隨着平常工做的逐步深刻,我漸漸瞭解閱文的技術體系,其中尤爲以騰訊TARS平臺最爲重要。目前TARS平臺承載了閱文內部絕大多數的服務,每日接口調用最大值近百億,單業務峯值可在數萬每秒,近300個業務服務。做爲一個新人,我來說下我從TARS小白到熟練工的歷程中整理的一些知識點。git

TARS文件

TARS做爲一個服務治理框架,最基礎的仍是要解決服務間調用的問題,這樣就引入一個問題:如何在多個服務之間發佈接口協議。TARS創新性的設計了一種接口描述語言,即TARS文件,在TARS文件中,能夠編寫模型、接口、枚舉等。在服務提供方,咱們能夠經過tars-maven-plugin解析TARS文件,生成對應的模型、接口、枚舉代碼,而後就能夠在接口實現類中進行業務邏輯的編寫。在對外提供服務時,調用方只須要拿到服務提供方的TARS文件,就能瞭解服務提供的全部接口及相關描述,從而生成客戶端調用代碼,進行服務接口調用。github

module TestApp
{
    interface Hello
    {
        string hello(int no, string name);
    };
};

在閱文內部,咱們也提供了統一的TARS管理中心,在這裏咱們能夠找到全部已經上傳到管理中心的TARS文件,從而避免了經過線下傳遞TARS文件帶來的不便;管理中心支持將TARS文件自動打包成jar包併發布到公司的Maven鏡像上,省去了本身編譯帶來的麻煩。spring

服務部署

在TARS平臺上進行服務部署,只需把代碼倉庫地址配置到TARS平臺,選擇分支、選擇編譯器、編譯、打包、分批發布一條龍部署到TARS平臺上。目前TARS平臺支持物理機部署、Docker部署、物理機和Docker混合部署,極大地提高了使用的體驗及知足了服務發佈的多樣性。同時,TARS平臺還支持對每臺服務器作特殊化處理,好比能夠選擇某臺服務器設置爲無流量作線上接口測試,能夠修改某臺服務器的私有模板進行服務設置、JVM設置、日誌設置等配置的修改。這些都爲平常工做中的開發、測試、問題排查提供了更多的方法及可能性。shell

在發佈線上服務時,TARS平臺只支持指定tag進行編譯打包,從而在流程上規範了服務發佈的操做。並且發佈是能夠自定義選擇分批發布、無損發佈,最大限度的下降因服務重啓引發的線上服務抖動。數據庫

服務監控

TARS平臺提供了多維度、多樣化的服務監控及特性監控。服務監控選項包含了流量、平均耗時、異常率、超時率等,能夠自由選擇時間範圍、主調方業務名、主調方IP、被調方IP、接口名,從而縮小監控範圍,方便定位問題。特性監控則針對每一臺服務器提供了對JVM內存、堆使用狀況、線程、請求隊列等特性的監控,從而實現從服務器JVM級別進行問題定位。這些監控目前都是以5分鐘爲間隔,期待將來TARS平臺能夠提供更細粒度的時間間隔的監控。緩存

服務監控還提供了實時數據的功能,實現實時觀測服務的秒級運行情況,在定位線上問題上發揮了重要的做用。springboot

日誌

TARS-JAVA自帶一套日誌系統,提供了日誌類的基礎功能。它支持異步輸出,支持多種日誌級別,而且日誌級別能夠直接在TARS的管理平臺經過修改私有模板或者給TARS服務發送設置日誌級別命令來進行實時修改,實現平臺一致性。它還支持異常輸出,能夠方便地打印異常日誌。該日誌系統不用額外的配置文件,不須要重寫加載配置(在services.xml的應用中使用sl4j日誌系統時,須要將日誌系統的初始化安排到配置文件加載以後;在springboot的應用中使用sl4j日誌系統時,須要寫從新加載配置文件的邏輯)。目前TARS提供的日誌系統在不少項目中都做爲惟一日誌系統使用。服務器

不過須要注意的是默認的日誌系統輸出的日誌編碼是GBK格式的,當你使用以UTF-8解析的遠程shell工具查看日誌時常常會發現有些日誌內容丟失或者時亂碼。則能夠根據須要,將遠程工具的編碼格式調整爲與GBK兼容的編碼,或者使用iconv等工具轉換日誌編碼進行查看。session

# encoding converting
cat xx.log | iconv -f=gbk

配置文件

TARS平臺提供了服務配置中心來管理配置文件,在這裏能夠添加多個配置文件。在TARS平臺上部署服務時,每臺服務器會自動將全部配置文件加載到本地(前提是在服務代碼中配置了加載配置文件),放在Classpath路徑下,供JAVA服務讀取解析。對於每一個配置文件,TARS平臺還提供了文件內容變動時觸發的回調函數。經過回調函數機制,咱們能夠在修改完一個配置文件以後,在TARS平臺上進行配置文件推送,從而觸發代碼中預先設定的回調函數,達到配置文件熱更新的效果。固然,對於數據庫鏈接信息、Redis鏈接信息這些須要重建鏈接的配置信息仍是推薦經過重啓服務來更新。併發

接口測試

TARS平臺提供了對TARS接口進行測試的頁面。在測試頁面,咱們能夠爲每一個接口添加多個測試用例數據,能夠任意選擇服務所在的一臺機器進行測試用例調用。這種調用方式方便、快捷,可是對於自動化腳本不甚友好。針對這種狀況,閱文內部提供了使用HTTP接口調用TARS接口的方式,更方便地進行自動化接口測試。期待TARS平臺後續能對自動化接口測試提供更多的支持。

編碼問題

在開發TARS服務時,尤爲須要注意各類編碼問題,這裏整理了一些可能出現的編碼問題以及解決方案。

服務配置文件編碼

上面提到TARS平臺提供了服務配置中心來管理配置文件,服務配置默認的編碼是GBK,而且不支持修改,但閱文這邊部署服務所使用的的機器(包括物理機和Docker)通常使用的編碼是UTF-8。GBK和UTF-8都對ASCII碼兼容,因此當配置文件不涉及中文或其餘超過ASCII碼覆蓋範圍的字符時,部署的微服務程序中採用系統默認編碼讀取配置文件時不會發生問題;可是當配置文件中涉及中文字符時,可能因爲操做系統默認編碼不與GBK兼容時,程序會讀到錯誤的信息。

解決辦法: 在本身寫的服務代碼中使用GBK編碼打開配置文件;使用Unicode編碼過的字符串代替原中文字符串。

TARS-JAVA的編碼

你想嘗試一下TARS,因而你把TARS-Java部署在剛剛調教好的Linux上(把本地語言設置成了zh_CN.UTF-8時),當你發佈應用時,你會遇到一些奇怪的錯誤。當你查找緣由時,你會發現原來在發佈程序使用了GBK去讀取Linux的命令行輸出。這個時候你只須要改一下TARS-JAVA的源碼,將讀取命令行輸出的編碼改爲UTF-8,而後從新編譯一下便可,很是快捷。固然,也能夠不將操做系統的編碼設置成zh_CN.UTF-8,不少工具可能沒法正確顯示中文字符。

服務器文件編碼

服務器默認文件編碼有時候會出現不是UTF-8的詭異的現象(每每是locale沒有配置對UTF-8的支持),這個時候若是代碼中使用了默認編碼,就會出現亂碼的現象。

解決方法:不要使用默認編碼,在須要使用編碼的時候,必定手動指定編碼。

一些Trick分享

在實踐TARS服務開發的過程當中,積累了一些小技巧,挑選一些獻醜。

系統關閉鉤子

在TARS平臺管理中能夠將特定服務的選中實例設置爲無流量,以方便作發佈、線上驗證等操做。不過惋惜的是,在TARS服務中沒法感知平臺的無流量配置,這也就意味着本身編寫的TARS服務沒法在無流量狀態配置先後作一些特別的動做,好比在無流量開啓時同時去屏蔽隊列消費操做等。可是,TARS服務支持系統的關閉鉤子,能夠在系統退出前對申請資源進行清理以及確保某些任務完成後再退出。退出TARS服務只須要經過平臺對服務的AdminObj發送shutdown命令來完成,而後經過System.exit退出系統。因而能夠利用Runtime.getRuntime().addShutdownHook方法,給TARS服務增長系統關閉的鉤子。

獲取調用方的IP

有時候須要記錄調用方的IP,但因爲TARS爲了高效等目的,沒有辦法從服務端獲取到客戶端的標識信息。咱們能夠從TCP/UDP鏈接獲取調用方的IP和端口信息。

Session session = ContextManager.getContext().request().getIoSession();

String remoteIp = session.getRemoteIp();

int remotePort = session.getRemotePort();

如何規避Communicator實例重用所帶來的問題

在TARS服務的實現中,不可避免地會去調用其餘現成的服務,而且絕大多數狀況下會調用多個服務。這些被調服務可能會要求在調用時使用不一樣的編碼,有的須要使用UTF-8,而有的須要使用GBK。當多種不一樣編碼的客戶端混合調用時,可能會遇到編碼問題。追本溯源,發如今獲取Communicator實例時,會對其使用Map進行緩存,Map的鍵爲locator或者CommunicatorConfig實例,而CommunicatorConfig只使用了locator和moduleName做爲hashCode和equals方法的計算要素。因而當使用locator和moduleName相同的CommunicatorConfig實例去獲取Communicator實例時,會獲得同一個實例,即使charsetName並不一致。 解決的辦法通常有兩種:

  1. 繼承CommunicatorConfig,並重寫hashCode和equals方法,加入charsetName做爲計算要素,再由這個派生類獲得的實例去獲取Communicator實例;
  2. 爲須要特別配置其餘屬性的CommunicatorConfig實例設置不一樣的moduleName。

小編有話說

感謝這位同窗的精彩分享,看完這位同窗從TARS小白到熟練工的進階過程當中積攢的經驗,你是否也想分享一下本身的經驗?歡迎向 tarscloud@qq.com 投稿。

若是你尚未了解過TARS,歡迎到GitHub上圍觀、交流,以爲好的話請給TARS點個star哦~!

GitHub地址:https://github.com/TarsCloud

相關文章
相關標籤/搜索