


+
Владислав Смирнов
FullStack Web Developer

PowerThesaurus в цифрах
- 19 миллионов синонимов
- Более 2 миллионов антонимов
- Более 3 миллионов пользователей в месяц
- Более 25 гигабайт данных
Нас стали парсить!
Признаки парсинга
- Длительное ожидание ответа от сервера
- Большая нагрузка на железо
- Странные запросы


Чем плох париснг
- Большая нагрузка на сервер
- Повышение отказа у пользователей
- Воровство контента
- Негативная реакция со стороны поисковых систем
Антипарсинг
Возможные решения
- Nginx:
- PHP + Redis (Memcached)
- CloudFlare
ngx_http_limit_req_module


+

NGINX - это HTTP-сервер и обратный прокси-сервер, почтовый прокси-сервер, а также TCP/UDP прокси-сервер общего назначения
- Скорость
- Отказоустойчивость
- Гибкость конфигурации
- Асинхронность
- Кэширование
- Модульность

Lua - высокоуровневый, скриптовый язык с динамической типизацией.
- Легкий
- Быстрый
- Низкий порог вхождения
- Встраиваемый
name = 'Yoda'
function bar(a, b)
print(a, b)
return 4, 8, 15
end
x, y = bar(name)
-- "Yoda nil nil"
-- x = 4, y = 8Кто использует Lua?




Преимущества NGINX + Lua
NGINX как сервер приложений

Lua исполняется в самом процессе Nginx, а не выносится в отдельный процесс, как это происходит в случае с другими языками.
Контекст
NGINX API
- ngx.status
- ngx.header.HEADER
- ngx.resp.get_headers
- ngx.req.is_internal
- ngx.req.start_time
- ngx.req.http_version
- ngx.req.raw_header
- ngx.req.get_method
- ngx.req.set_method
- ngx.req.set_uri
- ...
Код на Lua в контексте Nginx выполняется в неблокирующем режиме, включая запросы к БД и внешние HTTP-запросы, порожденные веб-приложением (например, запрос к API другого сайта).
Неблокирующий I/O
Расширение возможностей конфигурации NGINX
server {
location /hello {
content_by_lua_block {
ngx.say('Hello,world!')
}
}
}Что можно писать?
- Аналитика запросов
- Объединение сервисов
- API
- Middleware

OpenResty - это web платформа основанная на NGINX и LuaJIT.
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
server {
listen 8080;
location / {
default_type text/html;
content_by_lua '
ngx.say("<p>hello, world</p>")
';
}
}
}curl http://localhost:8080/
If everything is okay, we should get the output
<p>hello, world</p>server {
listen 8080;
location / {
default_type text/html;
content_by_lua_file /path/to/content.lua;
}
}uri = ngx.var.uri
ngx.say(uri)
-- try access /test?a=hello,world
ngx.say(ngx.var.arg_a)curl http://localhost:8080/test?a=hello,world
If everything is okay, we should get the output
/test
hello,worldКомпоненты
-
LuaRestyMemcachedLibrary
-
LuaRestyMySQLLibrary
-
LuaRestyRedisLibrary
-
LuaRestyWebSocketLibrary
-
LuaRestyLimitTrafficLibrary
-
PostgresNginxModule
-
...
local redis = require "resty.redis"
local red = redis:new()
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.say("failed to connect: ", err)
return
end
res, err = red:get("jedi")
ok, err = red:set("jedi", "Obi-Wan Kenobi")
if not ok then
ngx.say("failed to set dog: ", err)
return
end
ngx.say(res)Работа с Redis
curl http://localhost:8080/
null
curl http://localhost:8080/
Obi-Wan KenobiКак мы это используем?
Lua-Firewall
Что нам нужно?
- Определение поисковых роботов
- Определение парсера и пользователя
- Определение пользователей за одним IP
- Лимитирование количества обращений к Nginx
- White list для ip
- Ban list
- Сбор статистики
Определение поисковых ботов
local crawlers = {}
function crawlers.user_agent_check_bot(user_agent)
-- Проверяет user_agent клиента по списку ботов на совпадение
end
function crawlers.host_check_bot(host, bot)
-- Проверяет хост клиента на совпадение со списком хостов ботов
end
function crawlers.is_bot(storage, user_agent, ip)
-- Проверяет является ли клиент поисковым ботом
endОпределение парсера и пользователя
client = {}
function client:new(id, type, rps_storage, bans_storage, path_to_banlist)
local obj = {}
function obj:check_ban()
-- проверяем бы ли забанен ip
end
function obj:add_ban(time)
-- добавить в бан
end
-- тело класса
function obj:count_success_captcha()
-- сколько каптч отгадал пользователь
end
return setmetatable(obj, self)
end 
Используем капчу что бы определить человека
Определение пользователей за одним IP

Что еще?
- Лимитирование количества обращений к Nginx
- White list для ip
- Ban list
- Сбор статистики
Как это реализовали в 2GIS
https://habrahabr.ru/company/2gis/blog/199504/
http://www.highload.ru/2013/abstracts/934.html
Владимир Протасов
OpenResty: превращаем NGINX в полноценный сервер приложений
https://www.youtube.com/watch?v=silrEB0Brvo&t=1802s
Спасибо!

Nginx + Lua
By radyushin
Nginx + Lua
- 968