You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// MaxOpened is the maximum number of opened sessions allowed by the session
// pool. If the client tries to open a session and there are already
// MaxOpened sessions, it will block until one becomes available or the
// context passed to the client method is canceled or times out.
// Defaults to NumChannels * 100.
set the upper bound to an initial test number, such as 100. (For users working with the RPC API, we recommend having the cache store no more than 100 sessions, because 100 is the maximum number of concurrent sessions per gRPC channel.)
デフォルトでは gRPC チャンネル数は4になるため MaxOpened は 400 となるが、1インスタンスで並行トランザクション数 400 というのは App Engine や Cloud Run の max concurrency 80 と比べると十分すぎるほど大きい。
// MinOpened is the minimum number of opened sessions that the session pool
// tries to maintain. Session pool won't continue to expire sessions if
// number of opened connections drops below MinOpened. However, if a session
// is found to be broken, it will still be evicted from the session pool,
// therefore it is possible that the number of opened sessions drops below
// MinOpened.
// Defaults to 100.
#127 を踏まえて
spanner/v1.5.0
時点におけるセッション周りの設定の検討事項について書く。なお特に検証はしていないため正しさは保証しない。SessionPoolConfig
https://pkg.go.dev/cloud.google.com/go/spanner?tab=doc#SessionPoolConfig
MaxOpened
そのクライアントがセッションプールに入れることができるセッションの最大数。これ以上のセッション数を要求された場合ブロックする。
基本的にはあまり気にする必要がないが、 gRPC の1チャンネルあたり100セッションが限界であることに注意。
なお公式ドキュメントのセッションの説明には下記のように書かれている。
https://cloud.google.com/spanner/docs/sessions?hl=en#create_and_size_the_session_cache
デフォルトでは gRPC チャンネル数は4になるため
MaxOpened
は 400 となるが、1インスタンスで並行トランザクション数 400 というのは App Engine や Cloud Run の max concurrency 80 と比べると十分すぎるほど大きい。低すぎるとインスタンスのリソースを十分に活用できないが、高すぎるとセッションのオーバーヘッドが上がるケースがあると考えられる。
よって、セッション数に対してスケールする限界値に定めておくと良さそう。
ベンチマーク等によって1インスタンスあたりのセッション数をそれ以上上げてもパフォーマンスが増えず、セッションキャッシュのためのリソースが無駄になることが判明する事があれば、
MaxOpened
を増やしてスケールアップするよりもインスタンス数をスケールアウトした方が良いだろう。MinOpened
セッションプールの中のセッションが使われていなくてもこれ以上は減らさない最低数。
spanner/v1.2.0
以降はクライアント作成直後に initPool としてBatchCreateSessions
RPC を使ってこの数のセッションを必ず確保する。少なすぎるとコールドスタート直後や一定時間以上リクエストが低下した後のスパイク時に不足しているセッションを
CreateSession
RPC を発行するための待ち時間が発生する。多すぎると無駄なセッションを確保したまま解放できなくなる。
特に、CLI ツールやバッチのような並行してトランザクションを実行せずにクライアントの寿命も短いものでは大量のセッションを作成して即解放するような挙動になる場合がある。この場合はデフォルトの100は適していないため、最低限必要な数まで下げると良いだろう。
また、クライアントが Close されないなど何らかの理由で
DeleteSession
RPC が呼ばれずにセッションリークした場合は1時間はセッションが生き続けることになり、場合によっては Cloud Spanner のサーバサイドのリソースが枯渇するので注意すること。MaxIdle
直近使われたセッション数よりも余裕を持ってセッションプールの idleList に入れておく数。
spanner/v1.1.0
で session pool maintenance に修正が入って以降は直近10分間で最大の in_use_session + MaxIdle の数のセッション数を維持するため、比較的セッション数が安定しやすくなり、
CreateSession
RPC とDeleteSession
RPC が繰り返されるケースが減るとのこと。少なすぎるとスパイク時に
CreateSession
RPC の待ちが発生する。多すぎると無駄なセッションによるオーバーヘッドが発生する。
MaxBurst
spanner/v1.6.0 の BatchCreateSessions 導入以降全く意味を持たない。ライブラリの互換性を保つために削除はされていないが、ノイズになるので指定しない。
googleapis/google-cloud-go#4115
v1.6.0 より前の挙動についての記述
セッションが足りない時に一度に新しく作成できる最大数。これを超える数が一度に要求された場合はブロックする。
少なすぎるとトランザクション数の変化に十分に反応できない。
多すぎるとセッション数の変化が急になりすぎ、セッション数が安定しなくなったり、 Cloud Spanner の API 側で
CreateSession
RPC が弾かれるかもしれない。WriteSessions
デフォルトの 0.2 は
SessionPoolConfig
を使わない時のみ適用されるため、SessionPoolConfig
を指定した場合のゼロ値は 0.0 となる。idleList から
BeginTransaction
RPC を発行済のReadWriteTransaction
をidleWriteList
に分けてプールしておく割合。少なすぎると
ReadWriteTransaction
の中の処理の前にBeginTransaction
RPC によるレイテンシが発生する頻度が多くなる。多すぎると
ReadWriteTransaction
には使われず、そのまま abort もしくはセッション自体が解放されたりReadOnlyTransaction
に使われたりして単にBeginTransaction
RPC しただけ無駄になるセッションが多くなるとは思われるが、10秒間オペレーションがない idle transaction が abort されるのは一度でもオペレーションを行ってからなので、単に BeginTransaction しただけのトランザクションが abort されることは稀である。仮に pool から取得された
ReadWriteTransaction
が既に abort されていた場合のペナルティはBeginTransaction
からやり直すというものになる。
通常のケースで
BeginTransaction
1回分のラウンドトリップが減らせる方がメリットが大きいため、 MinOpened が 5 なら 0.2 以上など、1以上の write session pool があるには設定すると良い。(1ラウンドトリップに掛かる時間は通常は短いため許容できることも多いが、何らかの理由で RPC のレイテンシが安定しない場合に差が広がることがある。)
なお、データベースを更新する必要が全くない場合に
spanner.databaseReader
ロールを設定するなどしてReadWriteTransaction
としてBeginTransaction
RPC を発行するパーミッションがない場合にはエラーは無視される ためそのまま動作さえることができるが、BeginTransaction
RPC を発行するだけ無駄なので明示的にWriteSessions
を0に設定することが好ましい。HealthCheckWorkers
,HealthCheckInterval
コメントにはデフォルト値でも理論上 300K セッションを捌けると書かれているが、実際には spanner/v1.3.0, spanner/v1.4.0, spanner/v1.5.0 でヘルスチェック周りは大きく変更されており、1時間でセッションタイムアウトする前に約50分間隔で
SELECT 1
を発行して keepalive するという公式に推奨される適切な挙動になっているので特に設定を変更するモチベーションはないと考えられる。なお
spanner/v1.1.0
以降のセッション数計算に使われるhealthCheckSampleInterval
とmaintenanceWindowSize
は export された変数ではないので設定は不可能。gRPC チャンネル設定
spanner/v1.3.0 で
ClientConfig.NumChannels
からoption.WithGRPCConnectionPool(numConns)
に設定項目が変わりgoogle-cloud-go
独自から gRPC-Go の Balancer API V2 に実装が変わったが、単純なラウンドロビンなのでアルゴリズムはあまり気にする必要がない。MaxOpened
に書いたように、gRPC チャンネル1つあたり100セッションまでしか扱えないため、ceil(MaxOpened / 100)
以上に設定する。観測方法
interal/trace.TracePrintf
を使って OpenCensus Trace attribute に色々な情報を出力しているので、 exporter を設定すると良い。TrackSessionHandles
でセッション周りのエラー時にセッション作成時のスタックトレースが出力される。ListSessions
でセッションがサイドに使われた時間の確認が可能。ClientConfig.SessionLabels
を設定することでより情報量が増える。追記
Refs
The text was updated successfully, but these errors were encountered: