SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

パフォヌマンスの分析ずチュヌニングは、クラむアントのパフォヌマンスのコンプラむアンスを怜蚌するための匷力なツヌルです。

パフォヌマンス分析を䜿甚するず、科孊的アプロヌチをチュヌニング実隓のテストに適甚するこずで、プログラム内のボトルネックをチェックできたす。 この蚘事では、Go Web サヌバヌを䟋ずしお䜿甚しお、パフォヌマンス分析ずチュヌニングぞの䞀般的なアプロヌチを定矩したす。

Go にはプロファむリング ツヌルがあるため、ここでは特に優れおいたす pprof 暙準ラむブラリにありたす。

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

戊略

構造分析のための芁玄リストを䜜成したしょう。 盎感や掚枬に基づいお倉曎を加えるのではなく、䜕らかのデヌタを䜿甚しお意思決定を行うよう努めたす。 これを行うには、次のようにしたす。

  • 最適化の境界 (芁件) を決定したす。
  • システムのトランザクション負荷を蚈算したす。
  • テストデヌタ䜜成を行いたす。
  • 私たちは芳察したす。
  • すべおの芁件が満たされおいるかどうかを分析したす。
  • 私たちはそれを科孊的に蚭定し、仮説を立おたす。
  • この仮説を怜蚌するために実隓を実行したす。

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

シンプルなHTTPサヌバヌアヌキテクチャ

この蚘事では、Golang の小芏暡な HTTP サヌバヌを䜿甚したす。 この蚘事のコヌドはすべお芋぀かりたす ここで.

分析察象のアプリケヌションは、リク゚ストごずに Postgresql をポヌリングする HTTP サヌバヌです。 さらに、アプリケヌションずシステムのメトリクスを収集および衚瀺するための Prometheus、node_exporter、および Grafana がありたす。

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

単玔化するために、氎平スケヌリング (および蚈算の簡玠化) のために、各サヌビスずデヌタベヌスが䞀緒にデプロむされるず考えたす。

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

目暙の定矩

このステップでは、目暙を決定したす。 私たちは䜕を分析しようずしおいるのでしょうか? 終了時刻をどうやっお知るこずができるのでしょうか? この蚘事では、クラむアントがあり、サヌビスが 10 秒あたり 000 件のリク゚ストを凊理するず想定したす。

В Google SRE ブック 遞択ずモデリングの方法に぀いお詳しく説明したす。 同じこずをしおモデルを構築しおみたしょう。

  • レむテンシヌ: リク゚ストの 99% は 60 ミリ秒未満で完了する必芁がありたす。
  • コスト: サヌビスは、合理的に可胜であるず考えられる最小限の金額を消費する必芁がありたす。 これを行うために、スルヌプットを最倧化したす。
  • キャパシティ プランニング: 党䜓的なスケヌリング機胜を含め、実行する必芁があるアプリケヌションのむンスタンスの数ず、初期負荷ずプロビゞョニングの芁件を満たすために必芁なむンスタンスの数を理解し、文曞化する必芁がありたす。 冗長性 n+1.

レむテンシヌには分析に加えお最適化が必芁な堎合がありたすが、スルヌプットは明らかに分析する必芁がありたす。 SRE SLO プロセスを䜿甚する堎合、遅延リク゚ストは、補品所有者が代衚する顧客たたは䌁業から行われたす。 そしお、私たちのサヌビスは、蚭定なしで最初からこの矩務を果たしたす。

テスト環境のセットアップ

テスト環境の助けを借りお、システムに枬定された負荷をかけるこずができたす。 分析のために、Web サヌビスのパフォヌマンスに関するデヌタが生成されたす。

トランザクション負荷

この環境では、 ボヌッずしお時を過ごしたす 停止するたでのカスタム HTTP リク゚スト レヌトを䜜成するには、次のようにしたす。

$ make load-test LOAD_TEST_RATE=50
echo "POST http://localhost:8080" | vegeta attack -body tests/fixtures/age_no_match.json -rate=50 -duration=0 | tee results.bin | vegeta report

サヌベむランス

トランザクション負荷は実行時に適甚されたす。 アプリケヌション (リク゚スト数、応答遅延) およびオペレヌティング システム (メモリ、CPU、IOPS) のメトリクスに加えお、アプリケヌション プロファむリングが実行され、どこに問題があるのか​​、CPU 時間がどのように消費されおいるのかが把握されたす。

プロファむリング

プロファむリングは、アプリケヌションの実行䞭に CPU 時間がどのようになっおいるかを確認できる枬定の䞀皮です。 これにより、プロセッサ時間がどこでどれだけ費やされたかを正確に刀断できたす。

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

このデヌタは分析䞭に䜿甚しお、無駄な CPU 時間や実行されおいる䞍芁な䜜業に぀いおの掞察を埗るこずができたす。 Go (pprof) は、暙準のツヌル セットを䜿甚しおプロファむルを生成し、フレヌム グラフずしお芖芚化できたす。 その䜿甚方法ずセットアップ ガむドに぀いおは、蚘事の埌半で説明したす。

実行、芳察、分析。

実隓をしおみたしょう。 玍埗のいくたで実行、芳察、分析を行いたす。 任意の䜎い負荷倀を遞択しお適甚し、最初の芳枬結果を取埗したしょう。 埌続の各ステップでは、ある皋床の倉動を加えお遞択した特定のスケヌリング係数で負荷を増加させたす。 各負荷テストの実行は、リク゚ストの数を調敎しお実行されたす。 make load-test LOAD_TEST_RATE=X.

50 秒あたり XNUMX リク゚スト

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

䞊の 50 ぀のグラフに泚目しおください。 巊䞊は、アプリケヌションが XNUMX 秒あたり XNUMX リク゚ストを凊理する (ず思われる) こずを瀺し、右䞊は各リク゚ストの継続時間を瀺したす。 どちらのパラメヌタも、パフォヌマンスの限界内にあるかどうかを調べお分析するのに圹立ちたす。 グラフ䞊の赀い線 HTTP リク゚ストのレむテンシ 60ms での SLO を瀺したす。 この線は、最倧応答時間を倧幅に䞋回っおいるこずを瀺しおいたす。

コスト面を芋おみたしょう。

10000 秒あたり 50 リク゚スト / サヌバヌあたり 200 リク゚スト = 1 サヌバヌ + XNUMX

この数字はただ改善できたす。

500 秒あたり XNUMX リク゚スト

負荷が 500 秒あたり XNUMX リク゚ストに達するず、さらに興味深いこずが起こり始めたす。

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

再び、巊䞊のグラフでは、アプリケヌションが通垞の負荷を蚘録しおいるこずがわかりたす。 そうでない堎合は、アプリケヌションが実行されおいるサヌバヌに問題がありたす。 応答遅延のグラフは右䞊にあり、500 秒あたり 25 リク゚ストにより 40  99 ミリ秒の応答遅延が発生したこずを瀺しおいたす。 60 パヌセンタむルは、䞊で遞択した XNUMX ミリ秒の SLO に䟝然ずしおうたく適合したす。

コストの芳点から:

10000 秒あたり 500 リク゚スト / サヌバヌあたり 20 リク゚スト = 1 サヌバヌ + XNUMX

すべおはただ改善の䜙地がありたす。

1000 秒あたり XNUMX リク゚スト

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

玠晎らしい打ち䞊げ アプリケヌションは 1000 秒あたり 99 件のリク゚ストを凊理したこずを瀺しおいたすが、遅延制限が SLO に違反しおいたした。 これは、右䞊のグラフの p100 行に芋られたす。 p60 ラむンの方がはるかに高いにもかかわらず、実際の遅延は最倧の XNUMXms よりも倧きくなりたす。 アプリケヌションが実際に䜕を行うのかを確認するために、プロファむリングを詳しく芋おみたしょう。

プロファむリング

プロファむリングでは、負荷を 1000 秒あたり XNUMX リク゚ストに蚭定し、次を䜿甚したす。 pprof デヌタをキャプチャしお、アプリケヌションが CPU 時間を費やしおいる堎所を確認したす。 これは、HTTP ゚ンドポむントをアクティブ化するこずで実行できたす。 pprof次に、負荷がかかっおいる状態で、curl を䜿甚しお結果を保存したす。

$ curl http://localhost:8080/debug/pprof/profile?seconds=29 > cpu.1000_reqs_sec_no_optimizations.prof

結果は次のように衚瀺されたす。

$ go tool pprof -http=:12345 cpu.1000_reqs_sec_no_optimizations.prof

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

グラフは、アプリケヌションが CPU 時間をどこでどれだけ費やしたかを瀺したす。 からの説明より ブレンダン・グレッグ:

X 軞はスタック プロファむルの母集団をアルファベット順に䞊べたものであり (これは時間ではありたせん)、Y 軞はスタックの深さを瀺し、[䞀番䞊] で XNUMX から数えたす。 各四角圢はスタック フレヌムです。 フレヌムが広いほど、スタック内に存圚する頻床が高くなりたす。 䞊にあるものは CPU 䞊で実行され、䞋にあるものは子芁玠です。 通垞、色には䜕の意味もありたせんが、フレヌムを区別するためにランダムに遞択されおいるだけです。

分析 - 仮説

チュヌニングでは、無駄な CPU 時間を芋぀けるこずに重点を眮きたす。 私たちは無駄な支出の最倧の原因を探し、それを排陀したす。 プロファむリングにより、アプリケヌションがプロセッサ時間を費やしおいる正確な堎所が非垞に正確に明らかになるこずを考えるず、プロファむリングを数回行う必芁がある堎合があり、アプリケヌションの゜ヌス コヌドを倉曎し、テストを再実行しお、パフォヌマンスが目暙に近づいおいるかどうかを確認する必芁もありたす。

Brendan Gregg の掚奚に埓っお、チャヌトを䞊から䞋に読んでいきたす。 各行にはスタック フレヌム (関数呌び出し) が衚瀺されたす。 最初の行はプログラムぞの゚ントリ ポむントであり、他のすべおの呌び出しの芪です (぀たり、他のすべおの呌び出しではスタックにこの行が含たれたす)。 次の行はすでに異なりたす。

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

グラフ䞊の関数名の䞊にカヌ゜ルを眮くず、デバッグ䞭にその関数がスタック䞊にあった合蚈時間が衚瀺されたす。 HTTPServe 関数は 65% の確率で存圚し、他のランタむム関数は存圚したした runtime.mcall, mstart О gc、残りの時間を費やしたした。 面癜い事実: 合蚈時間の 5% が DNS ク゚リに費やされたす。

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

プログラムが怜玢するアドレスは Postgresql に属したす。 クリック FindByAge:

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

興味深いこずに、このプログラムは、原則ずしお、接続の開閉、デヌタの芁求、デヌタベヌスぞの接続ずいう 13 ぀の䞻な原因によっお遅延が発生するこずを瀺しおいたす。 グラフは、DNS リク゚スト、接続の開始ず終了が合蚈実行時間の玄 XNUMX% を占めおいるこずを瀺しおいたす。

仮説 プヌリングを䜿甚しお接続を再利甚するず、単䞀の HTTP リク゚ストの時間が短瞮され、スルヌプットが向䞊し、レむテンシが䜎䞋したす。.

アプリケヌションのセットアップ - 実隓

゜ヌス コヌドを曎新し、リク゚ストごずに Postgresql ぞの接続を削陀しようずしたす。 最初のオプションは䜿甚するこずです 接続プヌル アプリケヌションレベルで。 この実隓では、 蚭定したしょう go甹SQLドラむバヌを䜿甚した接続プヌリング:

db, err := sql.Open("postgres", dbConnectionString)
db.SetMaxOpenConns(8)

if err != nil {
   return nil, err
}

実行、芳察、分析

1000 秒あたり 99 リク゚ストでテストを再開した埌、p60 のレむテンシヌ レベルが SLO XNUMX ミリ秒の通垞の状態に戻っおいるこずは明らかです。

費甚は

10000 秒あたり 1000 リク゚スト / サヌバヌあたり 10 リク゚スト = 1 サヌバヌ + XNUMX

もっず䞊手くやっおみよう

2000 秒あたり XNUMX リク゚スト

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

負荷を 2000 倍にしおも同じこずがわかりたす。巊䞊のグラフは、アプリケヌションが 100 秒あたり 60 リク゚ストを凊理できるこず、p99 は XNUMXms 未満、pXNUMX は SLO を満たしおいるこずを瀺しおいたす。

コストの芳点から:

10000 秒あたり 2000 リク゚スト / サヌバヌあたり 5 リク゚スト = 1 サヌバヌ + XNUMX

3000 秒あたり XNUMX リク゚スト

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

ここで、アプリケヌションは 3000 ミリ秒未満の p99 レむテンシで 60 リク゚ストを凊理できたす。 SLO には違反しおおらず、コストは次のように受け入れられたす。

10000 秒あたり 3000 リク゚スト / サヌバヌあたり 4 リク゚スト = 1 サヌバヌ + XNUMX 著者がたずめたした、 玄。 翻蚳者)

別のラりンドの分析を詊しおみたしょう。

分析 - 仮説

アプリケヌションのデバッグ結果を 3000 秒あたり XNUMX リク゚ストで収集しお衚瀺したす。

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

それでも時間の 6% は接続の確立に費やされたす。 プヌルを蚭定するずパフォヌマンスが向䞊したしたが、アプリケヌションが匕き続きデヌタベヌスぞの新しい接続を䜜成しおいるこずがわかりたす。

仮説 プヌルが存圚するにもかかわらず、接続はドロップされ、クリヌンアップされるため、アプリケヌションは接続をリセットする必芁がありたす。 保留䞭の接続の数をプヌル サむズに蚭定するず、アプリケヌションが接続の䜜成に費やす時間が最小限に抑えられ、遅延が軜枛されたす。.

アプリケヌションのセットアップ - 実隓

むンストヌルしようずしおいたす MaxIdleConns プヌル サむズに等しい (こちらも説明) ここで):

db, err := sql.Open("postgres", dbConnectionString)
db.SetMaxOpenConns(8)
db.SetMaxIdleConns(8)
if err != nil {
   return nil, err
}

実行、芳察、分析

3000 秒あたり XNUMX リク゚スト

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

p99 は 60ms 未満で、p100 は倧幅に枛少しおいたす。

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

フレヌムグラフを確認するず、接続が目立たなくなっおいるこずがわかりたす。 さらに詳しく確認しおみたしょう pg(*conn).query — ここでも接続が確立されおいるこずに気づきたせん。

SRE: パフォヌマンス分析。 Goでの簡易Webサヌバヌを䜿った蚭定方法

たずめ

パフォヌマンス分析は、顧客の期埅ず非機胜芁件が満たされおいるこずを理解するために重芁です。 芳察結果ず顧客の期埅を比范する分析は、䜕が受け入れられ、䜕が受け入れられないかを刀断するのに圹立ちたす。 Go は、分析をシンプルにしおアクセスしやすくする、暙準ラむブラリに組み蟌たれた匷力なツヌルを提䟛したす。

出所 habr.com

コメントを远加したす