###前提・実現したいこと
Webのサーバーサイド(APIなど)の開発を行っていて502エラーが発生するようになってしまいました。
現在複数台のサーバーでサービス動かしており
流れとしては以下のような感じです。
- ユーザーがUserのGETのリクエストを飛ばす
- UserサーバーがGET処理を実行
- UserサーバーのGET処理の中でInfoのGETを実行
-
InfoサーバーでGET処理を実行
-
InfoサーバーのGET処理の中でDataのGETを実行
-
DataサーバーでGET処理を実行
-
DataサーバーからInfoサーバーにレスポンスを返す
-
Infoサーバーがレスポンスを受け取りデータを整形
-
InfoサーバーからUserサーバーにレスポンスを返す
- Userサーバーがレスポンスを受け取りデータを整形
- Userサーバーがユーザーにレスポンスを返す
- ユーザーがレスポンスを受け取る
502エラーが発生する原因は
infoサーバー内ででているConnection refusedエラーが原因だと思っています。
これを解決する方法を探しています。
###発生している問題・エラーメッセージ
userサーバーで起きているエラー
urllib.error.HTTPError: HTTP Error 502: Bad Gateway
infoサーバーで起きているエラー
「InfoサーバーのGET処理の中でDataのGETを実行する」
このタイミングでエラーが発生します。
urllib.error.URLError: <urlopen error [Errno 111] Connection refused>
###設定周りの情報
gunicornの設定です。
関係ありそうな部分だけ抜粋しました。
workers = multiprocessing.cpu_count() * 2 + 1 worker_class = 'sync' worker_connections = 1000 max_requests = 0 timeout = 30 keepalive = 2
nginxの.confではアクセス数やレスポンスまでの時間制限などの設定は行っていないです。
試したこと
Connection refusedは必ず発生するわけではありませんでした。
頻度としては7回に1回ほどエラーが出ます。
発生しない場合は取得したかった内容が取得できています。
###補足情報(言語/FW/ツール等のバージョンなど)
取得しているデータは文字列で半角英数字記号で500字ほど。
json形式で取得します。
成否問わずレスポンスは0.5秒かからず返ってきます。
環境情報
EC2インスタンス
Linux
nginx
Python3
gunicorn
RDSインスタンス
MySQL
APIの取得の確認は主にChromeで行っています。
追記、試したこと1
gunicornの設定の下記2つを変更しての動作を確認してみました。
変更したところインスタンスを作成してから
約1時間ほどで適当に百数回以上GETを試しましたが502エラーは発生しませんでした。
しかし、時間がたってからGETを行ったところ502が発生。
以降発生するのは変わりませんが頻度は少しだけ減ったように感じます。
(1/7から1/10くらいに変化)
timeout = 30 -> 3000 keepalive = 2 -> 20
追記
nginxのキャッシュが溜まっているとかそういう面について調べましたが
キャッシュは作られていませんでした。(設定もしてないです)
また現在サーバーの再起動や何やらは切ってある状態で試しているため
もし停止したら停止しっぱなしになります。
追記2
Dockerで同じような状況を作って試してみました。
DockerでMySQLサーバーを立てて、
CentOSのサーバーを立てて、
AWSのEC2インスタンスとRDSインスタンスと同じ内容を詰め込んで
Docker内でやり取りさせてみました。
そして、502エラーが発生するまで無限ループを行うようスクリプトを準備し
それを12個ほどcmdから実行しています。
現在30分ほど経ちましたが今のところ502エラーは発生していません。
AWSでも同じことをして試してみます。
追記3:メモリが怪しそうです
free コマンドでメモリの使用量を確認したところ以下のように表示されました。
また、GETを繰り返すたびにMem-usedの値が上がっていくのが確認できました。
Mem-cachedはすぐには上がりませんでしたがココらへんについてもう少し深く調査してみようと思います。
[ec2-user@ip-172-31-29-13 ~]$ free -m total used free shared buffers cached Mem: 995 871 123 0 32 682 -/+ buffers/cache: 157 838 Swap: 0 0 0
追記4:メモリに負荷をかけてリクエストの結果
stress コマンドでメモリに負荷をかけて
stress --vm 2 --vm-bytes 400M --timeout 10m
10のプロセスから各1000回づつ、10/sでリクエストの送信を行っている状態での
vmstatコマンドの結果です。
2017/01/26 11:05:25 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu----- 2017/01/26 11:05:25 r b swpd free buff cache si so bi bo in cs us sy id wa st 2017/01/26 11:05:25 2 0 0 291484 4024 18948 0 0 10 25 77 85 1 1 98 0 0 2017/01/26 11:05:26 2 0 0 266260 4032 18940 0 0 0 48 265 298 13 87 0 0 0 2017/01/26 11:05:27 2 0 0 261168 4032 18940 0 0 0 0 251 258 16 84 0 0 0 2017/01/26 11:05:28 3 0 0 179840 4044 20852 0 0 1940 0 1979 1332 32 68 0 0 0 ...省略
メモリに負荷をかけていない状態ではcpu の id に余裕がありましたが、
負荷をかけた状態では上記のようになっています。
仕様について追記
nginxを起動後、gunicornを起動させて
その状態でずっと稼働しっぱなしにして動かしています。
そして、問題の502が起きるのは、しばらくアクセスを繰り返した後に発生し始めること
アクセスするたびにメモリが減っていく様子が確認できたことからそこら辺に原因があるかもしれないと思っています。
現在の状況
InfoサーバーやDataサーバーから取得するデータ量を減少させたて、
タイムアウトまでの時間を伸ばすことでほぼ502エラーが出ないことが確認できました。
一応以前は502エラーが発生していた時以上にはアクセスを繰り返してもエラーは発生しませんでした。
例としては 10プロセスから 10/s で 各1千回リクエストを飛ばすと行ったことをしましたが
エラーは発生せずに終えることができました。
また、UserサーバーからInfoサーバーにリクエストを飛ばした際に
正常な結果が得られるまでリクエストを飛ばすことで、無理やり押し通すことが出来るのも確認しました。
(これはコメントアウトした状態で検証しています。)
ただ、どちらも対処療法の領域をでておらず、
原因の特定に至っていないためまだ調査中と言った感じです。
ワーカープロセスについて
今回のことで初めて調べたのであっているかわかりませんがご了承ください。
nginx,gunicorn共にすべてのサーバーで同じ設定を行っています。
サーバーのスペックも同スペックで作成しています。
まずこちらのサイトを参考にCPUや最大プロセス数を調べたところ
http://www.crystalsnowman.com/?p=344
CPU : 1
最大プロセス数 : 1024
とわかりました。
また、nginxにはワーカープロセスについての設定を行って無い状態でした。
gunicornでは以下の設定は行っていました。
workers = multiprocessing.cpu_count() * 2 + 1 worker_class = 'sync' worker_connections = 1000 max_requests = 0
以下は動いているnginxとgunicornのプロセスを確認したものです。
[ec2-user@ip-xxx-xx-xx-xx ~]$ ps aux |grep nginx |grep -v grep root 17576 0.0 0.1 58088 1080 ? Ss 11:58 0:00 nginx: master process nginx ec2-user 17578 0.0 0.4 58600 4756 ? S 11:58 0:00 nginx: worker process [ec2-user@ip-xxx-xx-xx-xx ~]$ ps aux |grep gunicorn |grep -v grep ec2-user 17614 0.0 2.1 202156 22332 ? S 11:58 0:01 /home/ec2-user/.pyenv/versions/3.5.2/bin/python3.5 /home/ec2-user/.pyenv/versions/3.5.2/bin/gunicorn run:app --config guniconf.py ec2-user 17646 0.4 2.5 223292 25996 ? S 11:58 0:44 /home/ec2-user/.pyenv/versions/3.5.2/bin/python3.5 /home/ec2-user/.pyenv/versions/3.5.2/bin/gunicorn run:app --config guniconf.py ec2-user 17647 0.3 2.5 223296 26000 ? S 11:58 0:38 /home/ec2-user/.pyenv/versions/3.5.2/bin/python3.5 /home/ec2-user/.pyenv/versions/3.5.2/bin/gunicorn run:app --config guniconf.py ec2-user 17648 0.4 2.5 223248 26004 ? S 11:58 0:41 /home/ec2-user/.pyenv/versions/3.5.2/bin/python3.5 /home/ec2-user/.pyenv/versions/3.5.2/bin/gunicorn run:app --config guniconf.py
回答1件
あなたの回答
tips
プレビュー