Конкретный сценарий: кластер nginx с балансировкой нагрузки на уровне доступа пересылает его бизнес-nginx, а бизнес-nginx пересылает его внутреннему серверу приложений. Конфигурационный файл бизнес-nginx выглядит следующим образом:
upstream ads {
server ap1:8888 max_fails=1 fail_timeout=60s;
server ap2:8888 max_fails=1 fail_timeout=60s;
}
Если отображается бизнес-журнал nginx: при подключении к восходящему журналу отсутствуют восходящие потоки,
Кроме того, существует большое количество «преждевременно закрытых соединений восходящего потока при чтении заголовка ответа из журналов восходящего потока».
Буквальный смысл заключается в том, что nginx обнаруживает, что уцелевшего бэкэнда нет, но, как ни странно, с 502 появляются только некоторые исключения доступа к интерфейсу.
Вы можете посмотреть на это с точки зрения исходного кода nginx.
Поскольку это ошибка, связанная с восходящим потоком, найдите ключевое слово «нет живых восходящих потоков» в ngx_http_upstream.c, и вы сможете найти следующий код (фактически, вы обнаружите, что если вы выполните поиск в глобальном коде nginx, только этот файл имеет это ключевые слова):
Здесь видно, что когда rc равен NGX_BUSY, будет записана ошибка «нет прямых восходящих потоков».
Глядя на строку 1328, вы можете обнаружить, что значение rc возвращается функцией ngx_event_connect_peer.
ngx_event_connect_peer реализован в event/ngx_event_connect.c. В этой функции только это место вернет NGX_BUSY, другие места вернут NGX_OK, NGX_ERROR или NGX_AGAIN.
rc = pc->get(pc, pc->data);
if (rc != NGX_OK) {
return rc;
}
ПК здесь — указатель на структуру ngx_peer_connection_t, а get — указатель на функцию ngx_event_get_peer_pt. Непонятно, куда конкретно он указывает. Затем посмотрите ngx_http_upstream.c.
Я видел это в ngx_http_upstream_init_main_conf, следующий код:
uscfp = umcf->upstreams.elts;
for (i = 0; i < umcf->upstreams.nelts; i++) {
init = uscfp[i]->peer.init_upstream ? uscfp[i]->peer.init_upstream:
ngx_http_upstream_init_round_robin;
if (init(cf, uscfp[i]) != NGX_OK) {
return NGX_CONF_ERROR;
}
}
Как видите здесь, конфигурация по умолчанию — опросная (фактически каждый модуль балансировки нагрузки формирует связанный список, и каждый раз, когда он обрабатывается с начала связанного списка, это видно из файла конфигурации выше, что nginx не начнет опрос до опроса) Вызовите другие модули) и инициализируйте каждый восходящий поток с помощью ngx_http_upstream_init_round_robin.
Посмотрите еще раз на функцию ngx_http_upstream_init_round_robin, которая содержит следующие строки:
r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer;
Здесь указатель get указывает на ngx_http_upstream_get_round_robin_peer
В ngx_http_upstream_get_round_robin_peer вы можете увидеть:
if (peers->single) {
peer = &peers->peer[0];
if (peer->down) {
goto failed;
}
} else {
/* there are several peers */
peer = ngx_http_upstream_get_peer(rrp);
if (peer == NULL) {
goto failed;
}
Посмотрите на неудавшуюся часть еще раз:
failed:
if (peers->next) {
/* ngx_unlock_mutex(peers->mutex); */
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "backup servers");
rrp->peers = peers->next;
n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1))
/ (8 * sizeof(uintptr_t));
for (i = 0; i < n; i++) {
rrp->tried[i] = 0;
}
rc = ngx_http_upstream_get_round_robin_peer(pc, rrp);
if (rc != NGX_BUSY) {
return rc;
}
/* ngx_lock_mutex(peers->mutex); */
}
/* all peers failed, mark them as live for quick recovery */
for (i = 0; i < peers->number; i++) {
peers->peer[i].fails = 0;
}
/* ngx_unlock_mutex(peers->mutex); */
pc->name = peers->name;
return NGX_BUSY;
Истина здесь ясна: если соединение не удалось, попробуйте подключиться к следующему. Если все не удалось, будет выполнено быстрое восстановление, чтобы сбросить количество неудач каждого узла до 0, а затем вернуть NGX_BUSY, а затем nginx это сделает. напечатайте сообщение об отсутствии восходящего потока и, наконец, вернитесь в исходное состояние, а затем перешлите его.
Это объясняет, почему до сих пор нет нормального доступа к восходящим потокам.
Перечитайте файл конфигурации. Если один из них выйдет из строя, nginx подумает, что он мертв, а затем отправит весь будущий трафик на другой. Когда другой тоже выйдет из строя, он подумает, что оба умерли, а затем быстрое восстановление. , а затем распечатайте журнал.
Сцена: Просматривая журнал nginx, мы обнаружили, что тело ответа на запрос составляет около 1500 КБ, а request_time составляет около 6 с, что приводит к истечению времени ожидания запроса и невозможности получения нормальных данных.
причина: Проблемы с клиентской сетью:
Когда передача TCP разделена на пакеты, каждый пакет TCP имеет размер около 1400 байт, а тело ответа на предыдущий запрос составляет около 1500 КБ, которое необходимо разделить на более чем 100 пакетов TCP. TCP имеет медленный процесс запуска. Сначала он каждый раз отправляет 10 пакетов, а затем регулирует количество отправляемых пакетов каждый раз в зависимости от условий сети. Если сеть не в порядке, он будет отправлен 10 раз. Поскольку TCP является надежной передачей, необходимо гарантировать, что каждый пакет получен другой стороной (реализуется путем сериализации каждого пакета и получения подтверждения, отправленного другой стороной, если подтверждение, отправленное другой стороной, не получено в течение этого времени). в согласованное время пакет будет передан повторно. Кроме того, в TCP существует концепция окна отправки. Если предположить, что окно отправки равно 10, то за один раз можно отправить 10 пакетов. После этого каждый раз при получении подтверждения позиция окна отправки, соответствующая этому пакету, может быть освобождена. и можно отправить следующий пакет. Поэтому, если клиентская сеть не в порядке, это повлияет на время, необходимое для отправки тела ответа, а затем повлияет на request_time в журнале nginx.
Тело ответа на запрос слишком велико:
Поскольку в данных, выводимых интерфейсом запроса, содержатся слишком большие бесполезные данные, тело ответа на запрос слишком велико, что приводит к тому, что отправка подпакета влияет на request_time.
Настройте параметры, связанные с nginx.conf, следующим образом.
client_header_buffer_size 16k; large_client_header_buffers 4 64k;
Отрегулируйте в соответствии с конкретной ситуацией, обычно просто корректируйте значение соответствующим образом.
Эта ошибка обычно возникает при загрузке файлов: сервер отказывается обрабатывать текущий запрос, поскольку размер данных объекта, отправленных по запросу, превышает диапазон, который сервер желает или может обработать. В этом случае сервер может закрыть соединение, чтобы клиент не мог продолжать отправлять этот запрос.
Добавьте раздел http{} в файл конфигурации Nginx.conf.
Client_max_body_size 10m; //Установите размер и настройте его в соответствии со своими потребностями.
Если вы используете php, размер client_max_body_size должен соответствовать или немного превышать максимальное значение следующих значений в php.ini, чтобы не возникало ошибок из-за несоответствия размера отправляемых данных.
post_max_size = 10M upload_max_filesize = 2M
Причина этой проблемы неизвестна,
В качестве решения добавьте следующую конфигурацию:
proxy_http_version 1.1;
Значение по умолчанию элемента конфигурации proxy_http_version равно 1.0, поэтому предполагается, что оно связано с функцией поддержки активности в версии 1.1.
log_format main ‘remote_addr remote_user [time_local] “request” http_host ‘ ‘status upstream_status body_bytes_sent “http_referer” ‘ ‘”http_user_agent” ssl_protocol ssl_cipher upstream_addr ‘ ‘request_time
имя переменной | Описание переменной | Приведите пример |
---|---|---|
$remote_addr | адрес клиента | 113.140.15.90 |
$remote_user | Имя пользователя клиента | - |
$time_local | Время доступа и часовой пояс | 18/Jul/2012:17:00:01 +0800 |
$request | Запрошенный URI и протокол HTTP | “GET /pa/img/home/logo-alipay-t.png HTTP/1.1″ |
$http_host | Адрес запроса, который представляет собой адрес (IP или доменное имя), который вы вводите в браузере. | img.alipay.com 10.253.70.103 |
$status | Статус HTTP-запроса | 200 |
$upstream_status | статус восходящего потока | 200 |
$body_bytes_sent | Размер содержимого файла, отправляемого клиенту | 547 |
$http_referer | Источник перехода | “https://cashier.alipay.com…/” |
$http_user_agent | агент пользовательского терминала | “Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SV1; GTB7.0; .NET4.0C; |
$ssl_protocol | Версия протокола SSL | TLSv1 |
$ssl_cipher | Алгоритмы обмена данными | RC4-SHA |
$upstream_addr | Адрес фонового восходящего потока, то есть адрес хоста, который фактически предоставляет услуги. | 10.228.35.247:80 |
$request_time | Общее время всего запроса | 0.205 |
$upstream_response_time | В процессе запроса время ответа восходящего потока | 0.002 |
Пример: 116.9.137.90 – [02/Aug/2012:14:47:12 +0800] “GET /images/XX/20100324752729.png HTTP/1.1″img.alipay.com 200 200 2038 https://cashier.alipay.com/XX/PaymentResult.htm?payNo=XX&outBizNo=2012XX “Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0; 360SE)” TLSv1 AES128-SHA 10.228.21.237:80 0.198 0.001
сообщение об ошибке | Описание ошибки |
---|---|
«преждевременно закрытое соединение выше по течению» | Исключение, возникающее при запросе URI, вызвано отключением пользователя, когда восходящий сервер не вернул пользователю ответ. Это не влияет на систему и его можно игнорировать. |
“recv() failed (104: Connection reset by peer)” | (1) Количество одновременных подключений сервера превышает его пропускную способность, и сервер прерывает некоторые соединения (2) Клиент закрывает браузер, но сервер все еще отправляет данные клиенту; (3) браузер нажимает Стоп |
“(111: Connection refused) while connecting to upstream” | Когда пользователи подключаются, если серверная часть восходящего потока зависает или блокируется, они получают эту ошибку. |
“(111: Connection refused) while reading response header from upstream” | Когда пользователи читают данные после успешного соединения, если серверная часть восходящего потока зависает или блокируется, они получают эту ошибку. |
“(111: Connection refused) while sending request to upstream” | Когда Nginx и восходящий поток успешно соединяются и отправляют данные, если серверная часть восходящего потока зависает или блокируется, вы получите эту ошибку. |
“(110: Connection timed out) while connecting to upstream” | Время ожидания nginx при подключении к восходящему серверу позади него |
“(110: Connection timed out) while reading upstream” | Тайм-аут nginx при чтении ответа от восходящего потока |
“(110: Connection timed out) while reading response header from upstream” | Тайм-аут nginx при чтении заголовков ответов из восходящего потока |
“(110: Connection timed out) while reading upstream” | Тайм-аут nginx при чтении ответа от восходящего потока |
“(104: Connection reset by peer) while connecting to upstream” | восходящий поток отправил RST, сбрасывая соединение |
“upstream sent invalid header while reading response header from upstream” | Заголовок ответа, отправленный восходящим потоком, недействителен. |
“upstream sent no valid HTTP/1.0 header while reading response header from upstream” | Заголовок ответа, отправленный восходящим потоком, недействителен. |
“client intended to send too large body” | Используется для установки максимального значения содержимого запроса клиента, которое разрешено принять. Значение по умолчанию — 1M. Тело, отправленное клиентом, превышает установленное значение. |
“reopening logs” | Пользователь отправляет команду kill -USR1 |
“gracefully shutting down”, | Пользователь отправляет команду kill -WINCH |
“no servers are inside upstream” | Сервер не настроен в восходящем направлении |
“no live upstreams while connecting to upstream” | Все вышестоящие серверы не работают. |
“SSL_do_handshake() failed” | SSL-квитирование не удалось |
“SSL_write() failed (SSL:) while sending to client” | |
“(13: Permission denied) while reading upstream” | |
“(98: Address already in use) while connecting to upstream” | |
“(99: Cannot assign requested address) while connecting to upstream” | |
“ngx_slab_alloc() failed: no memory in SSL session shared cache” | Вызвано такими причинами, как недостаточный размер ssl_session_cache. |
“could not add new SSL session to the session cache while SSL handshaking” | Вызвано такими причинами, как недостаточный размер ssl_session_cache. |
“send() failed (111: Connection refused)” |