편집하다:

편집하다:

벤치마킹 도구를 사용하여 동시 사용자 수를 2000명으로 늘리려고 합니다. 나는 메뚜기를 사용하여 시뮬레이션하고 있습니다.

내 서버에는 24vCPU, 128GB RAM, 25SSD가 있습니다.

2000명의 동시 사용자를 오류 없이 서비스할 수 있기를 원하지만 700명의 사용자만 지나면 문제가 발생합니다.

군니콘

비동기 서비스를 제공하기 위해 gevent를 설치했지만 부하 테스트에서는 아무 것도 변경되지 않았습니다(gevent가 작동하지 않을 수 있나요?). 내 시스템 파일은 다음과 같습니다.

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

내 계산에 따르면 처리할 수 있는 초당 요청 수는 49 x 1000 = 49000개입니다.

대신 약 700명의 사용자가 있으면 메뚜기 오류 탭에 다음 오류가 표시됩니다.

# fails Method  Name    Type
1227    GET     //  HTTPError('500 Server Error: Internal Server Error for url: http://my.site.com//')

기본적으로 내부 서버 오류가 있다고 말합니다.

내 gunicorn.log를 열면 알 수 있어요EPIPE 무시:

gunicorn.log

[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

관련 정보