Примечания к исходному коду Nginx — предварительное условие
В этой статье обобщаются отрывочные сведения об части исходного кода Nginx, обрабатывающей протокол HTTP, для дальнейшего использования.
Путь долгий и есть много экспертов.Мы должны проявлять настойчивость и иметь отношение к постоянному обучению.
Содержание этой статьи
- инструменты отладки
- просто несколько слов
- этап запроса
- заказ модуля
- поле данных
-
вызов функции
- ngx_http_close_connection
- ngx_http_finalize_connection
- ngx_http_termniate_request
- ngx_http_free_request
- ngx_http_close_request
- ngx_http_finalize_request
- ngx_event_t::handler
- ngx_request_t::read_event_handlerа такжеwrite_event_handler
- ngx_http_read_client_request_body
- ngx_http_send_headerа такжеngx_http_output_filter
- ngx_handle_read_eventа такжеngx_handle_write_event
- переменная запроса
инструменты отладки
-
Тестовый пример — Test::Nginx (perl)
-
Проверка на утечку памяти - valgrind (worker_processes 1; daemon off; master_process off;), no-pool-patch
valgrind --log-file=valgrid.log --leak-check=full --leak-resolution=high \ --track-origins=yes --show-reachable=yes root@laptop:/usr/local/src/nginx-1.4.3# patch -p1 <../no-pool-nginx/nginx-1.4.3-no_pool.patch
-
файл стресса valgrind — Автоматизируйте тестирование valgrind.
-
Одношаговая отладка — gdb, cgdb
-
стек вызовов - pstack, strace, lstrace, systemtap, -finstrument-functions, valgrind --tool=callgrind
-
Стресс-тест - ab, httperf, wrk
-
Измерение реального трафика — tcpcopy, goreplay, ngx-http-mirror-module
просто несколько слов
-
Функция обратного вызова синтаксического анализа инструкций, которая может возвращать строку, описывающую сообщение об ошибке ("дублируется"). Это сообщение об ошибке будет объединено Nginx в полное сообщение и распечатано в терминале:
nginx: [emerg] "spent_prefix" directive is duplicate in /usr/local/nginx/conf/nginx.conf:101
-
Функция создания структуры конфигурации, возвратNULLИли фактическая структура. вернутьNULL, Nginx не будет печатать никаких сообщений об ошибках. Итак, лучше всего использоватьngx_conf_log_errorФункция печатает сообщение об ошибке вручную.
-
Преобразователи типов, предоставляемые Nginx%VСоответствующий типngx_str_t *, вместоngx_str_t.
-
ngx_cpystrn(u_char *dst, u_char *src, size_t n)третий параметр функцииnинструктироватьdstМаксимальная длина соответствующего блока памяти (включая завершающий нулевой байт, см. функциюsnprintfопределение функции).
-
ngx_str_tТип имеет только два члена, из которыхngx_str_t::dataУказатель указывает на начальный адрес строки,ngx_str_t::lenУказывает эффективную длину строки.ngx_str_t::dataможет не указывать на обычную строку и не может начинаться с\0конец, так что используйтеngx_str_tдолжно быть основано на длинеngx_str_t::lenЗначение определяет длину строки.
-
- ngx_buf_tа такжеngx_chain_t
-
- ngx_buf_tОбъекты, которые могут быть представлены: блоки памяти, файлы на диске и специальные флаги;
- ngx_buf_tобычно иngx_chain_tПарное использование:ngx_chain_tБудуngx_buf_tУпаковывается в односвязный узел списка, а затем Nginx используетngx_chain_tСформировать односвязный список для представления логически непрерывных данных;
-
Различайте функции следующих четырех функций обратного вызова, которые являются ключом к пониманию потока обработки запроса:
c->read->handler = ngx_http_request_handler; c->write->handler = ngx_http_request_handler; r->read_event_handler = ngx_http_block_reading; r->write_event_handler = ngx_http_block_reading;
этап запроса
Nginx делит процесс обработки HTTP-запроса на несколько этапов (PHASE), каждому этапу соответствуетphase checkerВызовите функции обратного вызова, предоставляемые каждым модулем, одну за другой в порядке регистрации, то естьphase handler. для всех запросовphase checkerа такжеphase handlerПорядок выполнения — когда процесс Nginx запускается, вngx_http_init_phase_handlersопределяется в функции.
Этапы, определенные Nginx, перечислены ниже, аphase checkerможно справитьсяphase handlerвозвращаемое значение.
POST_READ
на данном этапеphase checkerфункцияngx_http_core_generic_phase. Каждый модуль регистрируется на этом этапеphase handlerПоток обработки запроса можно контролировать с помощью следующих возвращаемых значений:
код ошибки | Как обращаться |
---|---|
NGX_OK | Переместить запрос на следующий этап обработки (пропустить обработчик фазы, который не был вызван на этом этапе) |
NGX_DECLINED | Вызвать обработчик следующей фазы для запроса (может быть, этой фазы или следующей фазы) |
NGX_AGAIN/NGX_DONE | Текущий обработчик фазы должен быть вызван снова для запроса |
разное | код ошибкиNGX_ERRORилиNGX_HTTP_*При ожидании завершить текущий запрос досрочно |
Зарегистрирован на данном этапе в собственном модуле Nginxphase handlerМодули:
- ngx_http_realip_module - Change the client address to the one sent in the specificed header field.
SERVER_REWRITE
на данном этапеphase checkerФункцияngx_http_core_rewrite_phase. Каждый модуль регистрируется на этом этапеphase handlerПоток обработки запроса можно контролировать с помощью следующих возвращаемых значений:
код ошибки | Как обращаться |
---|---|
NGX_DECLINED | Вызвать обработчик следующей фазы для запроса (может быть, этой фазы или следующей фазы) |
NGX_DONE | Текущий обработчик фазы должен быть вызван снова для запроса |
разное | код ошибкиNGX_OK, NGX_AGAIN, NGX_ERRORилиNGX_HTTP_xxждать, завершить текущий запрос досрочно |
Зарегистрирован на данном этапе в собственном модуле Nginxphase handlerМодули:
- ngx_http_rewrite_module- реализация определена вserver {}изrewrite, set, ifи другие инструкции.
FIND_CONFIG
на данном этапеphase checkerФункцияngx_http_core_find_config_phase. Этот этап относится к внутреннему процессу Nginx и не позволяет регистрировать модули.phase handler.
ngx_http_core_find_config_phaseфункция по запросуuriсоответствовать соответствующемуlocation {}блок конфигурации.
REWRITE
на данном этапеphase checkerФункцияngx_http_core_rewrite_phase. Каждый модуль регистрируется на этом этапеphase handlerВозвращаемые значения, которые можно использовать, и то, как Nginx обрабатывает эти возвращаемые значения иSERVER_REWRITEФазы одинаковые.
Зарегистрирован на данном этапе в собственном модуле Nginxphase handlerМодули:
- ngx_http_rewrite_module- реализация определена вlocation {}изrewrite, set, ifи другие инструкции.
POST_REWRITE
на данном этапеphase checkerФункцияngx_http_core_post_rewrite_phase. Этот этап относится к внутреннему процессу Nginx и не позволяет регистрировать модули.phase handler.
Проверить на этом этапеREWRITEРезультат выполнения этапа и выполнение разной логики: если запросuriЕсли изменено предыдущим этапом (r->uri_changed = 1), этот запрос направляетсяFIND_CONFIGэтап, переделатьlocation {}Найдите и сопоставьте; если требуетсяuriЕсли не было изменено на предыдущем этапе, продолжайте вызывать запросPREACCESSсценаphase handler.
PREACCESS
на данном этапеphase checkerФункцияngx_http_core_generic_phase. Каждый модуль регистрируется на этом этапеphase handlerВозвращаемые значения, которые можно использовать, и то, как Nginx обрабатывает эти возвращаемые значения иPOST_READФазы одинаковые.
Зарегистрирован на данном этапе в собственном модуле Nginxphase handlerМодули:
- ngx_http_limit_conn_module - limits the number of connections per the defined key, in particular, the number of of connections from a single IP address.
- ngx_http_limit_req_module - limits the request processing rate per the defined key, in particular, the processing rate of requests coming from a single IP address.
- ngx_http_degradation_module - returns 204 or 444 code for some locations on low memory condition.
- ngx_http_realip_module - Change the client address to the one sent in the specificed header field.
ACCESS
на данном этапеphase checkerФункцияngx_http_core_access_phase. Каждый модуль регистрируется на этом этапеphase handlerПоток обработки запроса можно контролировать с помощью следующих возвращаемых значений:
код ошибки | Как обращаться |
---|---|
r != r->main | Текущий запрос является подзапросом и напрямую передается на следующий этап обработки. |
NGX_DECLINED | Вызвать обработчик следующей фазы для запроса (может быть, этой фазы или следующей фазы) |
NGX_AGAIN/NGX_DONE | Текущий обработчик фазы должен быть вызван снова для запроса |
NGX_OK |
|
NGX_HTTP_FORBIDDEN |
|
NGX_HTTP_UNAUTHORIZED | логика обработки иNGX_HTTP_FORBIDDENтакой же |
разное | код ошибкиNGX_ERRORилиNGX_HTTP_*При ожидании завершить текущий запрос досрочно |
Зарегистрирован на данном этапе в собственном модуле Nginxphase handlerМодули:
- ngx_http_auth_basic_module - limits access to resources by validating the user name and password using the "HTTP Basic Authentication" protocol.
- ngx_http_access_module - limits access to certain client addresses.
POST_ACCESS
на данном этапеphase checkerФункцияngx_http_core_post_access_phase. Этот этап относится к внутреннему процессу Nginx и не позволяет регистрировать модули.phase handler.
Проверить на этом этапеACCESSобработать результат этапа и выполнить другую логику: еслиr->access_code == NGX_HTTP_FORBIDDENзатем завершите обработку запроса досрочно (используяNGX_HTTP_FORBIDDENкак код ответа HTTP); еслиr->access_codeдля других не0значение, завершить обработку запроса досрочно; еслиr->access_code == 0значение, вызовите следующий запросphase handler.
TRY_FILES (PRECONTENT)
ПРИМЕЧАНИЯ. Начиная с Nginx 1.13.4, этот этап был переименованPRECONTENTи использоватьngx_http_core_generic_phaseтак какphase checker.try_filesФункция инструкции контролируется модулемngx_http_try_files_moduleпоставка.
commit 129b06dc5dfab7b4513a4f274b3778cd9b8a6a22
Author: Roman Arutyunyan <arut@nginx.com>
Date: Thu Jul 20 15:51:11 2017 +0300
Precontent phase.
The phase is added instead of the try_files phase. Unlike the old phase, the
new one supports registering multiple handlers. The try_files implementation is
moved to a separate ngx_http_try_files_module, which now registers a precontent
phase handler.
В версиях до Nginx 1.13.4phase checkerФункцияngx_http_core_try_files_phase. Этот этап относится к внутреннему процессу Nginx и не позволяет регистрировать модули.phase handler.
Если предлагается использоватьlocation {}блок не настроенtry_filesуказание переадресовать запрос следующемуphase handler.
Если предлагается использоватьlocation {}используется вtry_filesкоманду, то продолжить проверку параметров команды: если файл статического диска, соответствующий параметру (кроме последнего параметра), существует, вернуть клиенту содержимое статического файла; если файл статического диска, соответствующий параметру, существует не существует, используйте функциюngx_http_internal_redirectперенаправить запрос наtry_filesуказывается последним параметром командыlocationПосле этого повторно обработайте запрос.
CONTENT
на данном этапеphase checkerФункцияngx_http_core_content_phase. Каждый модуль регистрируется на этом этапеphase handlerПоток обработки запроса можно контролировать с помощью следующих возвращаемых значений:
код ошибки | Как обращаться |
---|---|
r->content_handler | еслиlocation {}Настроено сcontent handler, использовать его для обработки запросов и игнорировать другиеphase handler |
NGX_DECLINED | Вызов обработчика следующей фазы для запроса. Если все обработчики фазы были вызваны, завершите обработку запроса (используя код ответа:NGX_HTTP_FORBIDDEN(URI запроса заканчивается на '/') илиNGX_HTTP_NOT_FOUND(URI запроса не заканчивается на '/')) |
разное | Завершите поток обработки запроса (код ошибки какngx_http_finalize_requestпараметры функции) |
Как видно из вышеприведенного анализа, данные ответа на запрос можно определить поcontent handlerфункция илиphase handlerпредусмотрена функция.content handlerсоотношение приоритетовphase handlerвысокий и эксклюзивный.phase handlerможно рассматривать какCONTENTStage обеспечивает общую логику обработки запросов, аcontent handlerэтоlocation {}Блоки обеспечивают специальную логику обработки запросов.
Зарегистрирован на данном этапе в собственном модуле Nginxphase handlerМодули:
- ngx_http_random_index_module - processes requests ending with the slash character ('/') and picks a random file in a directory to serve as an index file.
- ngx_http_index_module - processes requests ending with the slash character ('/').
- ngx_http_autoindex_module - processes requests ending with the slash character ('/') and produces a directory listings.
- ngx_http_dav_module - intended for file management automation via the WebDAV protocol. The module processes HTTP and WebDAV methods PUT, DELETE, MKCOL, COPY, and MOVE.
- ngx_http_gzip_static_module - allows sending precompressed files with the ".gz" filename extension instead of regular files.
- ngx_http_static_module- Статический модуль ответа файла
Собственный модуль Nginx предоставляетcontent handlerиз них:
- ngx_http_fastcgi_module
- ngx_http_scgi_module
- ngx_http_memcached_module
- ngx_http_proxy_module
- ngx_http_stub_status_module
- ngx_http_flv_module
- ngx_http_mp4_module
- ngx_http_empty_gif_module
- ngx_http_perl_module
- ngx_http_uwsgi_module
LOG
Эта стадия особенная, она не соответствуетphase checker, на данном этапеphase handlerПо окончании обработки запроса,ngx_http_log_requestфункция вызывается напрямую.
Зарегистрирован на данном этапе в собственном модуле Nginxphase handlerМодули:
- ngx_http_log_module
заказ модуля
В стандартной конфигурации,filterПорядок вызова модулей (обратный порядку инициализации модулей) следующий:
последовательность вызовов | имя модуля | предоставленный фильтр |
---|---|---|
1 | ngx_http_not_modified_filter_module | header |
2 | ngx_http_range_body_filter_module | body |
3 | ngx_http_copy_filter_module | body |
4 | ngx_http_headers_filter_module | header |
third party filter goes here | ||
6 | ngx_http_userid_filter_module | header |
7 | ngx_http_ssi_filter_module | header and body |
8 | ngx_http_charset_filter_module | header and body |
9 | ngx_http_postpone_filter_module | body |
10 | ngx_http_gzip_filter_module | header and body |
11 | ngx_http_range_header_filter_module | header |
12 | ngx_http_chunked_filter_module | header and body |
13 | ngx_http_header_filter_module | header |
14 | ngx_http_write_filter_module | body |
поле данных
ngx_connection_t::data
Это поле имеет множество применений, оно должно бытьngx_connection_tСостояние изменяется для представления различных значений:
- Когда соединение повторно используется в пуле незанятых соединений Nginx (односвязный список), это поле указателя действует как указатель для узлов односвязного списка.nextуказатель:
- После того, как клиент и Nginx установят TCP-соединение, прежде чем Nginx начнет считывать и обрабатывать данные HTTP-запроса в TCP-соединении, поле указателя указывает наngx_http_connection_tпеременная типа. В этой переменной хранится информация, относящаяся к «HTTP-соединению», например виртуальный хост, соответствующий HTTP-запросу, структура конфигурации виртуального хоста и имя хоста SSL.
- При последующей обработке HTTP-запроса (прием данных запроса, формирование данных ответа и т. д.) это поле всегда указывает на текущий активный запрос по TCP-соединению (из-за технологии HTTP Pipeline, механизма подзапросов Nginx и т. д., текущее TCP-соединение может соответствовать нескольким экземплярам запроса). Данные ответа на этот запрос могут быть немедленно отправлены клиенту.
ngx_connection_t::buffered
TODO: More explanation needed.
ngx_http_request_t::postponed
когда значение поля указателя неNULLпри указании на тип узла, которыйngx_http_postponed_request_tодносвязный список. Узлы этого односвязного списка содержат подзапросы, созданные запросом (ngx_http_postponed_request_t::request), или данные ответа, сгенерированные запросом, который временно не может быть отправлен (ngx_http_postponed_request_t::out).
Когда значение поля указателяNULL, у запроса нет отложенных подзапросов.
ngx_http_request_t::posted_requests
Это поле указывает на тип узла,ngx_http_posted_request_tодносвязный список. Этот односвязный список содержит «готовые» запросы по запросу (основной запрос), и эти запросы могут быть запланированы и обработаны Nginx в любое время.
Nginx поддерживает список «готовых» запросов только для «основного запроса», а «готовые» запросы могут быть основными запросами, подзапросами, подзапросами и так далее. функцияngx_http_post_requestИспользуется для добавления «готового» запроса в список, функцияngx_http_run_posted_requestsИспользуется для планирования «готовых» запросов.
ngx_http_request_t::valid_location
TODO: More explanation needed.
когдаrewriteИспользование инструкцииbreakотредактированоr->uriПосле запроса эта переменная флага устанавливается в 0; если запросngx_http_internal_redirectЕсли функция перенаправляется внутрь Nginx, этот флаг сбрасывается в 1.
ngx_http_request_t::uri_changed
TODO: More explanation needed.
когдаrewriteВ инструкции используется не-breakотредактированоr->uriПосле этого эта переменная флага устанавливается в 1;
ngx_http_request_t::count
Запросить подсчет ссылок. Что касается его роли, он был представлен в разделе 11.8 «Углубленное понимание Nginx: разработка модулей и анализ архитектуры», 1-е издание:
> 在 HTTP 模块中每进行一类新的(异步)操作,包括为一个请求添加新的事件,或者把一些已经
> 由定时器、epoll 中移除事件重新加放其中,都需要把这个请求的引用计数加 1.这是因为需要让
> HTTP 框架知道,HTTP 模块对于该请求有独立的异步处理机制,将由该 HTTP 模块决定这个操作
> 什么时候结束,防止在这个操作还未结束时 HTTP 框架却把这个请求销毁了(如其它 HTTP 模块通
> 过调用 ngx_http_finalize_request 方法要求 HTTP 框架结束请求),异致请求出现不可知的
> 严重错误。这就要求每个操作在 “认为” 自身的动作结束时,都得最终调用
> ngx_http_close_request 方法,该方法会自动检查引用计数,当引用计数为 0 时才真正地销销
> 毁请求。
Резюме: чтобы добавить ветвь асинхронного выполнения к текущему процессу выполнения запроса, необходимо увеличить счетчик ссылок для основного запроса. Например, когда тело пакета запроса необходимо прочитать через «читаемое событие», когда создается подзапрос;
ngx_http_requeste_t::out
использоватьngx_chain_tнатянутыйngx_buf_tСвязанный список, используемый для сохранения отправляемых данных ответа.
Кроме того, модуль Nginx вызывает функциюngx_http_output_filterОтправьте данные ответа через цепочку выходных фильтров. Если данные ответа были обработаны выходным фильтром, но не полностью отправлены по сетевым причинам, они могут быть переданы после того, как произойдет «событие, доступное для записи» соединения.ngx_http_output_filter(r, NULL)Форма вызова продолжает отправлять.
ngx_event_t::active
Управляет ли модуль событий, используемый Nginx, структурой событий.
ngx_event_t::ready
Готова ли структура события (с необработанными событиями).
вызов функции
ngx_http_close_connection
Эта функция используется для закрытия соединения.
- подпись функции:
-
void ngx_http_close_connection(ngx_connect_t *c);
- Основная функция:
-
функцияngx_close_connectionПосле очистки всех событий (сетевых событий, событий тайм-аута), зарегистрированных соединением из модуля событий, закройте базовый дескриптор сокета. При этом звонитеngx_free_connectionФункция сохраняет связанную структуру в односвязном списке.ngx_cycle->free_connectionsдля следующего использования.
Эта функция очищает связанную с SSL структуру, соответствующую соединению, закрывает пул памяти, соответствующий соединению, а затем вызываетngx_close_connectionФункция выполняет другую работу по очистке.
ngx_http_finalize_connection
Эта функция вызывается после завершения обычной обработки запроса.ngx_http_close_requestЗакройте запрос (количество ссылок запроса минус один) и определите, следует ли закрыть соединение или оставить его (поддерживать активное соединение).
- подпись функции:
-
static void ngx_http_finalize_connection(ngx_http_request_t *r);
ngx_http_termniate_request
Принудительная очистка и уничтожение запроса.
- подпись функции:
-
static void ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc);
- Основная функция:
- Эта функция вызывает обработчик очистки, зарегистрированный в запросе, и устанавливает счетчик ссылок равным 1, а затем используетnxx_http_close_requestФункция уничтожает запрос.
ngx_http_free_request
Эта функция очищает и уничтожает запрос.
- подпись функции:
-
void ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc);
- Основная функция:
- Эта функция вызывается как обработчик очистки, зарегистрированный в запросе, и вызывается для запроса.LOGсценаphase handler, а затем уничтожьте пул памяти запроса.
ngx_http_close_request
Эта функция закрывает ссылку на запрос.
- подпись функции:
-
static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc);
- Основная функция:
- Функция будет запрашиватьrосновной запрос (r->main) количество ссылок (r->main->count) минус 1. Если счетчик ссылок основного запроса равен 0, вызовитеngx_http_free_requestФункция очищает и уничтожает основной запрос, вызываяngx_http_close_connectionФункция очищает и уничтожает соединение, используемое запросом.
ngx_http_finalize_request
Эта функция определяет следующий поток обработки запроса в соответствии с результатом обработки запроса.
- подпись функции:
-
void ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc);
- Основная функция:
- Функция этой функции более сложная, и есть много логических ответвлений. Далее устанавливаем параметры согласноrcЗначение и текущий статус запроса обобщают основной поток ветвей и метод обработки этой функции (используя номер версии исходного кода: 1.13.6):
заказ | условие перехода | Как обращаться |
---|---|---|
запуск функции | ||
1 | rc == NGX_DONE | Текущее действие запроса было обработано, но над запросом выполняются другие асинхронные действия. передачаngx_http_finalize_connectionФункция уменьшает счетчик ссылок запроса на единицу.RETURN |
2 | rc == DECLINED | Обработчик содержимого не может обработать запрос, поэтому он будет обработан обработчиком фазы в фазе СОДЕРЖИМОЕ.RETURN |
3 | значение rcNGX_ERROR,NGX_HTTP_REQUEST_TIMEOUT,NGX_HTTP_CLIENT_CLOSE_REQUESTодин из кодов ошибок илиc->error == 1 | Произошла ошибка в соединении, по которому был сделан запрос, вызываяngx_http_terminate_requestПринудительная очистка Уничтожает запрос.RETURN |
4 | rc >= NGX_HTTP_SPECIAL_RESPONSEили значение rc равноNGX_HTTP_CREATED,NGX_HTTP_NO_CONTENTодин из | Если значение rc равноNGX_HTTP_CLOSE(больше, чемNGX_HTTP_SPECIAL_RESPONSE), срочно звонитеngx_http_terminate_requestУничтожить запрос; в противном случае вызвать функциюngx_http_special_response_handlerВосстановите данные ответа для этого запроса. Затем вам нужно снова вызвать функциюngx_http_finalize_requestиметь дело сngx_http_special_response_handlerВозвращаемое значение.RETURN |
Ответ на запрос отправлен, данные ответа на запрос не отправлены, запрос является подзапросом и т. д. Нормальный бизнес-процесс продолжает разветвляться. | ||
5 | r != r->main |
Когда текущий запрос является «подзапросом», функция продолжает следующий поток обработки:
|
6 | r == r->main |
Текущий запрос является «основным запросом», и функция продолжает следующий поток обработки:
|
функция заканчивается |
ngx_event_t::handler
Функция обратного вызова события, вызываемая непосредственно циклом событий.
- подпись функции:
-
typedef void (*ngx_event_handler_pt)(ngx_event_t *ev);
Для HTTP-модуля Nginx после того, как Nginx обращается к клиентскому соединению, соединение выделяетсяngx_connection_tструктура. Структура содержит два соответствующих «события для чтения» и «события для записи».ngx_event_tчлен типаreadа такжеwrite, функции обратного вызова этих двух элементов будут вызываться при возникновении события. Ниже мы кратко перечисляем изменения значений этих двух функций обратного вызова по мере изменения статуса запроса:
-
Функция вызова Nginxngx_event_acceptполучать доступ к соединениям и назначать ихngx_connection_tструктура:
void ngx_event_accept(ngx_event_t *ev) { ... c = ngx_get_connection(s, ev->log); ... ls->handler(c); ... }
-
Впоследствии Nginx вызывает функциюngx_http_init_connectionУстановите функцию обратного вызова «чтение события», чтобы подготовиться к получению данных запроса:
void ngx_http_init_connection(ngx_connection_t *c) { ... rev = c->read; rev->handler = ngx_http_wait_request_handler; c->write->handler = ngx_http_empty_handler; ... if (rev->ready) { ... rev->handler(rev); return; } ... if (ngx_handle_read_event(rev, 0) != NGX_OK) { ... } }
-
функцияngx_http_wait_request_handlerПрочитайте некоторые данные из соединения, затем создайте структуру запроса.ngx_request_t. Затем настройте функцию обратного вызова «читаемое событие» наngx_http_process_request_line, который используется для получения и анализа строки состояния запроса. В течение этого периода, если полученных данных недостаточно для создания полной строки состояния, Nginx зарегистрирует «читаемое событие» для соединения и продолжит выполнение при поступлении новых данных.
void ngx_http_wait_request_handler(ngx_event_t *rev) { ... c->data = ngx_http_create_request(c); rev->handler = ngx_http_process_request_line; ngx_http_process_request_line(rev); } void ngx_http_process_request_line(ngx_event_t *rev) { ... for (;;) { if (rc == NGX_AGAIN) { n = ngx_http_read_request_header(r); if (n == NGX_AGAIN || n == NGX_ERROR) { return; } ... } ... rev->handler = ngx_http_process_request_headers; ngx_http_process_request_headers(rev); } }
-
После обработки строки состояния запроса Nginx настраивает функцию «прочитать событие».ngx_http_process_request_headers, для получения и разбора заголовков запросов. В течение этого периода, если полученных данных недостаточно для формирования полного заголовка, Nginx зарегистрирует «читаемое событие» для соединения и продолжит выполнение вниз при поступлении новых данных.
void ngx_http_process_request_headers(ngx_event_t *ev) { ... n = ngx_http_read_request_header(r); if (n == NGX_AGAIN || n == NGX_ERROR) { return; } ... if (rc == NGX_HTTP_PARSE_HEADER_DONE) { ... ngx_http_process_request(r); return; } ... }
-
После того, как данные заголовка запроса получены и проанализированы, вызывается функцияngx_http_process_requestЗапустите процесс обработки запросов и формирования ответных данных. На этом этапе Nginx устанавливает действительную функцию обратного вызова «событие, доступное для записи» для соединения.
- Затем и «события, доступные для чтения», и «события, доступные для записи» обрабатываются функцией обратного вызова.ngx_http_request_handlerобработка, он вызовет структуру запроса на основе типа событияngx_request_tсерединаread_event_handlerа такжеwrite_event_handlerФункция, на которую указывает член.
- Поскольку Nginx уже получил требуемые данные запроса, при возникновении «читаемого события» он использует функциюngx_http_blocking_readingВременно заблокируйте это мероприятие.
- Перед этим шагом нет необходимости обрабатывать «событие, доступное для записи» в соединении, а после этого нам нужно использовать этот управляемый событием запрос для завершения потока обработки PHASE (ngx_http_core_run_phases).
- При этом каждый раз, когда происходит событие, Nginx также будет вызывать функциюngx_http_run_posted_requestsТриггер "готов" (posted, имеет значение "размещения" и "публикации", то есть этот тип запроса уже находится в состоянии готовности, ожидая запланированной обработки) Поток обработки запроса.
void ngx_http_process_request(ngx_event_t *ev) { ... c->read->handler = ngx_http_request_handler c->write->handler = ngx_http_request_handler; r->read_event_handler = ngx_http_block_reading; ngx_http_handler(r); ngx_http_run_posted_requests(c); } void ngx_http_handler(ngx_http_request_t *r) { ... r->write_event_handler = ngx_http_core_run_phases; ngx_http_core_run_phases(r); } void ngx_http_request_handler(ngx_event_t *ev) { ... if (ev->write) { r->write_event_handler(r); } else { r->read_event_handler(r); } ngx_http_run_posted_requests(c); }
-
С тех пор функции обратного вызова «событие для чтения» и «событие для записи» запроса практически не изменились. Поток обработки запросов на разных этапах определяетсяngx_request_t::read_event_handlerа такжеwrite_event_handlerЭти две функции решают.
ngx_request_t::read_event_handlerа такжеwrite_event_handler
После того, как данные запроса получены, обработка запроса переходит к этапам генерации ответа и отправки ответа. Эти две функции используются для управления потоком обработки запроса на разных этапах обработки.
write_event_handler:
ngx_http_core_run_phases
ngx_http_writer
ngx_http_request_finalizer
ngx_http_terminate_handler
read_event_handler:
ngx_http_block_reading
ngx_http_read_client_request_body_handler
ngx_http_discarded_request_body_handler
ngx_http_upstream_process_header
ngx_http_read_client_request_body
Прочтите тело запроса и сохраните его вngx_http_request_t::request_bodyсреди членов.
Эта функция увеличивает счетчик ссылок основного запроса по следующим причинам:
Функция вызова Nginxngx_http_read_client_request_bodyПри чтении тела пакета запроса может потребоваться отслеживать «читаемое событие» в соединении с помощью механизма обработки событий и использовать функцию обратного вызова чтения для продолжения чтения данных. Когда другие процессы запроса обрабатывают процесс «событие, доступное для записи», если запрос необходимо уничтожить из-за нормального процесса или исключения обработки, без защиты подсчета ссылок, запрос, используемый процессом «событие, доступное для чтения», будет недействительным. , и весь процесс будет недействителен.Процесс имеет серьезные последствия.
ngx_http_send_headerа такжеngx_http_output_filter
Используется для начала отправки заголовков и тел ответа.ngx_http_send_headerможно вызвать только один раз иngx_http_output_filterМожно вызывать несколько раз. но каждый разngx_http_output_filterРазличные части тела ответа должны быть отправлены, и данные ответа, которые не были отправлены в прошлый раз, будут временно сохранены вngx_http_request_tсередина. передачаngx_http_output_filter(r, NULL)Вы можете попробовать отправить данные ответа еще раз.
ngx_handle_read_eventа такжеngx_handle_write_event
Зарегистрируйте «события, доступные для чтения» и «события, доступные для записи» в цикле событий и убедитесь, что события не регистрируются повторно (еслиngx_event_tЕсли соответствующее событие отслеживается циклом обработки событий, функция возвращается напрямую).
переменная запроса
$request_body
Она содержит тело запроса, эта переменная может получить из нее данные тела тогда и только тогда, когда Nginx прочитал тело запроса и тело запроса не было записано во временный файл.