Всем привет. В данной статье я расскажу как легко и просто можно организовать сбор данных с веб сервера NGINX при помощи модуля Lua. Статья подразумевает, что читатель знаком с NGINX и Lua.
Начнем. Для начала создадим конфигурационный файл для NGINX, в котором будет создан мини-сервер для получения данных.
Code | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| #специальная переменная (хэш-таблица), которая будет общей для всех воркеров nginx
lua_shared_dict requests_counter 20m;
#добавляем обработчик, который будет срабатывать на каждом обработанном запросе (фаза логирования)
log_by_lua_file '/path/to/lua/counter.lua';
server {
listen 127.0.0.1:8890;
server_name ams.local;
#простой вывод содержимого по принципу ключ-значение
location /monitor {
content_by_lua '
local keys = ngx.shared.requests_counter:get_keys(100000)
for _, ip in pairs(keys) do
ngx.say(ip .. ";" .. ngx.shared.requests_counter:get(ip))
end
';
}
} |
|
После этого, создадим файл "/path/to/lua/counter.lua" и напишем в нем следующее:
Code | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
| -- ссылка на таблицу
local requests = ngx.shared.requests_limit;
local function monitor()
-- ключ для таблицы - имя сервера, к которому было обращение
local key = ngx.var.server_name;
-- ответ сервера
local status = ngx.var.status;
-- ссылка на таблицу
local list = ngx.shared.requests_counter;
-- список "плохих" ответов
local banned_statuses = { ['444'] = true, ['408'] = true, ['449'] = true, ['400'] = true };
local keys = {
["a"] = key .. ";all",
["be"] = key .. ";backend",
["bn"] = key .. ";banned",
["ajax"] = key .. ";ajax",
["bs"] = key .. ";bytes"
};
-- для каждого ключа делаем проверку, если он не существует, дабавляем его
for _, _key in pairs(keys) do
local temp_val = list:get(keys[_key]);
if temp_val == nil then
list:add(_key, 0);
end
-- я сделал ограничение на максимальное число, так как не знаю, что будет, когда превысится лимит. Может кто подскажет? Будет ли это значение 0 или каким-то специальным?
if temp_val and temp_val >= 70368744177664 then --math.pow(2, 46) value
list:set(_key, 0);
end
end
list:incr(keys.a, 1);
-- если есть ответ от бэкенд сервера
if ngx.var.upstream_status ~= nil then
list:incr(keys.be, 1);
end
-- если ответ в списке "плохих"
if banned_statuses[status] then
list:incr(keys.bn, 1);
end
-- если есть заголовок к запросе
if ngx.header['X-Requested-With'] ~= nil then
list:incr(keys.ajax, 1);
end
-- если в ответе есть данные
if ngx.var.body_bytes_sent ~= nil then
list:incr(keys.bs, ngx.var.body_bytes_sent);
end
end
monitor(); |
|
Теперь можно перезагрузить nginx сервер и собирать с него данные, например с помощью CURL: curl http://127.0.0.1:8890/monitor

Код, написанный на Lua, собирает следующую статистику для каждого заведенного сервера: общее кол-во обращений, кол-во запросов, отправленных до бэкенд сервера, кол-во ajax запросов, кол-во "забаненных" или "ошибочных" запросов, и кол-во отданных байт, т.е. считаем трафик.
Эти данные выводятся в удобно формате для парсинга. Так что, написав простой парсер, можно собирать эти данные в БД и строить по ним графики.
Спасибо за прочтение!
З.Ы. Я также пишу в своем личном блоге статьи на английском (пока только начал, строго не судите ). Кому интересно вот ссылка. Там я буду продолжать выкладывать свои интересные наработки.
З.Ы.Ы. Также я выкладываю на github обновления.
|