ベンチマーク ツールで同時ユーザー数を 2000 に増やそうとしています。シミュレーションには locust を使用しています。
私のサーバーには 24vCPU、128GB RAM、25SSD が搭載されています。
2000 人の同時ユーザーにエラーなくサービスを提供できるようにしたいのですが、700 人のユーザーを超えた時点で問題が発生します。
ガンイコーン
非同期処理ができるように gevent をインストールしましたが、負荷テストでは何も変わりませんでした (gevent が動作していないのでしょうか?)。私の systemd ファイルは次のとおりです。
mysite-production.conf
[Unit]
Description=mysite production daemon
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/mysite/production/src
ExecStart=/var/www/mysite/production/venv/bin/gunicorn --worker-class=gevent --worker-connections=1000 --workers=49 --bind unix:/var/www/mysite/production/sock/gunicorn --log-level DEBUG --log-file '/var/www/mysite/production/log/gunicorn.log' mysite.wsgi:application
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
[Install]
WantedBy=multi-user.target
私の計算によると、1 秒あたり 49 x 1000 = 49000 件のリクエストを処理できることになります。
代わりに、約 700 人のユーザーで、Locust の失敗タブに次のエラーが表示されます。
# fails Method Name Type
1227 GET // HTTPError('500 Server Error: Internal Server Error for url: http://my.site.com//')
基本的には、内部サーバーエラーが発生していることを示しています。
gunicorn.logを開くとEPIPEを無視する:
グニコーンログ
[2020-01-27 20:22:30 +0000] [13121] [DEBUG] Ignoring EPIPE
[2020-01-27 20:22:31 +0000] [13121] [DEBUG] Ignoring EPIPE
[2020-01-27 20:22:31 +0000] [13121] [DEBUG] Ignoring EPIPE
[2020-01-27 20:22:31 +0000] [13121] [DEBUG] Ignoring EPIPE
[2020-01-27 20:22:31 +0000] [13121] [DEBUG] Ignoring EPIPE
エンギンクス
私の nginx access.log には 499 および 500 エラーがいくつか表示されます。
アクセスログ
185.159.126.246 - - [27/Jan/2020:19:22:25 +0000] "GET // HTTP/1.1" 200 30727 "-" "python-requests/2.22.0"
185.159.126.246 - - [27/Jan/2020:19:22:25 +0000] "GET // HTTP/1.1" 499 0 "-" "python-requests/2.22.0"
185.159.126.246 - - [27/Jan/2020:19:22:25 +0000] "GET // HTTP/1.1" 499 0 "-" "python-requests/2.22.0"
185.159.126.246 - - [27/Jan/2020:19:22:25 +0000] "GET // HTTP/1.1" 200 30727 "-" "python-requests/2.22.0"
185.159.126.246 - - [27/Jan/2020:19:22:25 +0000] "GET // HTTP/1.1" 500 2453 "-" "python-requests/2.22.0"
185.159.126.246 - - [27/Jan/2020:19:22:25 +0000] "GET // HTTP/1.1" 500 2453 "-" "python-requests/2.22.0"
185.159.126.246 - - [27/Jan/2020:19:22:25 +0000] "GET // HTTP/1.1" 499 0 "-" "python-requests/2.22.0"
185.159.126.246 - - [27/Jan/2020:19:22:25 +0000] "GET // HTTP/1.1" 499 0 "-" "python-requests/2.22.0"
nginxのerror.logには何も表示されませんが、前回のテストではリソースが一時的に利用できません:
エラーログ
2020/01/27 19:15:32 [error] 1514#1514: *57151 connect() to unix:/var/www/mysite/production/sock/gunicorn failed (11: Resource temporarily unavailable) while connecting to upstream, client: 185.159.126.246, server: my.site.com, request: "GET // HTTP/1.1", upstream: "http://unix:/var/www/mysite/production/sock/gunicorn://", host: "my.site.com"
2020/01/27 19:15:32 [error] 1514#1514: *56133 connect() to unix:/var/www/mysite/production/sock/gunicorn failed (11: Resource temporarily unavailable) while connecting to upstream, client: 185.159.126.246, server: my.site.com, request: "GET // HTTP/1.1", upstream: "http://unix:/var/www/mysite/production/sock/gunicorn://", host: "my.site.com"
私の nginx.conf は次のとおりです:
nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
worker_rlimit_nofile 40000;
events {
worker_connections 4096;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
これが私のサーバー ブロックです。
my.site.com (サーバーブロック)
upstream mysite-production {
server unix:/var/www/mysite/production/sock/gunicorn;
}
server {
listen [::]:80;
listen 80;
server_name my.site.com;
# set client body size to 100M #
client_max_body_size 100M;
location / {
include proxy_params;
proxy_pass http://unix:/var/www/mysite/production/sock/gunicorn;
}
location /static/ {
root /var/www/mysite/production/;
expires 30d;
add_header Vary Accept-Encoding;
access_log off;
gzip on;
gzip_comp_level 6;
gzip_vary on;
gzip_types text/plain text/css application/json application/x-javascript application/javascript text/xml application/xml application/rss+xml text/javascript image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype;
}
location /media/ {
root /var/www/mysite/production/;
expires 30d;
add_header Vary Accept-Encoding;
access_log off;
}
}
質問
これらすべてを見ると、次のような疑問が湧いてきます。
502 エラーはどこから来ているのでしょうか? 何が起こっているのか理解するのに十分な情報が表示されません... 700 人のユーザーがエラーを引き起こした後、すべてのワーカーが占有されているのでしょうか?
499 エラーはどこから発生するのでしょうか?
これは私の postgresql データベースと何か関係があるのでしょうか? もしそうなら、どうすればわかりますか?
gevent が機能しているかどうかはどうすればわかりますか? ab と locust を使用した負荷テストの結果は実際には変わっていません。
何をするEPIPEを無視するそれは何を意味し、なぜ起こっているのでしょうか?
時間を割いてこれを見ていただきありがとうございます。コメントや回答をいただければ幸いです。
さらに詳しい情報が必要な場合はお知らせください。質問に追加します。
編集:
@ServerFaults のコメントに基づいて、負荷テストが発生したときにどれだけのメモリが消費されるかを確認しました。どうやら特に重大なことはないようです。
MemTotal: 132027088 kB
MemFree: 127013484 kB
MemAvailable: 126458072 kB
Buffers: 57788 kB
Cached: 401088 kB
実行後netstat -s
(すべてが何を意味するのか理解する知識はありません):
Ip:
Forwarding: 2
6956023 total packets received
8 with invalid addresses
0 forwarded
0 incoming packets discarded
6953503 incoming packets delivered
6722961 requests sent out
20 outgoing packets dropped
Icmp:
107 ICMP messages received
0 input ICMP message failed
ICMP input histogram:
destination unreachable: 45
echo requests: 62
968 ICMP messages sent
0 ICMP messages failed
ICMP output histogram:
destination unreachable: 906
echo replies: 62
IcmpMsg:
InType3: 45
InType8: 62
OutType0: 62
OutType3: 906
Tcp:
222160 active connection openings
136492 passive connection openings
78293 failed connection attempts
161239 connection resets received
2 connections established
6245053 segments received
6487229 segments sent out
11978 segments retransmitted
0 bad segments received
185530 resets sent
Udp:
667101 packets received
41158 packets to unknown port received
0 packet receive errors
727164 packets sent
0 receive buffer errors
0 send buffer errors
UdpLite:
TcpExt:
2939 SYN cookies sent
28 SYN cookies received
215 invalid SYN cookies received
113 resets received for embryonic SYN_RECV sockets
18751 TCP sockets finished time wait in fast timer
175 packetes rejected in established connections because of timestamp
61997 delayed acks sent
54 delayed acks further delayed because of locked socket
Quick ack mode was activated 3475 times
2687504 packet headers predicted
1171485 acknowledgments not containing data payload received
2270054 predicted acknowledgments
TCPSackRecovery: 921
Detected reordering 22500 times using SACK
Detected reordering 596 times using time stamp
139 congestion windows fully recovered without slow start
490 congestion windows partially recovered using Hoe heuristic
TCPDSACKUndo: 14
413 congestion windows recovered without slow start after partial ack
TCPLostRetransmit: 47
TCPSackFailures: 5
7 timeouts in loss state
2416 fast retransmits
123 retransmits in slow start
TCPTimeouts: 5279
TCPLossProbes: 4284
TCPLossProbeRecovery: 22
TCPSackRecoveryFail: 1
TCPDSACKOldSent: 3482
TCPDSACKRecv: 1996
TCPDSACKOfoRecv: 4
52968 connections reset due to unexpected data
54079 connections reset due to early user close
51 connections aborted due to timeout
TCPDSACKIgnoredOld: 25
TCPDSACKIgnoredNoUndo: 822
TCPSpuriousRTOs: 81
TCPSackShifted: 4787
TCPSackMerged: 5128
TCPSackShiftFallback: 33199
TCPReqQFullDoCookies: 2939
TCPRcvCoalesce: 84434
TCPOFOQueue: 26
TCPChallengeACK: 3
TCPAutoCorking: 7
TCPFromZeroWindowAdv: 125
TCPToZeroWindowAdv: 125
TCPWantZeroWindowAdv: 1376
TCPSynRetrans: 4695
TCPOrigDataSent: 5023492
TCPHystartTrainDetect: 2403
TCPHystartTrainCwnd: 53596
TCPHystartDelayDetect: 346
TCPHystartDelayCwnd: 9883
TCPACKSkippedSynRecv: 6
TCPACKSkippedPAWS: 10
TCPACKSkippedSeq: 15
TCPWinProbe: 15
IpExt:
InOctets: 6090026491
OutOctets: 7098177391
InNoECTPkts: 6966279
InECT0Pkts: 11
InCEPkts: 1
編集2:
Gunicorn を生成せずに静的 HTML ページを作成した後、遅延なしで 4000 人のユーザーに簡単にサービスを提供できました。worker_connections を渡すと、次の結果を受け取りました。
/loadtest/ ConnectionError(MaxRetryError("HTTPConnectionPool(host='ll-my.site.com', port=80): Max retries exceeded with url: /loadtest/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x....>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known'))"))
私が理解していることは、NGINX はここでは問題ではないということです。
編集3:
postgresql ログを確認したところ、次のエラーがいっぱいあることがわかりました。
FATAL: remaining connection slots are reserved for non-replication superuser connections