9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

supervisorのメッセージキューが溜まる

Posted at

supervisorのメッセージキューが溜まる

つい先日, supervisorのメッセージキューが溜まり続けていたので教訓として残す.

start_child, terminate_child, etc...の実装について

start_childを例に取る.
見ての通り, supervisorはgen_server behaviourで定義されており, start_childは内部的にはgen_server:call/3 (timeout: infinity) が呼ばれる.

その後, ここChildSpecに則り, 起動処理を行う.
起動処理は単純でerlang:apply/3の結果を見て, 成功していればChildSpecを保存・管理する.

gen_serverの起動処理

子の起動処理として以下の関数をここでは以下を想定しよう.

-module(hoge_server).
-behaviour(gen_server).
-compile(export_all).

start_link(Args) ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, Args, []).

init(Args) ->
    {ok, Args}. 

%% 以下略

supervisorのdo_start_child内のerlang:apply/3で実行されるのは, hoge_server:start_link/1である.

この中のgen_server:start_linkinit/1の処理が終わるまで結果を返さない.
(proc_lib:start_linksync_waitで待っている)

supervisorのメッセージキューが溜まる条件

以上を踏まると,

Mod:start_link + Mod:initにかかる時間に呼ばれるstart_childの回数が1回を超えるとメッセージキューが溜まることが分かる.
あとは, 処理待ち時間が増えていくのでstart_childが減らない限りは溜まり続けるだけだ.

ちなみに, gen_server behvaiourのterminate処理に時間がかかっても同様の事が実現できる.

つまり, start_link, init, terminate で通信を行うような重い処理をしてはならない.


パーツパーツとしては分かっていたつもりだったが...

  1. 帯域が埋まり, ラック内のサーバーへのRTTが40msになる.
  2. start_link, initで行っていた, 分散KVSへのリクエストに時間がかかる.
  3. supervisorのメッセージキューがたまる.
  4. gen_server:call -> supervisor:start_child してたのでtimeoutしまくる.

素晴らしいコンボだった.

9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?