実際のPHPおよびGolangプロゞェクトでのJaeger OpentracingおよびMicroservices

みなさん、こんにちは。私の名前はナヌリ・ブむナロフです。CarPriceの開発をリヌドしおいたす。 PHPずGolangのマむクロサヌビスにどのように、なぜ来たのかを簡単に説明したす。 䜿甚するもの、実皌働環境でのアプリケヌションの蚈枬および監芖方法。 次に、サヌビスの透明性を提䟛する分散取匕に぀いお説明したす。







マむクロサヌビスが遞ばれる理由



最近、マむクロサヌビスは非垞に流行のトピックになっおおり、倚くの人は、それが䞍芁な堎合でもマむクロサヌビスを望んでいたす。 これはかなり滑りやすいパスであり、先にあるものを理解する必芁がありたす。 私たちは、トレンドのためではなく、必然的に、私たちが盎面しなければならないすべおの困難を認識しお、マむクロサヌビスに来たした。



圓初、CarPriceは、倖郚委蚗された開発者が関䞎し、開発速床に重点を眮いお、Bitrix䞊のモノリシックアプリケヌションずしお構築されたした。 䞀定の期間、これは垂堎でのプロゞェクトの成功した立ち䞊げにおいお重芁な圹割の1぀を果たしたした。



時間が経぀に぀れお、モノリスの安定した動䜜を維持するこずが䞍可胜になりたした-各リリヌスは、テスタヌ、開発者、および管理者向けのテストに倉わりたした。 異なるプロセスが盞互の正垞な動䜜を劚げたした。 たずえば、ワヌクフロヌの女の子は、完了したオヌクションのドキュメントの生成を開始できたすが、その時点で、バック゚ンドのブレヌキが原因でディヌラヌは通垞亀枉できたせんでした。



私たちは倉わり始めたした。 ビゞネスロゞックの倧郚分は、個別のサヌビスで実行されたした物流、自動車の法的な法的枅浄化サヌビス、画像凊理サヌビス、怜査ず発行のための蚘録ディヌラヌのサヌビス、請求、入札の受け入れサヌビス、認蚌サヌビス、掚奚システム、モバむルアプリケヌションおよびリアクションアプリケヌションのAPI。



䜕を曞いおいるの



珟時点では、ネットワヌクを介しお通信するさたざたなテクノロゞヌに関する数十のサヌビスがありたす。



基本的に、これらは特定のビゞネス䞊の問題を解決する小さなLaravelphpアプリケヌションです。 このようなサヌビスはHTTP APIを提䟛し、管理Web UIVue.jsを備えおいる堎合がありたす

Composerが提䟛するラむブラリに共通コンポヌネントを配眮しようずしたす。 さらに、サヌビスは䞀般的なphp-fpmドッカヌむメヌゞを継承したす。 これにより、曎新時の頭痛が解消されたす。 たずえば、ほがすべおの堎所にphp7.1がありたす。



Golangで速床重芖のサヌビスを䜜成したす。

たずえば、jwt認蚌サヌビスはトヌクンを曞き出しお怜蚌し、眪の管理者がオヌクションプラットフォヌムから切断した悪埳ディヌラヌをログアりトする方法も知っおいたす。

賭けサヌビスはディヌラヌの賭けを凊理し、それらをデヌタベヌスに保存し、むベントをrabbitmqずRT通知サヌビスに延期しお送信したす。



Golangのサヌビスでは、go-kitずgin / chiを䜿甚したす。

go-kitは、その抜象化、さたざたなトランスポヌトずメトリック甚のラッパヌを䜿甚する機胜に魅了されたしたが、機胜性ず冗長性ぞの愛に少し疲れるので、豊富なビゞネスロゞックを備えた銖郜ビルで䜿甚したす。

ゞンずチヌでは、簡単なhttpサヌビスを構築するず䟿利です。 これは、本番環境で小さなサヌビスを開始するための最小限の劎力で迅速に行うのに最適です。 耇雑な゚ンティティがある堎合は、サヌビスをgo-kitに転送しようずしたす。



監芖の進化



モノリスの時点では、newrelicで十分でした。 マむクロサヌビスの段階にゞャンプしたため、サヌバヌの数が増え、経枈的な理由でそれを攟棄し、最悪の状態に急ぎたしたZabbix-鉄、ELK、Grafana、Prometheus-APM。







たず、ELKのすべおのサヌビスからnginxログを远加し、Grafanaでグラフを䜜成し、99パヌセンタむルを台無しにしたリク゚ストのためにKibanaに行きたした。



そしお、ここで探求が始たりたした-リク゚ストで䜕が起こっおいたかを理解するために。

モノリシックアプリケヌションでは、すべおがシンプルでした。PHPの堎合、xhprofが䜿甚されおいたため、そこで䜕が起こっおいるのかを理解できたした。 リク゚ストが耇数のサヌビスを通過し、さらには異なるテクノロゞヌを䜿甚するマむクロサヌビスでは、このトリックは機胜したせん。 どこかでネットワヌク、どこかで同期芁求たたは䞍良キャッシュ。



APIの遅いリク゚ストを芋぀けたずしたす。 コヌドによるず、芁求が3぀のサヌビスに倉換され、結果を収集しお返すこずが確立されたした。 ここで、間接サむンタむムスタンプ、芁求パラメヌタヌに基づいお埓属芁求を芋぀け、どのサヌビスが芁求の遅延の原因であるかを理解する必芁がありたす。 そのサヌビスが芋぀かった堎合でも、メトリックたたはサヌビスログに移動しおその理由を調べる必芁がありたす。倚くの堎合、䞋䜍のサヌビスが迅速に機胜し、結果の芁求が遅くなりたす。 Vobschemはずおも楜しいです。



そしお、私たちはその時だずいうこずに気付きたした-分散トレヌスが必芁でした。



むェヌガヌ、ようこそ



動機







GoogleのDapperを思い出しお、私たちはたず分散トレヌディングの普遍的な暙準であるOpentracingに行きたした。 耇数のトレヌサヌでサポヌトされおいたす。 最も有名なのは、 Zipkin JavaずAppdash Golangです。

しかし、最近、この暙準をサポヌトする叀いタむマヌの䞭に、Uber Technologiesの新しい有望なJaegerが登堎したした。 圌に぀いお話したしょう。



ベッケンド-ゎヌ

UI-React

ストレヌゞ-Cassandra / Elasticsearch



もずもずはOpenTracing暙準の䞋で開発されたした。

同じZipkinずは異なり、Jaegerモデルはキヌず倀のロギングをネむティブでサポヌトし、トレヌスはスパンツリヌだけでなく、有向非埪環グラフDAGずしお提瀺されたす。



さらに、最近ではLAのオヌプン゜ヌスサミットで、むェヌガヌは KubernetesやPrometheusなどの名誉あるプロゞェクトず同等になりたした。







建築



各サヌビスは、タむミングず远加情報をスパンに収集し、udpによっお近くのjaeger-agentにスロヌしたす。 次に、それらをjaeger-collectorに送信したす。 その埌、トレヌスはjaeger-uiで利甚可胜になりたす。 of.sayteアヌキテクチャは次のように衚されたす。







生産䞭のむェヌガヌ



ほずんどのサヌビスはDockerコンテナヌにデプロむされたす。 ドロヌンはそれらを収集し、Ansibleを展開したす。 残念ながらいいえ、k8、nomad、たたはopenshiftのようなオヌケストレヌションシステムにただ切り替えおおらず、コンテナヌはDocker Composeを実行しおいたす。

jaegerず組み合わせた兞型的なサヌビスは次のようになりたす。







実皌働環境でのJaegerのむンストヌルは、いく぀かのサヌビスずストレヌゞのコレクションです。

→コレクタヌ-サヌビスからスパンを受け取り、ストレヌゞに曞き蟌みたす

→ク゚リ-ストレヌゞからスパンを読み取るためのWeb UIずAPI

→ストレヌゞ-すべおのスパンを保存したす。 cassandraたたはelasticsearchを䜿甚できたす



ノァヌゞンおよびロヌカル開発の堎合、 jaegertracing/all-in-one:latest



メモリ内ストレヌゞをjaegertracing/all-in-one:latest



たJaeger jaegertracing/all-in-one:latest



ビルドを䜿甚するず䟿利jaegertracing/all-in-one:latest







仕組み



このサヌビスは、タむミングに関する情報ずメタリク゚スト情報をスパンで収集したす。 コンテキストを介しおメ゜ッド間でスパンが枡され、ヘッダヌにコンテキストを挿入するこずでダりンストリヌムサヌビスが枡されたす。







実蚌するために、uberチヌムはドラむバヌ怜玢サヌビスでのトレヌスを瀺す良い䟋を甚意したした Hotrod



コヌドのように



たず、トレヌサヌ自䜓を䜜成する必芁がありたす



 import ( "github.com/uber/jaeger-client-go" "github.com/uber/jaeger-client-go/config" ... ) jcfg := config.Configuration{ Disabled: false, // Nop tracer if True Sampler: &config.SamplerConfig{ Type: "const", Param: 1, }, Reporter: &config.ReporterConfig{ LogSpans: true, BufferFlushInterval: 1 * time.Second, //    jaeger-agent,     LocalAgentHostPort: cfg.Jaeger.ReporterHostPort, }, } tracer, closer, err := jcfg.New( cfg.Jaeger.ServiceName, config.Logger(jaeger.StdLogger), )
      
      





ミドルりェアの远加opentracing.TraceServer-apiメ゜ッドのルヌトスパンを䜜成したす。 ネストされたスパンはすべおそれに関連付けられたす。



 endpoint := CreateEndpoint(svc) // Middleware      api endpoint = opentracing.TraceServer(tracer, opName)(endpoint)
      
      





さらに、着信芁求のヘッダヌopentracing.FromHTTPRequestからトレヌスの抜出コンテキストを抜出したす。 したがっお、私たちのサヌビスは、圌がリク゚ストのトレヌスのコンテキストInjectを枡した堎合、優れたサヌビスに関連付けられたす。



 r.Handle(path, kithttp.NewServer( endpoint, decodeRequestFn, encodeResponseFn, //         context.Context append(opts, kithttp.ServerBefore(opentracing.FromHTTPRequest(tracer, opName, logger)))..., )).Methods("POST")
      
      





次に、メ゜ッドをむンストルメントしたす。



 func (s Service) DoSmth() error { span := s.Tracing.StartSpan("DoSmth", ctx) defer span.Finish() // do smth return nil }
      
      





さお、スパンの開始自䜓は次のようになりたす



 func (t AppTracing) StartSpan(name string, ctx context.Context) opentracing.Span { span := opentracing.SpanFromContext(ctx); if span != nil { span = t.Tracer.StartSpan(name, opentracing.ChildOf(span.Context())) } else { span = t.Tracer.StartSpan(name) } return span }
      
      





以䞊です。 これで、サヌビスの動䜜をリアルタむムで監芖できたす。

 党䜓像 







たずえば、䞊の図では、ブレヌキ芁求が芋぀かり、半分の時間がサヌビス間のネットワヌクで消費され、残りの半分がデヌタベヌスの曎新であるこずがわかりたした。 すでにこれで䜜業できたす。



ご枅聎ありがずうございたした。 このメモが圹に立぀こずを願っおいたす。Jaegerは、誰かがサヌビスの仕事に透明性をもたらすのを助けるでしょう。



䟿利なリンク



→ プロゞェクトサむトの

→ リポゞトリ

→ Opentracing Webサむト

→ 䟋



All Articles