😎

Android Emulatorとlocustを併用すると問題がある

2022/10/26に公開

執筆背景

locustで負荷試験を行なっていたところ、突然masterとworker間の通信が行われなくなった。
問題はmacを再起動すると、解消することだけが分かっていたので、それでやり過ごした。
だが、この問題が一日に何回も発生するようになり、さすがに解決しないとまずい状況になったので、解消に向けて動き始め、原因がタイトル通りAndroid Emulatorとlocustを併用したときに起きていたことがわかった。
これの解決方法とそれに至った経緯を共有したい気持ちになったので、この記事を作成する。

起きたこと

masterをデフォルトの設定で起動しているにも関わらず、workerを起動すると、以下のエラーが出てしまう。

[2022-10-19 18:05:40,754] PC-0003395.local/WARNING/locust.runners: Failed to connect to master 127.0.0.1:5557, retry 3/60.

エラー文を見ると、master processが127.0.0.1:5557で待ち受けていないのが原因のようだ。
ただ、masterは何も異常がなく動いていた。

問題特定の過程

masterは異常なく動いているので、5557ポートではもちろんmasterが待ち構えていると思っていた。
が、この考えがおかしいかもしれないと思ったので、以下のコマンドを実行して確かめてみた。

$ lsof -i -P | grep 5557            
qemu-syst 22439 user   50u  IPv4 0xc2cb5c75361377ab      0t0  TCP localhost:5557 (LISTEN)
qemu-syst 22439 user   51u  IPv6 0xc2cb5c79ffa78f63      0t0  TCP localhost:5557 (LISTEN)
qemu-syst 22439 user  103u  IPv4 0xc2cb5c7536e58243      0t0  TCP localhost:5557->localhost:52139 (ESTABLISHED)
adb       22897 user   14u  IPv4 0xc2cb5c753614ad13      0t0  TCP localhost:52139->localhost:5557 (ESTABLISHED)
$ ps aux | grep 22439
user  22439  29.4 10.1 414920784 1689008 s013  S+    8:10PM  53:09.20 /Users/user/Library/Android/sdk/emulator/qemu/darwin-aarch64/qemu-system-aarch64 -avd Pixel_6_API_33
user  37634   0.0  0.0 408628368   1520 s001  R+   10:32PM   0:00.00 grep 22439

確かめたところ、5557で待ち構えていたのはAndroid Emulatorで立ち上げたプロセスだった。
なぜこれが起きてしまうのか調べたところ、Android Emulatorは仮想デバイスに以下のようにポートを割り振る。

特定のマシンで実行されている最初の仮想デバイスのコンソールは、コンソール ポート 5554 と adb ポート 5555 を使用します。後続のインスタンスは、5556 / 5557、5558 / 5559 というように、2 ずつ増加するポート番号を使用します。範囲は 5554~5682 で、64 個の仮想デバイスを同時に使用できます。

https://developer.android.com/studio/run/emulator-commandline

これが原因でAndroid Emulatorが5557ポートを使ってしまうことがある。
そして、ポートが衝突して問題が起こっているようだ。

不明点

仮に上記が正しい場合、Android Emulatorで仮想デバイスを起動した後、locustでmaster nodeを立ち上げた時、ポートがすでに使われていることで、エラーになるのでは?と思ったが、なぜかそれが起きなかった。
これがどうしてなのか、不明である。

が、master.confにmaster-bind-host = 127.0.0.1と追加すると、ちゃんとエラーになる。
この辺り、ホスト / ポート / ネットワーク 周りの基礎がないので、しっかりと理解できない。
いずれ理解できるように精進したい。

結論

lsofコマンドは便利。何か通信がうまくいかない時は叩いてみるとわかることがあるかもしれないです。
別にAndroid Emulatorに限らず、ポート衝突した場合、同じ問題が起きる可能性があります。その時はコマンドを叩きましょう。

最後に

ネットワーク、ホスト、ポート辺りのOSの知識を仕入れたいです、、、、。

Discussion