nginx가 잠시 동안 일부 POST 요청을 중단합니다.

nginx가 잠시 동안 일부 POST 요청을 중단합니다.

Ubuntu 18.08에서 실행되고 docker-compose로 정의된 다음 스택이 있습니다.

  1. 대신에mariadb:10.3.20
  2. wordpress:5.3.0-php7.2설치된 ioncube기반 의 사용자 정의 WordPress 인스턴스
  3. nginx:1.13설치된 기반 nginx-amplify-agent의 사용자 정의 nginx 인스턴스

nginx의 설정:

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  10000;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';

    log_format  main_ext  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for" '
                          '"$host" sn="$server_name" '
                          'rt=$request_time '
                          'ua="$upstream_addr" us="$upstream_status" '
                          'ut="$upstream_response_time" ul="$upstream_response_length" '
                          'cs=$upstream_cache_status' ;

    access_log  /var/log/nginx/access.log  main_ext;
    error_log  /var/log/nginx/error.log warn;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

사이트는 다음과 같이 정의됩니다.

server {
        listen 80;
        listen [::]:80;

        server_name some.org www.some.org;

        location / {
                rewrite ^ https://$host$request_uri? permanent;
        }
}

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name some.org www.some.org;

        index index.php index.html index.htm;

        root /var/www/html;

        server_tokens off;

        ssl_certificate /etc/letsencrypt/live/some.org/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/some.org/privkey.pem;

        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-XSS-Protection "1; mode=block" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header Referrer-Policy "no-referrer-when-downgrade" always;
        add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
        # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        # enable strict transport security only if you understand the implications

        location / {
                proxy_connect_timeout 600;
                proxy_send_timeout    600;
                proxy_read_timeout    600;
                proxy_redirect        off;
                proxy_pass http://wordpress;

                proxy_set_header      X-Real-IP $remote_addr;
                proxy_set_header      X-Forwarded-Proto https;
                proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header      Host $host;
        }

        location = /favicon.ico {
                log_not_found off; access_log off;
        }

        location = /robots.txt {
                log_not_found off; access_log off; allow all;
        }

        location ~* \.(css|js|gif|ico|jpeg|jpg|png)$ {
                expires max;
                log_not_found off;
        }
}

10~15명의 사용자가 웹 사이트에 와서 작업을 수행하려고 하지 않는 한 전체 스택은 예상대로 작동합니다. 이 경우 일부 요청이 중단되기 시작하고(일반적으로 일부 구성 요소에 대한 동일한 POST 요청) 3~4분 후에는 중단됩니다. 오류 없이 해제되며 사용자는 실제로 그 결과를 확인할 수 있습니다. 중단된 사이트는 동일한 브라우저에서 책임을 지지 않습니다(그러나 다른 브라우저에서는 모든 것이 정상입니다!). 요청이 공개되면 사이트가 다시 책임을 집니다.

로그도 꽤 이상합니다.

  • 정지/보류 중인 요청이 서버에 오면 nginx 액세스 로그에는 표시되지만 wordpress 로그에는 표시되지 않습니다.
  • 요청이 최종적으로 해제되면(즉, 처리되면) nginx 액세스 로그와 wordpress 로그에 두 번째로 표시되지만 시간은 다릅니다.

nginx 액세스 로그:

62.96.39.243 - - [17/Jan/2020:10:56:41 +0000] "GET /something

78.43.40.52 - - [17/Jan/2020:10:56:41 +0000] "POST /ajax-bidsform.html?meth=post&yid=d7f9f1a1a0bf HTTP/2.0" 200 208 "https://some.org/xchange_XRP_to_SBERRUB/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" "-"

78.43.40.52 - - [17/Jan/2020:10:56:41 +0000] "GET /something

워드프레스:

134.19.130.91 - - [17/Jan/2020:10:56:40 +0000] "GET /something

78.43.40.52 - - [17/Jan/2020:10:50:07 +0000] "POST /ajax-bidsform.html?meth=post&yid=d7f9f1a1a0bf HTTP/1.0" 200 559 "https://some.org/xchange_XRP_to_SBERRUB/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36"

62.96.39.243 - - [17/Jan/2020:10:56:41 +0000] "GET /something

보시다시피 응답 POST /ajax-bidsform.html...시간은 nginx 로그에서는 10:56이지만 wordpress에서는 10:50입니다. 이는 클라이언트가 이 요청을 수행한 시간과 정확히 일치합니다. 내가 이해하는 한 이는 요청이 실제로 wordpress에 전달될 때까지 거의 6분 동안 nginx 수준 어딘가에서 멈췄음을 의미합니다. 보시다시피 nginx의 ddos ​​보호 지시문이 없습니다.

또한 제가 전하는 몇 가지 참고 사항은 정지 요청 중에는 CPU 또는 RAM의 장기적인 급증이 없으므로 하드웨어 문제와 관련이 없을 가능성이 높다는 것입니다. 나는 또한 이것이 스크립트 정지(예: ajax-bidsform.html)와 관련이 있다고 생각했지만 가상 호스팅에서 digital-ocean의 클라우드 인스턴스로 마이그레이션할 때만 발생하기 시작했기 때문에(이전에는 발생하지 않은 경우) 구성 문제인 것 같습니다. 로그의 요청 타임라인도 이를 증명합니다.

지금까지 나는 다음을 시도했습니다.

  1. worker_connections10000으로 증가
  2. nginx 인스턴스(호스트 인스턴스 아님)를 net.core.somaxconn1024로 늘립니다.

하지만 문제는 여전히 발생하고 있습니다. 어떤 아이디어나 생각이라도 주시면 감사하겠습니다!

답변1

nginx 로그에서는 10:56, wordpress에서는 10:50

나는 이것을 WordPress가 10시 50분에 요청을 받고 10시 56분에 결과를 nginx로 반환하는 것으로 해석합니다. 확실히 알기 위해 nginx에 추가할 수 upstream_response_time있습니다 log_format. 보다애플리케이션 성능 모니터링을 위해 NGINX 로깅 사용.

관련 정보