- PVSM.RU - https://www.pvsm.ru -
Работая над несколькими open-source проектами, в один прекрасный день я решил упростить себе жизнь и разработал Upstream-модуль для nginx, который помог мне убрать громоздкие слои многослойной архитектуры. Это был забавный опыт, которым я хочу поделиться в этой статье. Мой код лежит в открытом доступе тут: github.com/tarantool/nginx_upstream_module [1]. Его можно поднять с нуля или скачать Docker-образ по этой ссылке: hub.docker.com/r/tarantool/tarantool-nginx [2].
На повестке дня:
Вот так выглядит стандартная архитектура микросервисов. Запросы пользователей поступают через nginx на сервер приложений. На сервере есть бизнес-логика, с которой взаимодействуют пользователи.
Сервер приложений не хранит состояния объектов, поэтому их нужно хранить где-то еще. Для этого можно использовать базы данных. И не забывайте про кэш, который уменьшит задержку и обеспечит более быструю доставку контента.
Разобьем это на слои:
1-й слой — nginx.
2-й слой — сервер приложений.
3-й слой — кэш.
4-й слой — прокси базы данных. Этот прокси необходим для обеспечения отказоустойчивости и поддержания постоянного подключения к базе данных.
5-й слой — сервер базы данных.
Раздумывая об этих слоях, я придумал, как исключить некоторые из них. Зачем? Много причин. Мне нравятся простые понятные вещи; я не люблю поддерживать большое количество разных систем в prodution; и последнее, но не по значимости — чем меньше слоев, тем меньше точек отказа. В результате я сделал модуль Tarantool Upstream под nginx, который помог сократить количество слоёв до двух.
Как Tarantool помогает уменьшить количество слоёв? Первый слой — nginx, второй, третий и пятый слои заменяет Tarantool. Четвертый слой — прокси базы данных — теперь в nginx. Фишка в том, что Tarantool — это база данных, кэш и сервер приложений, три в одном. Мой upstream-модуль связывает nginx и Tarantool друг с другом и позволяет им слаженно работать без других трёх слоёв.
Вот так выглядит новый микросервис. Пользователь отправляет запрос к REST или JSON RPC в nginx с модулем Tarantool Upstream. Модуль может быть подключен напрямую к Tarantool, или нагрузка может быть сбалансирована на несколько серверов Tarantool. Между nginx и Tarantool мы используем эффективный протокол, в основе которого лежит MSGPack. Дополнительную информацию вы найдете в этой статье [3].
Еще можете перейти по этим ссылкам, чтобы загрузить Tarantool и модуль nginx. Но я бы посоветовал установить их через пакетный менеджер вашего дистрибутива или воспользоваться Docker-образом (docker pull tarantool/tarantool-nginx
).
Docker-образы: hub.docker.com/r/tarantool/tarantool [4]
Tarantool NginX upstream module [2]
Бинарные пакеты: Tarantool — Download [5]
Исходный код: Tarantool [6]
tarantool/nginx_upstream_module [1]
Вот пример файла nginx.conf. Как видите, это обычный upstream nginx. Тут у нас есть tnt_pass
, прямо указывающий nginx, по какому пути расположить upstream tarantool.
nginx-tnt.conf
http {
# upstream
upstream tnt {
server 127.0.0.1:3301;
keepalive 1000;
}
server {
listen 8081;
# gateway
location /api/do {
tnt_pass_http_request parse_args;
tnt_pass tnt;
}
}
}
Вот ссылки на документацию:
nginx.org/en/docs/http/ngx_http_upstream_module.html [7]
github.com/tarantool/nginx_upstream_module/blob/master/README.md [8]
Сконфигурировали связку nginx и Tarantool, что потом? Теперь нужно прописать функцию обработчика для нашего сервиса и разместить ее в файле. Я положил её в файл “app.lua”.
Вот ссылка на документацию Tarantool: tarantool.io/ru/doc/1.9/book/box/data_model/#index [9]
-- Bootstrap Tarantool
box.cfg { listen='*:3301' }
-- Grants
box.once('grants', function()
box.schema.user.grant('guest', 'read,write,execute', 'universe')
end)
-- Global variable
hello_str = 'Hello'
-- function
function api(http_request)
local str = hello_str
if http_request.method == 'GET' then
str = 'Goodbye'
end
return 'first', 2, { str .. 'world!' }, http_request.args
end
Теперь рассмотрим код Lua.
Наш Box.cfg {}
говорит Tarantool начать слушать порт 3301, но он может принимать и другие параметры.
Box.once
говорит Tarantool вызывать какую-то функцию один раз.
function api ()
— это функция, которую я скоро буду вызывать. Она принимает HTTP-запрос в качестве первого аргумента и возвращает массив значений.
Я сохранил этот код в файл и назвал его “app.lua”. Выполнить его можно, просто запустив Tarantool-приложение.
$> tarantool app.lua
Вызовем нашу функцию с помощью GET-запроса. Я для этого использую “wget”. По умолчанию, “wget” сохраняет ответ в файл. И для чтения данных из файла я использую “cat”.
$ wget '0.0.0.0:8081/api/do?arg_1=1&arg_2=2'
$ cat do*
{ “id”:0, # — unique identifier of the request
“result”: [ # — is what our Tarantool function returns
[“first”], [2], [{
“request”:{“arg_2”:”2",”arg_1":”1"}
“1”:”Goodbye world!”
}]
]}
Оценка проводилась на данных из production. Входные данные — это большой JSON-объект. Средний размер такого объекта 2 Кб. Один сервер, 4-ядерный CPU, 90 Гб RAM, OS Ubuntu 14.04.1 LTS.
Для этого теста мы используем только один nginx worker. Этот worker — балансировщик с простым алгоритмом ROUND-ROBIN. Он балансирует нагрузку между двумя узлами Tarantool. Нагрузка масштабируется с помощью шардинга.
Эти графики показывают количество операций чтения в секунду. Верхний график показывает задержки (в миллисекундах).
А эти графики показывают количество операций записи в секунду. Верхний график показывает задержки (в миллисекундах)
Впечатляюще!
В следующей статье я подробно расскажу про REST и JSON RPC.
Англоязычная версия статьи: hackernoon.com/shrink-the-number-of-tiers-in-a-multitier-architecture-from-5-to-2-c59b7bf46c86 [10]
Автор: dedokOne
Источник [11]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/nginx/286866
Ссылки в тексте:
[1] github.com/tarantool/nginx_upstream_module: https://github.com/tarantool/nginx_upstream_module
[2] hub.docker.com/r/tarantool/tarantool-nginx: https://hub.docker.com/r/tarantool/tarantool-nginx
[3] этой статье: https://medium.com/@vasiliysoshnikov/building-nginx-and-tarantool-based-services-c92492fc34c6#.yiru1luj9
[4] hub.docker.com/r/tarantool/tarantool: https://hub.docker.com/r/tarantool/tarantool
[5] Tarantool — Download: https://tarantool.io/ru/download/
[6] Tarantool: https://github.com/tarantool
[7] nginx.org/en/docs/http/ngx_http_upstream_module.html: http://nginx.org/en/docs/http/ngx_http_upstream_module.html
[8] github.com/tarantool/nginx_upstream_module/blob/master/README.md: https://github.com/tarantool/nginx_upstream_module/blob/master/README.md
[9] tarantool.io/ru/doc/1.9/book/box/data_model/#index: https://tarantool.io/ru/doc/1.9/book/box/data_model/#index
[10] hackernoon.com/shrink-the-number-of-tiers-in-a-multitier-architecture-from-5-to-2-c59b7bf46c86: https://hackernoon.com/shrink-the-number-of-tiers-in-a-multitier-architecture-from-5-to-2-c59b7bf46c86
[11] Источник: https://habr.com/post/417829/?utm_campaign=417829
Нажмите здесь для печати.