Я думаю, что все сталкивались с онлайн-проблемами или отладкой, в какой-то момент особенно хочется открыть лог Response Body Nginx, чтобы помочь себе быстро найти проблему, но после долгих поисков я обнаружил, что только request_body/upstream_addr /upstream_response_time похожи Переменные доступны; не паникуйте в это время... На самом деле, есть причина, по которой Nginx не включает ведение журнала тела ответа по умолчанию, потому что, когда тело ответа слишком велико, например, возвращая статическую страницу, это не только приведет к большому потреблению ресурсов, но и уменьшит читаемость всего файла журнала; но если мы укажем формат тела ответа или если мы хотим захватить содержание ключевого слова в Body, мы можем выполнить это требование, объединив модуль lua.
Компиляция и установка Nginx
Можно использовать комбинацию Nginx и Lua.OpenResty, вы также можете использовать Taobao с открытым исходным кодомTengine, Tengine полностью совместим с Nginx, для примера возьмем Nginx для компиляции модуля lua:
Моя системная среда: Ubuntu 14.04
# 先安装pcre库,Redhat系的机器对应的包可能为pcre-devel;也可以自己手动编译
aptitude -y install libpcre3-dev
# 下载并编译安装Lua解释器-LuaJIT
wget -c https://github.com/openresty/luajit2/archive/v2.1-20200102.tar.gz
tar -zxvf v2.1-20200102.tar.gz
cd ./luajit2-2.1-20200102
make && make install
# 告诉操作系统luajit的路径
export LUAJIT_LIB=/usr/local/lib
export LUAJIT_INC=/usr/local/include/luajit-2.1
# 写进配置文件,为luajit配置动态链接库
echo '/usr/local/lib/' >> /etc/ld.so.conf.d/luajit_so.conf
ldconfig
# 下载并解压Nginx编译所需的模块
# OpenResty Lua 模块
wget -c wget -c https://github.com/openresty/lua-nginx-module/archive/v0.10.14.tar.gz
tar -zxvf v0.10.14.tar.gz
# ngx_devel_kit 模块
wget -c https://github.com/vision5/ngx_devel_kit/archive/v0.3.1.tar.gz
tar -zxvf v0.3.1.tar.gz
# 下载Nginx源码并编译安装
wget -c https://nginx.org/download/nginx-1.17.8.tar.gz
tar -zxvf nginx-1.17.8.tar.gz
cd nginx-1.17.8
# 简单编译示例
./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --add-module=../ngx_devel_kit-0.3.1 --add-module=../lua-nginx-module-0.10.16rc5
make && make install
Просмотр информации о версии и модуле Nginx
можно использовать-V
Возможность просмотра скомпилированной версии Nginx и информации о модуле.
/usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.17.8
built by gcc 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
built with OpenSSL 1.0.1f 6 Jan 2014
TLS SNI support enabled
configure arguments: --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --add-module=../ngx_devel_kit-0.3.1 --add-module=../lua-nginx-module-0.10.14
Конфигурация Nginx и конфигурация lua
Ниже приведен простой пример конфигурации Nginx.Чтобы сделать структуру Nginx Conf более понятной, мы используемinclude
ключевое слово, чтобы разделить конфигурацию нескольких частей log/lua/server в один независимый файл конфигурации; давайте посмотрим пример каждой части конфигурации:
Пример контекстного HTTP
cd /usr/local/nginx/conf
cat nginx.conf
user www www;
worker_processes auto;
error_log /data/nginx/logs/error.log warn;
pid /data/nginx/nginx.pid;
events {
worker_connections 4096;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
charset utf-8;
# 日志格式配置文件
include common/log_formats.conf;
# 虚机主机配置
include vhost/iyue_test.conf;
}
Пример контекстного сервера
Здесь мы используем nginx для проксирования API-интерфейса GitHub в качестве теста; пользовательские переменныеresp_body
(по умолчанию пусто) используется для хранения значения тела ответа и его назначения через функциональный модуль lua.
cat vhost/iyue_test.conf
server {
listen 80;
server_name test.iyue.pub;
proxy_ignore_client_abort on;
fastcgi_ignore_client_abort on;
root /data/htdocs/iyue;
# 指定日志输出文件和日志格式为iyue_log
access_log /data/nginx/logs/iyue_access.log iyue_log;
# 自定义一个resp_body的变量,用来存放Response Body信息
set $resp_body "";
# 也可以使用body_filter_by_lua指令,将lua代码直接展示在这里;推荐采用文件的配置形式,方便后期维护
body_filter_by_lua_file conf/lua/get_resp_code.lua;
# 通过nginx配置代理github api,用于测试结果展示
location /github/api/ {
proxy_pass https://api.github.com/;
proxy_http_version 1.1;
proxy_set_header Connection "";
#proxy_set_header Host $host;
proxy_set_header Host api.github.com;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
пример кода луа
Получите значение Respondy Body и присвойте его переменной $resp_body:
cat lua/get_resp.lua
local chunk = string.sub(ngx.arg[1], 1, 1000)
ngx.ctx.buffered = (ngx.ctx.buffered or "") .. chunk
if ngx.arg[2] then
local resp = ngx.ctx.buffered
ngx.var.resp_body = resp
end
Здесь ngx.arg[2] — тип bool, после получения через lua информации всего Response Body, он присваивается переменной $resp_body, значение переменной может быть выведено в лог позже;
пример log_format
Определите формат журнала и напечатайте пользовательскую переменную $resp_body в журнале; поместите ее в конец для нашего наблюдения:
cat common/log_formats.conf
log_format iyue_log '$remote_addr $http_x_forwarded_for [$time_local] $request_method $uri $args $request_body $server_protocol $status $body_bytes_sent $http_referer $http_user_agent $request_length rspt:$upstream_response_time rqtt:$request_time up:$upstream_addr $remote_port $host $resp_body';
Отображение результатов
Инициировать тестовый запрос
curl http://test.iyue.pub/github/api/
Из выходного журнала мы видим, что nginx нормально записал информацию тела ответа:
192.168.10.11 - [04/May/2020:17:35:55 +0800] GET /github/api/ - - HTTP/1.1 200 2178 - curl/7.54.0 88 rspt:0.884 rqtt:0.880 up:140.82.113.5:443 64502 test.iyue.pub {\x22current_user_url\x22:\x22https://api.github.com/user\x22,\x22current_user_authorizations_html_url\x22:\x22https://github.com/settings/connections/applications{/client_id}\x22,\x22authorizations_url\x22:\x22https://api.github.com/authorizations\x22,\x22code_search_url\x22:\x22https://api.github.com/search/code?q={query}{&page,per_page,sort,order}\x22,\x22commit_search_url\x22:\x22https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}\x22,\x22emails_url\x22:\x22https://api.github.com/user/emails\x22,\x22emojis_url\x22:\x22https://api.github.com/emojis\x22,\x22events_url\x22:\x22https://api.github.com/events\x22,\x22feeds_url\x22:\x22https://api.github.com/feeds\x22,\x22followers_url\x22:\x22https://api.github.com/user/followers\x22,\x22following_url\x22:\x22https://api.github.com/user/following{/target}\x22,\x22gists_url\x22:\x22https://api.github.com/gists{/gist_id}\x22,\x22hub_url\x22:\x22https://api.github.com/hub\x22,\x22issue_search_url\x22:\x22https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}\x22,\x22issues_url\x22:\x22https://api.github.com/issues\x22,\x22keys_url\x22:\x22https://api.github.com/user/keys\x22,\x22label_searc
Фильтрация тела ответа
В приведенных выше результатах вывода журнала мы видим слово «x22» в журнале, которое на самом деле является шестнадцатеричным кодом ASCII с двойными кавычками; так что вы также можете видеть, что этот способ печати всего содержимого тела ответа не очень удобен. для специальных символов или китайского вывода; предлагаемое решение здесь состоит в том, чтобы выводить только определенный сегмент тела ответа, который вам нужен, и результат вывода должен быть максимально на английском языке; наш код lua может дополнительно фильтровать вывод, например, наш Выводить только результаты, соответствующие 'current_user_url' в теле ответа, код lua можно изменить на:
cat lua/get_resp.lua
local chunk = string.sub(ngx.arg[1], 1, 1000)
ngx.ctx.buffered = (ngx.ctx.buffered or "") .. chunk
if ngx.arg[2] then
local resp = ngx.ctx.buffered
local user_url = ""
user_url = string.match(resp, "\x22current_user_url\x22: \x22(.[^,]+)\x22")
ngx.var.resp_body = user_url
end
Результаты оптимизированного вывода журнала:
192.168.10.11 - [04/May/2020:18:05:40 +0800] GET /github/api/ - - HTTP/1.1 200 2308 - curl/7.54.0 88 rspt:0.900 rqtt:0.897 up:140.82.112.6:443 50340 test.iyue.pub https://api.github.com/user
Вы можете видеть, что формат лога стал более аккуратным, а результат, соответствующий «current_user_url», получается и печатается корректно.
возможные проблемы
Во время теста, если вы столкнулись со следующей ошибкой:failed to load the 'resty.core' module
, могут быть проблемы с совместимостью версий, можно попробовать уменьшить версию lua ниже 0.10.14;
Ссылка на справочную документацию
- Nginx: nginx.org/
- Tengine: Двигатель T. Taobao.org/document ATI…
- OpenResty Lua: GitHub.com/open остальное имеет/приходит…
- GitHub API v3: developer.github.com/v3/
- Загрузка исходного кода Nginx:nginx.org/download/
- Загрузка модуля ngx_lua:GitHub.com/open остальное имеет/приходит…
- Загрузите LuaJIT:GitHub.com/open остальное имеет/приходит…
- Загрузка модуля ngx_devel_kit (NDK):GitHub.com/vision5/Школа сельскохозяйственного вещания…