TarsGo新版本發佈,支持protobuf,zipkin和自定義插件

来源:https://www.cnblogs.com/tars/archive/2018/11/13/9953503.html
-Advertisement-
Play Games

本文作者:陳明傑(sandyskies) Tars是騰訊從2008年到今天一直在使用的後臺邏輯層的統一應用框架,目前支持C++,Java,PHP,Nodejs,Golang語言。該框架為用戶提供了涉及到開發、運維、以及測試的一整套解決方案,幫助一個產品或者服務快速開發、部署、測試、上線。 它集可擴展 ...


本文作者:陳明傑(sandyskies)

Tars是騰訊從2008年到今天一直在使用的後臺邏輯層的統一應用框架,目前支持C++,Java,PHP,Nodejs,Golang語言。該框架為用戶提供了涉及到開發、運維、以及測試的一整套解決方案,幫助一個產品或者服務快速開發、部署、測試、上線。 它集可擴展協議編解碼、高性能RPC通信框架、名字路由與發現、發佈監控、日誌統計、配置管理等於一體,通過它可以快速用微服務的方式構建自己的穩定可靠的分散式應用,並實現完整有效的服務治理。目前該框架在騰訊內部,各大核心業務都在使用,頗受歡迎,基於該框架部署運行的服務節點規模達到上萬個。
Tars 於2017年4月開源,並於2018年6月加入Linux 基金會。
TarsGo 是Tars 的Go語言實現版本, 於2018年9月開源, 項目地址 https://github.com/TarsCloud/TarsGo ,歡迎star 。

TarsGo 新版本發佈

在上次開源之後,有些用戶反饋了一些需求,基於用戶反饋的需求,我們進行了實現,併發布了1.1.0版本。 本次發佈新增了:支持pb、支持zipkin分散式追蹤、支持filter(自定義插件編寫)、支持context 等,除此之外還做了一系列優化和bugfix。

新功能:PB支持

Protocol Buffers (簡稱 PB )是 Google 的一種數據交換的格式,它獨立於語言,獨立於平臺,最早公佈於 2008年7月。隨著微服務架構的發展及自身的優異表現,ProtoBuf 可用於諸如網路傳輸、配置文件、數據存儲等諸多領域,目前在互聯網上有著大量應用。
如果對於現有已使用grpc,使用proto文件,想轉換成tars協議的用戶而言,需要將上面的proto文件翻譯成Tars文件。這種翻譯會比較繁瑣,而且容易出錯。 為此我們決定編寫插件支持proto文件直接生成tars的rpc邏輯。protoc-gen-go的代碼邏輯裡面是預留了插件編寫的規範的,參照grpc,主要有 grpc/grpc.go 和一個導入插件的link_grpc.go 。 這裡我們編寫 tarsrpc/tarsrpc.go 和 link_tarsrpc.go
使用方面:

  • 將這兩個文件放到protoc-gen-go 下麵,go install重新生成protoc-gen-go 二進位
  • 定義proto 文件
  • 使用重新編譯安裝的protoc-gen-go生成序列化和rpc相關介面代碼
protoc --go_out=plugins=tarsrpc:. helloworld.proto

  

  • 編寫tars 客戶端和服務端代碼,參數使用pb生成的結構體,其餘代碼邏輯和正常的tars服務一致。

新功能: filter機制, 支持zipkin分散式追蹤

為了支持用戶編寫插件,我們支持了filter機制,分為服務端的過濾器和客戶端過濾器,用戶可以基於這個機制,實現自己的TarsGo插件。

//服務端過濾器, 傳入dispatch,和f, 用於調用用戶代碼, req, 和resp為傳入的用戶請求和服務端相應包體
type ServerFilter func(ctx context.Context, d Dispatch, f interface{}, req *requestf.RequestPacket, resp *requestf.ResponsePacket, withContext bool) (err error)
//客戶端過濾器, 傳入msg(包含obj信息,adapter信息,req和resp包體), 還有用戶設定的調用超時
type ClientFilter func(ctx context.Context, msg *Message, invoke Invoke, timeout time.Duration) (err error)
//註冊服務端過濾器
//func RegisterServerFilter(f ServerFilter)
//註冊客戶端過濾器
//func RegisterClientFilter(f ClientFilter)

  有了過濾器,我們就能對服務端和客戶端的請求做一些過濾,比如使用 hook用於分散式追蹤的opentracing 的span。 我們來看下客戶端filter的例子:

//生成客戶端tars filter,通過註冊這個filter來實現span的註入
func ZipkinClientFilter() tars.ClientFilter {
    return func(ctx context.Context, msg *tars.Message, invoke tars.Invoke, timeout time.Duration) (err error) {
        var pCtx opentracing.SpanContext
        req := msg.Req
        //先從客戶端調用的context 裡面看下有沒有傳遞來調用鏈的信息,
        //如果有,則以這個做為父span,如果沒有,則起一個新的span,span名字是RPC請求的函數名
        if parent := opentracing.SpanFromContext(ctx); parent != nil {
            pCtx = parent.Context()
        }
        cSpan := opentracing.GlobalTracer().StartSpan(
            req.SFuncName,
            opentracing.ChildOf(pCtx),
            ext.SpanKindRPCClient,
        )
        defer cSpan.Finish()
        cfg := tars.GetServerConfig()

        //設置span的信息,比如我們調用的客戶端的ip地址,請求的介面,方法,協議,客戶端版本等信息
        cSpan.SetTag("client.ipv4", cfg.LocalIP)
        cSpan.SetTag("tars.interface", req.SServantName)
        cSpan.SetTag("tars.method", req.SFuncName)
        cSpan.SetTag("tars.protocol", "tars")
        cSpan.SetTag("tars.client.version", tars.TarsVersion)

        //將span註入到 請求包體的  Status裡面,status 是一個map[strint]string 的結構體
        if req.Status != nil {
            err = opentracing.GlobalTracer().Inject(cSpan.Context(), opentracing.TextMap, opentracing.TextMapCarrier(req.Status))
            if err != nil {
                logger.Error("inject span to status error:", err)
            }
        } else {
            s := make(map[string]string)
            err = opentracing.GlobalTracer().Inject(cSpan.Context(), opentracing.TextMap, opentracing.TextMapCarrier(s))
            if err != nil {
                logger.Error("inject span to status error:", err)
            } else {
                req.Status = s
            }
        }
        //沒什麼其他需要修改的,就進行客戶端調用
        err = invoke(ctx, msg, timeout)
        if err != nil {
            //調用錯誤,則記錄span的錯誤信息
            ext.Error.Set(cSpan, true)
            cSpan.LogFields(oplog.String("event", "error"), oplog.String("message", err.Error()))
        }

        return err
    }

服務端也會註冊一個filter,主要功能就是從request包體的status 提取調用鏈的上下文,以這個作為父span,進行調用信息的記錄。整體的一個效果:

詳細代碼參見 TarsGo/tars/plugin/zipkintracing完整的zipkin tracing的客戶端和服務端例子,詳見 TarsGo/examples下麵的ZipkinTraceClient和ZipkinTraceServer

新功能: 支持context

TarsGo 之前在生成的客戶端代碼,或者用戶傳入的實現代碼裡面,都沒有使用context。 這使得我們想傳遞一些框架的信息,比如客戶端ip,埠等,或者用戶傳遞一些調用鏈的信息給框架,都很難於實現。 通過介面的一次重構,支持了context,這些上下文的信息,將都通過context來實現。 這次重構為了相容老的用戶行為,採用了完全相容的設計。

服務端使用context

type ContextTestImp struct {
}
//只需在介面上添加 ctx context.Context參數
func (imp *ContextTestImp) Add(ctx context.Context, a int32, b int32, c *int32) (int32, error) {
    //我們可以通過context 獲取框架傳遞的信息,比如下麵的獲取ip, 甚至返回一些信息給框架,詳見tars/util/current下麵的介面
    ip, ok := current.GetClientIPFromContext(ctx)
    if !ok {
        logger.Error("Error getting ip from context")
    }  
    return 0, nil
}
//以前使用AddServant ,現在只需改成AddServantWithContext
app.AddServantWithContext(imp, cfg.App+"."+cfg.Server+".ContextTestObj")

客戶端使用context

 ctx := context.Background()
    c := make(map[string]string)
    c["a"] = "b" 
//以前使用app.Add 進行客戶端調用,這裡只要變成app.AddWithContext ,就可以傳遞context給框架,如果要設置給tars請求的context
//可以多傳入參數,比如c,參數c是可選的,格式是 ...[string]string
    ret, err := app.AddWithContext(ctx, i, i*2, &out, c)

服務端和客戶端的完整例子,詳見 TarGo/examples

其他優化和修複

  • 將request package 的Sbuffer欄位由vector<unsigned byte> 改成vector<byte>,解決和其他語言通信問題
  • 修複stat監控上報問題
  • 日誌級別從遠端更新
  • 修複路由刷新協程極端情況下死鎖問題
  • 優化協程池方案,並添加協程池方案
  • 修複go協程啟動順序導致panic問題
  • golint大部分代碼

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 項目中經常會遇到一種情況,就是點擊切換,比如點擊按鈕,div樣式為1,再點擊一下按鈕,div樣式為2,再點擊一下按鈕,div樣式為1。需要自定義jQuery方法toggle。 註意不要與jQuery中預設的toggle方法搞混淆,預設的toggle方法用於切換元素的可見狀態,如果被選元素可見,則隱藏 ...
  • div、h1或p元素常常被稱為塊級元素。這意味著這些元素顯現為一塊內容,即“塊框”。與之相反,span和h3等元素稱為“行內元素”,這是由於它們的內容顯現內行中,即“行內框”。 在這種狀況下,這個框稱為無名塊框,由於它不與專門界說的元素相關聯。 塊級元素的文本行也會發作相似的狀況。假設有一個包括三行 ...
  • 1、flex佈局 1.1 容器指定為flex佈局 .box{display: flex;} 1.2 行元素指定flex佈局 .box{display:inline-flex} 2、容器的屬性 2.1、flex-direction 2.2、flex-wrap 2.3、flex-flow 2.4、jus ...
  • *.3gpp audio/3gpp, video/3gpp 3GPP Audio/Video*.ac3 audio/ac3 AC3 Audio*.asf allpication/vnd.ms-asf Advanced Streaming Format*.au audio/basic AU Audio ...
  • 前幾天給了個需求對瀏覽器網頁進行截圖,把網頁統計數據圖形表等截圖保存至用戶本地。 首先對於網頁截圖,我用的是canvas實現,獲取你需要截圖的模塊的div,從而使用canvas對你需要的模塊進行截圖。 我們先來引入canvas的js文件,js文件獲取地址官網主頁:http://html2canvas ...
  • 項目中遇到的問題,需要表頭固定,給表主體設置滾動條。搜了很多種方法,bootstrap table也研究了一下。 下麵是我們使用的方法。 表頭放在div1中,表主體放在div2中,給div2設置固定高度,加樣式overflow:auto,這樣在數據多的時候會出現滾動條,數據少的時候滾動條會消失。 如 ...
  • <!DOCTYPE html><html><head><meta charset="UTF-8"><title>Insert title here</title><!-- 步驟分析 1.確定事件:點擊事件:onclick事件 2.事件要觸發函數selectOne 3.selectOne要做一些操作 ...
  • @media screen and (max-width: 300px) { //當視口寬度小於等於300px時生效 } max-width 相當於 <= @media screen and (min-width: 300px) { //當視口寬度大於等於300px時生效 } max-width 相 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...