GCは、多くの場合、100msの捜査超えて一時停止し、コンテナサービスのために行く(転載、他の文書)
GCの一時停止は、多くの場合、100ミリ秒を超えて
現象
同社は最近、問題があるプロセス内のドッキングウィンドウの回で展開され、K8Sのトライアルを開始し、インタフェースはタイムアウトも長い時間がかかりますが、ことを同僚からのフィードバック。ロジックはシンプルで、ちょうど店のKVを呼び出し、KV一般的なストレージの応答時間<5msの以下40qpsより、容器が0.5核のクォータを割り当てられ、非常に小さい、CPUコアの日常業務は、0.1未満です。
再現
私は、トラフィックキックオフ、コンテナを発見した。これらの要求は、679msに200ミリ、99%の時間を浪費するよりも60ミリ秒のAB 50同時ネットワークの往復遅延が、平均処理時間がかかると見て構造を取ります。
ABによる治療は、CPUとメモリ情報の下で見ると、。何も問題があるドッカー分布が0.5コアもそんなにここでは使用しませんでしたです。
監視下に見えた、GC STWが10ミリ秒未満(世界を停止)、50-100msは1.8 GCの一時停止後に主張しないの100msを超える。ゴーの多くは、1msのが何よりも基本的にはありますが、多くのですか?
GC情報とトレース
プロセスに関する実行時の情報を見て、非常に少ないメモリ、偉大GCポーズを発見し、GOMAXPROCS 76は、マシンを監査しています。
輸出GODEBUG = gctrace = 1、再起動を確認するプロセスは、非常に深刻な確かGCポーズを見ることができます。
-
gc 111 @97.209s 1%: 82+7.6+0.036 ms clock, 6297+0.66/6.0/0+2.7 ms cpu, 9->12->6 MB, 11 MB goal, 76 P
-
gc 112 @97.798s 1%: 0.040+93+0.14 ms clock, 3.0+0.55/7.1/0+10 ms cpu, 10->11->5 MB, 12 MB goal, 76 P
-
gc 113 @99.294s 1%: 0.041+298+100 ms clock, 3.1+0.34/181/0+7605 ms cpu, 10->13->6 MB, 11 MB goal, 76 P
-
gc 114 @100.892s 1%: 99+200+99 ms clock, 7597+0/5.6/0+7553 ms cpu, 11->13->6 MB, 13 MB goal, 76 P
トレースについてのSDKサービスの実行を行かなければならない単一のサーバ上で、その後、トレースファイルは、ローカルな外観にダウンロードされます
-
curl -o trace.out 'http://ip:port/debug/pprof/trace?seconds=20'
-
sz ./trace.out
もちろん、ない科学の、道のほぼ全体GC時間を埋め、壁時間のGCで見られる次の図は172msであり、GC 2 STWこの段階、スイープ終了とマーク終端は80以上のミリ秒です。
原因と解決法
理由
このサービスは数ある(GOMAXPROCSとして)デフォルト設定Pになり、コンテナプロセスは、CPUのコア数がアプリケーションのために、また、ゴー工作機械であるCPUコアの数を確認するために、コンテナとマシンツールは、カーネルを共有するコンテナで実行されていますCPUコアの数。我々はまた、図、GOMAXPROCS 76の正面から見ることができるが、Pは、図中、しかし、スレッドのロット番号、171をそれに結合したm個に使用されるそれぞれがに割り当てられていますスレッドの数とたくさんながら、実際にはあまりないCPUクォータ容器、わずか0.5コア、。
推測:LinuxのCFS(完全公平スケジューラ)は、それをすべての現在のスレッド(LWP)内に容器内に各タスクが実行されているため、スケジューリンググループの効率を確保するために、しない限りため閉塞理由スイッチに取り組み、その後、少なくとも、自分の時間が実行されていることを確実にするためには、/ proc / sys / kernel / schedmingranularity_ns 4msのように見えることができます。
ゴー・プロセス・コンテナーが適切に実行することができますあまりにも多くのスレッドで、その結果、GOMAXPROCS番号を設定されていない場合、スケジュール遅延の問題が発生することがあります。それは長い時間のために、スケジューラを切り替えられた後だけで停止に他のスレッドをGC STWスレッドに打ち上げ発生します糸は、本質的になり、非常に長い(スケジューリングは100ミリ秒レベルになるのために0.1msの通常処理が遅延)STW時間を引き起こし、スケジュールされていません。
ソリューション
あまりにも多くのスレッドを取って、その結果、Pを実行することができますので、解決策は、STW仮想ランタイムを開始し、CPU割当量がはるかに我々が行う必要はありませあるP、我々が選択できるCPUクォータの試合..行います。
-
CPUクォータの増加コンテナ。
-
コンテナ内のレイヤのコンテナCPUコアの数を確認するためのプロセスは数クォータとなるように、
-
正しいGOMAXPROCSを設定し、クォータによると、
最初の方法の差はあまり効果はないが、0.5〜クォータは1ない性質(試みの後に、問題が残る)となります。
ポイント2方法:私はK8S非常に精通していないですので、私はサプリメントに続い研究とするために、待ちます。
最初の三つの方法:設定GOMAXPROCS最も簡単な方法は、環境変数を追加するためのスクリプトを開始することです
GOMAXPROCS = 2 ./svr_binこれは有効であるが、欠点もありますが、あなたはクォータ大きなコンテナを展開した場合、スクリプトは変化に追従することはできません。
ユーバーライブラリautomaxprocs
ユーバーは、コンテナ行くプロセスを開始するが、それはGOMAXPROCSが正しい設定されますライブラリ、go.uber.org/automaxprocsを、持っている。コードテンプレートを変更します。私たちはgo.modでライブラリを参照します
-
go.uber.org/automaxprocs v1.2.0
インポートおよびmain.go
-
import (
-
_ "go.uber.org/automaxprocs"
-
)
効果
ヒントautomaxprocsライブラリー
使用automaxprocsライブラリには、次のログを持っています。
-
仮想マシンまたは物理マシンの場合
8コアの場合:2019年11月7日夜05時29分47秒maxprocsに:終了GOMAXPROCS = 8:CPU割当は不定
-
コアコンテナクォータの複数のセットについて
2019年11月8日夜07時30分50秒maxprocsに:更新GOMAXPROCS = 8:CPUクォータから決定
-
コンテナは、一つの核クォータよりも配置されています。
2019年11月8日夜7時19分30秒maxprocsに:GOMAXPROCS = 1の更新:GOMAXPROCS許可使用最小
-
無クォータ]ドッキングウィンドウであれば
2019年11月7日夜7時38分34秒maxprocsに:GOMAXPROCS = 79を残す:CPUクォータ未定義
明示的に起動スクリプトに設定されたこの提案でGOMAXPROCS
要求応答
設定後は、その後、AB要求、60msののネットワークラウンドトリップ時間を見てみましょ少ない200msの99%以上を要求し、前600msのです。同じCPUの消費量の下では、ほとんど倍増からQPS。
ランタイムおよびGCトレース情報
分布は1 GCポーズとして識別0.5コア、GOMAXPROCであるため非常に低く、スレッドの数も11以上170下から見ることができるが、米国の多数は、見えます。
-
gc 97 @54.102s 1%: 0.017+3.3+0.003 ms clock, 0.017+0.51/0.80/0.75+0.003 ms cpu, 9->9->4 MB, 10 MB goal, 1 P
-
gc 98 @54.294s 1%: 0.020+5.9+0.003 ms clock, 0.020+0.51/1.6/0+0.003 ms cpu, 8->9->4 MB, 9 MB goal, 1 P
-
gc 99 @54.406s 1%: 0.011+4.4+0.003 ms clock, 0.011+0.62/1.2/0.17+0.003 ms cpu, 9->9->4 MB, 10 MB goal, 1 P
-
gc 100 @54.597s 1%: 0.009+5.6+0.002 ms clock, 0.009+0.69/1.4/0+0.002 ms cpu, 9->9->5 MB, 10 MB goal, 1 P
-
gc 101 @54.715s 1%: 0.026+2.7+0.004 ms clock, 0.026+0.42/0.35/1.4+0.004 ms cpu, 9->9->4 MB, 10 MB goal, 1 P
コンテキスト切り替え
クォータの数がPの数に応じて設けながら、同時50後、STAT比較結果PERF 8000要求処理の総。CPUコア76 Pのデフォルト数は、コンテキストは、13万回、pidstatビューシステムCPU消費コア9%スイッチのみ20,000回のコンテキスト切り替え、CPUは核の3%を消費します。
分析の原則automaxprocs
、コードは読んだ後、実際には、原理は複雑ではありません、周りのビットどのようにクォータの設定GOMAXPROCSこと。ドッカー利用のcgroupを制限CPUの使用コンテナにこのライブラリ、コンテナの設定cpu.cfsquotaus / cpu.cfsperiodusを使用するには、CPUの割り当てを取得することができます。そのため、キーは、2隻の値を見つけることです。
マウントは、情報のcgroupを取得します
猫の/ proc /自己/ mountinfo
-
....
-
1070 1060 0:17 / /sys/fs/cgroup ro,nosuid,nodev,noexec - tmpfs tmpfs ro,mode=755
-
1074 1070 0:21 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory
-
1075 1070 0:22 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,devices
-
1076 1070 0:23 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,blkio
-
1077 1070 0:24 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,hugetlb
-
1078 1070 0:25 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpuacct,cpu
-
1079 1070 0:26 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpuset
-
1081 1070 0:27 / /sys/fs/cgroup/net_cls rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,net_cls
-
....
cpuacct、/ SYS / FS / cgroup内/ CPUの下のCPUは、このディレクトリをcpuacct。
コンテナのcgroupサブディレクトリを取得します。
猫の/ proc /自己/ cgroup内
-
10:net_cls:/kubepods/burstable/pod62f81b5d-xxxx/xxxx92521d65bff8
-
9:cpuset:/kubepods/burstable/pod62f81b5d-xxxx/xxxx92521d65bff8
-
8:cpuacct,cpu:/kubepods/burstable/pod62f81b5d-xxxx/xxxx92521d65bff8
-
7:hugetlb:/kubepods/burstable/pod62f81b5d-5ce0-xxxx/xxxx92521d65bff8
-
6:blkio:/kubepods/burstable/pod62f81b5d-5ce0-xxxx/xxxx92521d65bff8
-
5:devices:/kubepods/burstable/pod62f81b5d-5ce0-xxxx/xxxx92521d65bff8
-
4:memory:/kubepods/burstable/pod62f81b5d-5ce0-xxxx/xxxx92521d65bff8
-
....
特定/ kubepods /破断可能な下/ pod62f81b5d-XXXX / xxxx92521d65bff8サブディレクトリ内のコンテナ、CPUをcpuacct
計算されたクォータ
-
cat /sys/fs/cgroup/cpu,cpuacct/kubepods/burstable/pod62f81b5d-5ce0-xxxx/xxxx92521d65bff8/cpu.cfs_quota_us
-
50000
-
-
cat /sys/fs/cgroup/cpu,cpuacct/kubepods/burstable/pod62f81b5d-5ce0-xxxx/xxxx92521d65bff8/cpu.cfs_period_us
-
100000
両方0.5を分割して得られる、1〜1未満、GOMAXPROCSセット場合は、計算された数よりも大きくなるように設定されています。
カーネル
automaxprocsライブラリコア機能次のように、CGが計算次いで、それぞれcpu.cfs_period_usを読み出してcpu.cfs_quota_usのすべての構成のcgroup解析されたパスです。
公式問題
Googleの次を検索し、それはまた、この問題に言及しました。
ランタイム:長いGC STW一時停止(≥80ms)#19378 https://github.com/golang/go/issues/19378
概要
-
一般的に工作機械の核CPUコア数の数、大きい方> 32値、高い数値にPの設定に行くことに至る過程を見るためにコンテナプロセス、およびスレッドPの多くを開きます
-
スレッドので、小さなクォータ、一般的なクォータの容器は、0.5〜4、公平であるグループスケジューリングスレッドとしてコンテナへのLinuxのスケジューラ、大規模なものではなく、実行することができ、各スレッドは、特定の実行時間を保証します要求が非常に小さいが、マルチコンテキストの切り替えですが、それはスレッドが大幅に100ミリ秒の要求に影響を与えるレベルにまで上昇するSTW時間によって引き起こさSTWスケジュールの遅延を、開始した可能性があり
-
スレッドの数、GC休止安定に<1msのように、同一のCPU消費量を削減、CPU容器に割り当てクォータ、および正しく設定GOMAXPROCS Pの数に従って、automaxprocsライブラリを使用して、QPSは、平均倍増します応答時間は100ミリ秒に200ミリ秒から減少。1/6切替元のスレッドコンテキストに減少します
-
また、ライブラリ。cgroupのディレクトリはcpu.cfs_quota_us / cpu.cfs_period_us下の容器、計算cpuacct、CPUを見つけるという単純な原理を分析し、CPUの監査が割り当てられるものとします。
-
CPUコアの割り当ての数を確認するには、コンテナプロセスが割り当てられている場合はもちろん、それはまた、この問題を解決することができます。私はかなりのこの側面を理解していません。