Обязательное руководство по предотвращению ям Nginx для интерфейсных пользователей

задняя часть Nginx
Обязательное руководство по предотвращению ям Nginx для интерфейсных пользователей

Эта статья участвует в "Реальный боевой рекорд оптимизации производительности — эксклюзивный трек NGINX» Тема Призыв к докладам

написать впереди

Nginx — это высокопроизводительный HTTP-сервер с открытым исходным кодом и обратный прокси-сервер; он также является прокси-сервером IMAP, POP3, SMTP; Nginx можно использовать в качестве HTTP-сервера для публикации веб-сайтов, а Nginx также можно использовать в качестве обратного прокси-сервера. , Реализация балансировки нагрузки. Многие веб-сайты и платформы используют nginx в качестве прокси-сервера для оптимизации и повышения производительности системы.Сегодня я расскажу о ямах, которые nginx облазил за время его использования.

1. Лимит соединений Nginx

Nginx очень легко столкнуться со слишком большим количеством подключений в сценариях с высоким параллелизмом. Когда пользователь инициирует запрос, будет создан дескриптор файла. Дескриптор файла будет увеличиваться с увеличением количества запросов, но дескриптор файла Nginx и системы ограничено. Если лимит превышен, Nginx сообщит об ошибке.

Взяв CentOS в качестве примера, вы можете ввести следующую команду в командной строке, чтобы просмотреть максимальное количество дескрипторов файлов, настроенных по умолчанию на сервере.

# ulimit -n
1024

Как видите, на сервере CentOS максимальное количество дескрипторов файлов по умолчанию равно 1024. Когда количество подключений Nginx превышает 1024, в журнале ошибок Nginx будет отображаться следующее сообщение об ошибке.

[alert] 13576#0: accept() failed (24: Too many open files) 

Решение первое:

Количество дескрипторов открытых файлов может быть установлено достаточно большим, команда выглядит следующим образом:

ulimit -n 655350

В то же время измените nginx.conf и добавьте следующие элементы конфигурации.

worker_rlimit_nofile 655350; 

Это может решить проблему слишком большого количества подключений Nginx и обеспечить высокий параллелизм. Следует отметить, что модификация с помощью команды ulimit -n 655350 действительна только для текущей оболочки и будет недействительна после выхода.

Решение второе:

Чтобы измененное значение вступило в силу постоянно, вы должны изменить файл конфигурации, вы можете изменить файл конфигурации /etc/security/limits.conf, как показано ниже.

vim /etc/security/limits.conf

Добавьте следующие элементы конфигурации в конец файла.

* soft nofile 655360
* hard nofile 655360

Звездочка обозначает глобальные, мягкие — программное обеспечение, жесткие — аппаратные средства, а nofile — количество дескрипторов открытых файлов.

Во-вторых, приоритет доступа к виртуальному хосту

Приоритет доступа нескольких виртуальных хостов под одним и тем же server_name отличается

#/etc/nginx/conf.d文件夹下面文件排序方式
testserver1.conf testserver2.conf

#testserver1.conf
server{
	listen 80;
	server_name testserver1 juejin.com;
	location {
		root /opt/app/code1;
		index index.html;
	}
}

#testserver2.conf
server{
	listen 80;
	server_name testserver2 juejin.com;
	location {
		root /opt/app/code2
		index index.html;
	}
}

На данный момент nginx определяется в соответствии с порядком чтения конфигурационных файлов в файле /etc/nginx/conf.d. Поэтому сначала прочитайте testserver1.conf и по умолчанию получите доступ к /opt/app/code1.

3. Nginx Proxy занимает слишком много памяти

После включения Nginx Proxy Cache использование памяти через некоторое время достигает 98%, что приводит к резкому падению производительности. Проблема высокого использования памяти — это проблема ядра, в ядре используется механизм LRU, который можно улучшить, изменив параметры ядра:

sysctl -w vm.extra_free_kbytes=6463787
sysctl -w vm.vfs_cache_pressure=10000

Если производительность прокси-кэша низкая при развертывании на жестком диске, вы можете использовать кеш tmpfs или nginx для обмена метаданными кеша словаря или напрямую подключиться к SSD.

В-четвертых, как использовать сопоставление путей Nginx Try_files

Правила синтаксиса для try_files:

//格式1
try_files *file* ... *uri*; 
//格式2
try_files *file* ... =*code*;

Применимый контекст: сервер, сегмент местоположения

Процесс реализации:

Найти существующие файлы в указанном порядке файлов и использовать первый найденный файл для обработки запроса

Путь поиска ищется в соответствии с заданным корнем или псевдонимом в качестве корневого пути.

Если ни один из заданных файлов не совпадает, повторно запросите uri, заданный последним параметром, который соответствует новому местоположению.

Если это формат 2, если последний параметр = 404, если ни один из заданных файлов не совпадает, в конце будет возвращен код ответа 404

location /images/ {
root /ht/;
try_files $uri $uri/ /images/default.gif;
}

Например, запрос 127.0.0.1/images/test.gif проверит в свою очередь

1. Файл /ht/test.gif

2. Индексный файл в папке /ht/

3. Если не найдет, запросит 127.0.0.1/images/default.gif Следует отметить, что если $uri/ не прописан в try-файлах, при прямом доступе к пути к каталогу он не будет соответствовать странице индекса в каталоге. То есть доступ к 127.0.0.1/images/ не приведет к доступу к 127.0.0.1/images/index.html.

5. Как Nginx запрещает прямой доступ по IP

Когда пользователь заходит на веб-сайт, посетив IP-адрес или неизвестное доменное имя, можно запретить отображение любого действительного контента и вернуть ему 500.

server {
 listen 80;
 server_name www.juejin.com # 这里指定自己的域名
}
server{
 listen 80 default_server; # 默认优先返回
 server_name _; # 空主机头或IP
 return 500; # 返回500错误
}
也可以将流量集中导入自己的网站,只要做以下跳转设置就可以

server {
 listen 80 default_server;
 return 302 https://www.juejin.com;
}

6. Nginx блокирует IP-адрес реальных вредоносных атак

За злонамеренное поведение, такое как сканеры, сканирование, кража ресурсов и злонамеренные атаки, IP-адрес может быть заблокирован напрямую.

server {
 listen 80;
 server_name juejin.com;
 location / {
 set $allow true;
 if ($http_x_forwarded_for ~ "127.0.*.*|127.0.0.120|127.0.0.130"){
 set $allow false;
 }
 if ($allow = false){
 return 403;
 }
 }
}

7. Проблема «ударной группы»

Рабочие процессы в Nginx обычно настраиваются в соответствии с количеством ядер ЦП в системе.Сколько ядер ЦП имеется, количество рабочих процессов будет настроено.Когда рабочий процесс запустится, он будет использовать функцию fork для создания несколько рабочих процессов, и все рабочие процессы будут прослушивать порт прослушивания, настроенный в nginx.conf, чтобы в полной мере использовать производительность многоядерных машин. Когда поступает запрос на подключение клиента, будет сообщено о новом событии подключения, и каждый рабочий процесс перехватит это событие, что является проблемой «шокированного стада». Чем больше рабочих процессов, тем более очевидной будет проблема, которая снизит производительность системы, поэтому следует избегать проблемы «шокированного стада».

Например: когда нет запроса пользователя, все рабочие процессы спят, в это время пользователь инициирует запрос на подключение к серверу, например, в режиме опроса, когда ядро ​​​​получит пакет TCP SYN, оно проснется all sleep Рабочий процесс, который первым получает запрос на соединение, может успешно установить новое соединение, и соединения других рабочих процессов завершатся ошибкой. Эти неудачные пробуждения не нужны, поскольку вызывают ненужное переключение контекста процесса и увеличивают нагрузку на систему, что является типичным сценарием проблемы «шокового стада».

Прикладной уровень Nginx разработал механизм для решения этой проблемы: предусмотрено, что только один рабочий процесс может одновременно прослушивать веб-порт, поэтому новое событие подключения может разбудить только один рабочий процесс. Внутренняя реализация фактически использует блокировку синхронизации между процессами. Рабочий процесс пытается установить эту блокировку каждый раз, когда просыпается, чтобы гарантировать, что только один рабочий процесс может одновременно войти в блокировку. Процесс, который получает блокировку, устанавливает событие чтения Для обработки будущих новых запросов на подключение и обработки связанных событий рабочий процесс, который не может войти в блокировку мониторинга, не прослушивает новое событие подключения, а только обрабатывает событие подключения. Пробужденный рабочий процесс разделены на две категории: 1. Один класс (только один) может прослушивать новые подключения, а другой класс нормально обрабатывает существующие запросы на подключение. Процесс, который установил прослушиватель событий соединения, будет разбужен, когда поступит событие соединения, и проверит системные переменные.Если в новой очереди соединений есть соединение, блокировка будет снята, и метод обработчика соответствующего события будет называться. Эта технология не только решает проблему, называемую «шоковой группой», но и позволяет избежать проблемы, заключающейся в том, что процесс занимает блокировку в течение длительного времени, так что новое соединение не может быть вовремя обработано.После получения соединения блокировка сразу снимается. после того, как соединение поставлено в очередь.Когда новое соединение приходит сразу же, новый рабочий процесс получает соединение, которое будет играть определенную роль в балансировке нагрузки, а события запроса, помещенные в очередь, будут обрабатываться в последующие этапы.

Восемь, правила сопоставления местоположения

location [=|~|~*|^~] /uri/ { … }

= начинается с точного совпадения

Начало ^~ означает, что uri начинается с обычной строки, которую можно понимать как соответствие URL-пути. nginx не кодирует URL-адреса, поэтому запрос имеет вид /static/20%/aa, что соответствует правилу ^~ /static/ /aa (обратите внимание на пробел).

~ начинается с обычного совпадения с учетом регистра

~* в начале означает регулярное сопоставление без учета регистра

!и!*Обычно для несоответствия с учетом регистра и несоответствия без учета регистра соответственно

/ Универсальное совпадение, подойдет любой запрос.

В случае конфигураций с несколькими местоположениями порядок сопоставления следующий: Первое совпадение =

Второй матч ^~

с последующим обычным сопоставлением по порядку в файле

Наконец, он передается / общему сопоставлению

При успешном совпадении прекратите сопоставление и обработайте запрос в соответствии с текущим правилом сопоставления.

location = / {
   #规则A
}
location = /login {
   #规则B
}
location ^~ /static/ {
   #规则C
}
location ~ \.(gif|jpg|png|js|css)$ {
   #规则D
}
location ~* \.png$ {
   #规则E
}
location / {
   #规则F
}

Тогда эффект следующий: Доступ к корневому каталогу /, например.http://localhost/будет соответствовать правилу A

доступhttp://localhost/loginбудет соответствовать правилу B,http://localhost/registerзатем сопоставьте правило F

доступhttp://localhost/static/a.htmlбудет соответствовать правилу C

доступhttp://localhost/a.gif, http://localhost/b.jpgбудет соответствовать как правилу D, так и правилу E, но правило D имеет приоритет по порядку, правило E не работает, иhttp://localhost/static/c.png первым соответствует правилу C

доступhttp://localhost/a.PNGзатем соответствует правилу E, но не правилу D, потому что правило E не чувствительно к регистру

доступhttp://localhost/category/id/1111Затем правило F, наконец, соответствует, поскольку ни одно из вышеперечисленных правил не соответствует, в это время nginx должен перенаправить запрос на внутренний сервер приложений.

9. Когда Nginx указывает путь, разница между корнем и псевдонимом

Основное различие между корневым и псевдонимом сопоставления пути заключается в том, как nginx интерпретирует uri за местоположением, что приводит к тому, что они по-разному сопоставляют запросы с файлами сервера.псевдоним — это определение псевдонима каталога, а корень — это определение верхнего каталог уровня. .

Результат обработки root: корневой путь + путь к местоположению.

Результат обработки псевдонима: заменить путь местоположения на путь псевдонима

1. Пример конфигурации корневого пути: пользователи посещают www.juejin.com/image/test.gif, фактически Nginx найдет файл test.gif в каталоге /code/image/ на собрании.

server {
 listen 80;
 server_name www.juejin.com;
 location /image/ {
 root /code;
 }
}

2. Пример конфигурации псевдонима: пользователи посещают www.juejin.com/image/test.gif, фактически Nginx будет искать файл test.gif в каталоге /code/.

server {
 listen 80;
 server_name www.juejin.com;
 location /image/ {
 alias /code;
 }
}

Десять, пользовательская страница ошибок настроек обратного прокси-сервера nginx

#Конфигурация прокси

# cat proxy.conf
server {
 listen 80;
 server_name test.juejin.com;
 location / {
 proxy_pass http://127.0.0.1:8080;
 proxy_intercept_errors on; #接收后端web4xx,5xx错误
 error_page 500 502 403 404 = /proxy_error.html; #将后端web抛出的错误定向到指定的页面
 }
 #如果有请求proxy_error.html文件的则指定到对应的目录
 location = /proxy_error.html {
 root /code/proxy;
 }
}

#Конфигурация внутреннего веб-узла

# cat web.conf
server {
 listen 8080;
 server_name test.juejin.com;
 root /code/web;
 index index.html;
 error_page 404 /404.html; #如果代理开启proxy_intercept_errors则后端web配置error_page无效
}

Суммировать

Выше перечислены проблемы, которые часто возникают при использовании Nginx. С какими «ямами» Nginx вы сталкивались? Добро пожаловать в зону комментариев для обмена кровью и слезами.