У нас есть:
- Проект с нагрузкой ~ 1000-3000 RPS. В пиках - до 5К RPS.
- Партнёр к которому постоянно обращаемся за данными. (Одна из основных функций). Данные очень часто обновляются. Один пользователь создаёт нагрузку на партнёров ≈ 0.5 - 2 RPS. И это нормально, такая специфика...
- Основной сервер 16 Gb RAM, 16 Cores, Ubuntu 16.04.1 LTS, Nginx 1.10.3
- 5 серверов "поменьше" - на них крутится наш BackEnd
- Сервер с БД, Redis-ом и RabbitMQ
Упрощенно, взаимодействие можно представить следующим образом:
Основной nginx выступает в роли reverse-proxy. Балансирует нагрузку на наши сервера, и проксирует запросы к партнёрам.
Проблема:
При нагрузке некоторые запросы (~1K из 100K) начинают отпадать по тайм-ауту.
Провели нагрузочное тестирование:
- Если пользователь запрашивает данные от партнёров напрямую - все отдается быстро, четко и корректно. Вот линк на Yandex.Overload
- А вот график тестирования при проксировании через наш основной Nginx. В среднем - в два раз быстрее благодаря кэшированию, но если посмотреть на квантиль "100%"...
Причем проблема становится ГОРАЗДО существеннее, при пиковых нагрузках.
Есть идея попробовать другой reverse-proxy, например "Traefik" или тот-же Apache.
Но ведь Nginx - инструмент проверенный временем и сотнями крупных компаний с нагрузкой гораздо выше, нежели у нас. Поэтому, вероятнее всего проблема - в наших конфигах или(и) неверно настроенным сетевым взаимодействием.
Привожу примеры конфигурационных файлов (упростил, но оставил основные настройки).
nginx.conf (main)user www-data;
worker_processes 16;
worker_priority -10;
pid /run/nginx.pid;
worker_rlimit_nofile 200000;
events {
worker_connections 2048;
use epoll;
}
http {
sendfile on;
tcp_nopush off;
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_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
gzip_disable "msie6";
# 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;
upstream backend {
least_conn;
ip_hash;
server localhost:8082;
server 37.48.123.321:8082;
# other servers...
}
upstream partner_api {
server WW.XX.YY.ZZ;
}
proxy_cache_path /etc/nginx/conf.d/data/cache/line levels=1:2 keys_zone=line_cache:150m max_size=1g inactive=60m;
proxy_cache_path /etc/nginx/conf.d/data/cache/live levels=1:2 keys_zone=live_cache:150m max_size=1g inactive=60m;
include /etc/nginx/sites-enabled/*;
}
/etc/nginx/sites-enabled/domain.com.confserver {
listen 443 ssl http2;
server_name domain.com www.domain.com *.domain.com;
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/domain.com/chain.pem;
ssl_stapling on;
ssl_stapling_verify on;
resolver 127.0.0.1 8.8.8.8;
add_header Strict-Transport-Security "max-age=31536000";
include /etc/nginx/conf.d/reverse_porxy.conf;
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
error_page 500 502 503 504 /50x.html;
}
}
server
{
listen 80;
server_name domain.com www.domain.com;
location /
{
return 301 https://$host$request_uri;
}
}
/etc/nginx/conf.d/reverse_porxy.conflocation ~ ^/api/remote/(.+) {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
include /etc/nginx/conf.d/reverse_proxy_settings.conf;
proxy_pass http://partner_api/WebApiG/WebServices/BCService.asmx/$1;
}
location ~ ^/api/bs2/remote/api/line/(.+) {
include /etc/nginx/conf.d/reverse_proxy_settings.conf;
proxy_cache_valid any 2m;
proxy_pass http://partner_api/WebApiG/api/line/$1;
proxy_cache line_cache;
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
}
location ~ ^/api/bs2/remote/api/live/(.+) {
include /etc/nginx/conf.d/reverse_proxy_settings.conf;
proxy_pass http://partner_api/WebApiG/api/live/$1;
proxy_cache live_cache;
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
}
# etc...
/etc/nginx/conf.d/reverse_proxy_settings.confproxy_buffering on;
proxy_ignore_headers "Cache-Control" "Expires";
expires max;
proxy_buffers 32 4m;
proxy_busy_buffers_size 25m;
proxy_max_temp_file_size 0;
proxy_cache_methods GET;
proxy_cache_valid any 3s;
proxy_cache_revalidate off;
proxy_set_header Host "PARTNER_IP";
proxy_set_header Origin "";
proxy_set_header Referer "";
proxy_set_header Cookie '.TOKEN1=$cookie__TOKEN1; ASP.NET_SessionId=$cookie_ASP_NET_SessionId;';
proxy_hide_header 'Set-Cookie';
proxy_http_version 1.1;
Что можете посоветовать? Может, прокинуть VPN тоннель до партнёров или может действительно заменить nginx на что-то другое? (Увеличивать таймаут, как везде советуют - не наш случай)