Openresty можно использовать с lua-скриптами на базе Nginx для достижения более продвинутых функций, таких как Ограничение тока、кэш、Незаконный перехват URI и другие функции.
Ограничения движения в основном включают ограничение частоты и Ограничение тока:
Ограничение ток делится на Ограничение по объему запроса токаи количество подключений Ограничение тока, можно настроить в nginx.conf. Сам Nginx поставляется с Ограничением. функции тока, Openresty также реализует гибкое Ограничение Функция тока.
limit_req_zone
да Nginx Один из модулей, используемых для реализации запроса Ограничение Функция тока. это да Nginx Поставляется с функциями, не зависит от OpenResty。
По умолчанию Нгинкс использовать "leaky Алгоритм "ведро" (дырявое ведро) для выполнения запросов Ограничение тока。
Алгоритм дырявого ведра даA классический запрос Ограничение алгоритм тока,В его основе лежит структура данных, похожая на дырявое ведро. Запросы попадают в «дырявое ведро» с фиксированной скоростью.,Если дырявое ведро полное,Запрос отклоняется или задерживается. Этот алгоритм плавно ограничивает скорость запросов,Предотвратите перегрузку сервера.
Можетиспользовать limit_req_zone
Директива для определения запроса площадь Тока,ииспользовать limit_req
Инструкция по применению Ограничения тока Стратегия。
Простой пример выглядит следующим образом:
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
server {
listen 8080;
location / {
limit_req zone=perip burst=5;
default_type text/html;
content_by_lua_block {
ngx.say("<p>hello, world</p>")
}
}
}
}
вышеlimit_req_zone
Определена область хранения с именем perip размером 10 МБ, используемая для хранения статуса запроса каждого IP-адреса. Переменная $binary_remote_addr представляет IP-адрес клиента. скорость=100р/м означает, что каждый IP может отправлять только 100 запросов в минуту.
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
limit_req
Конфигурация применена вышеlimit_req_zone
Определенные пределы. Zone=perip указывает, какую область хранения использовать.,всплеск=5 означает, что запросы за короткий период времени могут превысить лимит,Максимум более 5. Если эта сумма превышена,Тогда лишние запросы будут задерживаться.,Пока частота запросов не упадет ниже лимита. Если установить параметр nodelay,Тогда запросы, превышающие количество пакетов, будут напрямую отклонены.
limit_req zone=perip burst=5;
Конечно, вы также можете обратиться к указанному выше номеру запроса. Ограничение. ток способ установки количества подключений Ограничение тока。
limit_conn_zone $binary_remote_addr zone=concurrent:10m;
limit_conn concurrent 5;
Несколько расширений Lua, официально предоставленных OpenResty:
Реализация логики в Openresty использует скрипт lua.,существоватьlocation
中Можетиспользоватьaccess_by_lua_block
Блоки кода для реализации логики,Вы также можете разделить логику на другие файлы.,тогда пройдиaccess_by_lua_file xxx.lua
Просто процитируйте.
Вот пример ограничения тока, который можно запрашивать только 100 раз каждые 60 секунд:
worker_processes 1;
error_log logs/error.log info;
events {
worker_connections 1024;
}
http {
# Объявить объект хеш-кэша
lua_shared_dict limit_count_store 100m;
server {
location / {
access_by_lua_block {
-- Запрос на введение токмодуль
local limit_count = require "resty.limit.count"
-- Его можно вызвать только 100 раз в течение 60 секунд, а статистика сохранится в кеш.
local lim, err = limit_count.new("limit_count_store", 100, 60)
if not lim then
ngx.log(ngx.ERR, "failed to instantiate a resty.limit.count object: ", err)
return ngx.exit(500)
end
-- Используйте IP-адрес клиента в качестве ключа для подсчета количества запросов.
local key = ngx.var.binary_remote_addr
local delay, err = lim:incoming(key, true)
-- Если количество запросов находится в пределах лимита, задержка для обработки текущего запроса и оставшегося количества запросов для обработки, задержка возвращает 0, err возвращает оставшееся число
-- Если запрос отклонен, задержка возвращает ноль, ошибка возвращает отклонено
ngx.log(ngx.INFO, "Запросить оставшийся номер:", err);
if not delay then
if err == "rejected" then
return ngx.exit(503)
end
ngx.log(ngx.ERR, "failed to limit count: ", err)
return ngx.exit(500)
end
}
default_type text/html;
content_by_lua_block {
ngx.say("<p>hello, world</p>")
}
}
}
}
нижедаограничить каждыйклиент Макс1одновременные запросы。
worker_processes 1;
error_log logs/error.log info;
events {
worker_connections 1024;
}
http {
# Объявить объект хеш-кэша
lua_shared_dict limit_count_store 100m;
server {
location / {
access_by_lua_block {
local limit_conn = require "resty.limit.conn"
-- Ограничьте один ip клиент Макс 1 одновременные запросы
-- burst установлен на 0. Если максимальное количество одновременных запросов превышено, будет возвращено 503.
-- Если вы хотите разрешить внезапное увеличение параллелизма, вы можете изменить это. burst Значение (емкости дырявого ведра)
-- Последний параметр фактически означает, что вам необходимо оценить, сколько времени займет обработка этих одновременных (или отдельных запросов), чтобы вы могли применить алгоритм дырявого ведра к запросам в ведре.
-- Если установлено локальное lim, err = limit_conn.new("limit_conn_store", 50, 25, 0.5)
-- Это значит, что лимит 50одновременные. запросы,и 25 дополнительных одновременных пакетных запросов, То есть один клиент обращается к 50 +25 503 будет выброшено после
local lim, err = limit_conn.new("limit_conn_store", 1, 0, 0.5)
if not lim then
ngx.log(ngx.ERR, "failed to instantiate a resty.limit.conn object: ", err)
return ngx.exit(500)
endlocal key = ngx.var.binary_remote_addr
-- commit это правда Указывает на необходимость обновления общего Значение ключа в dict,-- false Это означает, что вы можете просмотреть только задержку обработки текущего запроса и количество предыдущих запросов, которые еще не были обработаны. delay, err = lim:incoming(key, true)
if not delay thenif err == "rejected" thenreturn ngx.exit(503)
end
ngx.log(ngx.ERR, "failed to limit req: ", err)
return ngx.exit(500)
end-- Если такая информация, как количество запросов на подключение, добавляется в общий dict, затем запишите его в ctx, -- Потому что нам нужно сообщить вам, что соединение будет отключено позже для обработки других соединений, если lim:is_committed() thenlocal ctx = ngx.ctx
ctx.limit_conn = lim
ctx.limit_conn_key = key
ctx.limit_conn_delay = delay
endlocal conn = err
-- На самом деле здесь delay Оно должно быть целым числом, кратным времени одновременной обработки, упомянутому выше, -- Например, если в секунду обрабатывается 100 одновременных вызовов, а емкость корзины равна 200, то при одновременном поступлении 500 одновременных вызовов 200 будут отклонены. 100 обрабатываются, а затем 200 временно сохраняются в корзине. Среди 200 временно сохраненных соединений 0–100 соединений фактически должны быть задержаны на 0,5 секунды, -- 101-200 должны быть задержаны на 0,5*2=1 секунду (0,5да расчетного времени одновременной обработки, указанного выше) -- ngx.say("delay: ", delay)if delay >= 0.001 then-- ngx.sleep(delay)end
}
log_by_lua_block {
local ctx = ngx.ctx
local lim = ctx.limit_conn
if lim thenlocal key = ctx.limit_conn_key
-- После того, как это соединение будет обработано, вы должны сообщить нам и обновить общий доступ. Значение в dict позволяет получать доступ к последующим соединениям для обработки: Здесь вы можете динамически обновлять предыдущее расчетное время, но не забудьте написать метод limit_conn.new, -- В противном случае local будет сбрасываться каждый раз при поступлении запроса. conn, err = lim:leaving(key, 0.5)
if not conn then
ngx.log(ngx.ERR,
"failed to record the connection leaving ",
"request: ", err)
returnendend
}
default_type text/html;
content_by_lua_block {
ngx.say("<p>hello, world</p>")
}
}
}
}
Другие Ограничение частотыи Ограничение Метод тока также является аналогичным методом обработки.