TarsGoの新しいリリース、protobuf、zipkin、カスタムプラグインのサポート


著者:陳明傑(sandyskies)Tarsはテンセントが2008年から今日まで使用してきたバックグラウンド論理層の統一応用フレームワークであり、現在はC++、Java、PHP、Nodejs、Golang言語をサポートしている.このフレームワークは、製品またはサービスの迅速な開発、導入、テスト、オンライン化を支援する、開発、メンテナンス、およびテストに関するソリューションを提供します.拡張可能なプロトコルコーデック、高性能RPC通信フレームワーク、名前のルーティングと発見、公開監視、ログ統計、構成管理を一体化し、マイクロサービスで安定で信頼性の高い分散アプリケーションを迅速に構築し、完全で効率的なサービスガバナンスを実現します.現在、このフレームワークはテンセント内部で、各コア業務が使用されており、人気があり、このフレームワークに基づいて運行されているサービスノードの規模は1万個に達している.Tarsは2017年4月にオープンし、2018年6月にLinux財団に加入した.TarsGoはTarsのGo言語実装バージョンで、2018年9月にオープンソース、プロジェクトアドレスhttps://github.com/TarsCloud/...あ、スターさん、いらっしゃいませ.
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の使用方法:
  • この2つのファイルを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からvectorに変更し、他の言語との通信問題を解決する
  • 修復statモニタエスカレーション問題
  • ログ・レベル
  • をリモートから更新
  • ルーティングリフレッシュコモンシップ極端の場合のデッドロック問題を修復する
  • コプロセッサ・プール・スキーマを最適化し、コプロセッサ・プール・スキーマ
  • を追加
  • goコヒーレント起動順序の修復によるpanic問題
  • golint大部分コード