Будуємо сервіси на базі Nginx і Tarantool

Вам знайома така архітектура? Хоровод демонів, танцюють між web-server, cache і storage.



Які мінуси такої архітектури можна відзначити? Вирішуючи завдання у рамках такої архітектури, ми стикаємося з купою питань: яку мову(і?) взяти, який I/O framework вибрати, як синхронізувати cache і storage? Купа інфраструктурних питань. А навіщо вирішувати інфраструктурні питання, коли треба розв'язати задачу? Безумовно, можна сказати, що нам подобаються якісь технології X і Y, і перевести ці мінуси в рамки ідеологічних. Але не можна заперечувати той факт, що дані розташовуються на деякій відстані від коду (зображення вище), що додає latency, що може зменшити RPS.

Мета даної статті — розповісти про альтернативу, яка побудована на базі Nginx як web-server, bаlancer і Tarantool як App Server, Cache, Storage.

Покращуємо cache і storage


У Tarantool є кілька цікавих властивостей. Tarantool — це не тільки ефективна inmemory DB, але і повноцінний Application Server, програми пишуться на Lua (luajit), C, C++, тобто можна написати логіку будь-якої складності, обмеження одне: фантазія. Якщо даних більше, ніж доступно пам'яті, частина даних можна зберігати на диску, використовуючи движок Sophia. Якщо Sophia не підходить, можна взяти щось інше і скидати «холодні» дані, тобто дані, які не потрібні прямо зараз, з Tarantool в інший Storage, а «гарячу» частина зберігати в Tarantool, тобто в пам'яті. Які переваги це дає нам?

  • Немає посередників. Як мінімум гаряча частину даних знаходиться на одному рівні з кодом.
  • Гарячі дані в пам'яті.
  • Код досить простий і легко оновлюється, якщо ми говоримо про Lua.
  • Транзакції, реплікація, шардінг і можество інших можливостей Taranool.


Покращуємо web-server


Кінцевим споживачем даних є користувач. Зазвичай, користувач отримує дані від Application Server через Nginx як балансер/проксі. Варіант написання демона, який вміє спілкуватися і з Tarantool, і з HTTP не підходить, так як приведе нас до першого малюнка, і ми знову повернемося до того, з чого почали. Тому спробуємо поглянути на ситуацію з іншого боку, і поставити інше питання: «Як позбутися посередників між даними і користувачем?». Відповіддю на це питання і стала реалізація Tarantool Nginx Upstream Module.

Nginx Upstream
Nginx Upstream — це персистентное (див. Upstream Keepalive) з'єднання через pipe/socket до backend, далі будемо називати це «проксированием». Nginx надає багато різноманітного функціоналу для написання правил Upstream, для проксі серверів HTTP Tarantool особливого значення набувають такі функції:

  1. можливість вказувати кілька backend, на які Nginx буде балансувати навантаження;
  2. можливість вказувати backup, тобто вказувати, куди ходити, якщо Upstream не працює.
Ці можливості дозволяють:

  1. розподіляти навантаження на N Tarantool, наприклад, укупі з шардингом можна побудувати кластер з рівномірним завантаженням по нодам;
  2. можна зробити відмовостійку систему за допомогою реплікації;
  3. використовуючи п. а) і п. b) отримаємо відмовостійкий кластер.
Приклад конфига для Nginx, частково ілюструє можливості налаштувань:

# Настройки проксі серверів в Tarantool
upstream tnt
{
server 127.0.0.1:10001; # перший сервер живе на localhost
server node.com:10001; # другій де-то ще
server unix:/tmp/tnt; # третій через unix socket

server node.backup.com backup; # а тут backup
}

# HTTP-сервер
server
{
listen 8081 default;
location = /тнт/pass {
# Говоримо Nginx що треба використовувати Tarantool Upstream Module
# і вказуємо ім'я Upstream
tnt_pass tnt; 
}
}

Більш детально про конфігуруванні Nginx Upstream можна прочитати тут: http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream.

Nginx Tarantool Upstream Module (v0.1.4 Stable)


Основний функціонал:

  • модуль активується в Nginx.conf директивою — tnt_pass UPSTREAM_NAME;
  • швидке потокове перетворення HTTP + JSON <-> Tarantool Protocol, мінімальні блокування (на час парсинга) Nginx worker;
  • неблокирующее I/O Nginx в обидва напрямки;
  • як приємний бонус: всі фічі Nginx, Nginx Upstream;
  • модуль дозволяє викликати збережені процедури Tarantool через JSON-based Protocol;
  • дані доставляються через HTTP(S) POST, що зручно для Modern WebApps і не тільки.

Вхідні дані

[ { "method": STR, "params":[arg0 ... argN], "id": UINT }, ...N ]

«method»
Ім'я збереженої процедури. Ім'я повинне збігатися з ім'ям процедури в Tarantool. Наприклад, щоб викликати lua-функцію
do_something(a, b)
, треба:
"method": "do_something"


«params»
Аргументи збереженої процедури. Наприклад, щоб передати аргументи у lua-функцію
do_something(a, b)
, треба:
"params": [ "1", 2 ]


«id»
Числовий ідентифікатор, встановлюється клієнтом.

Вихідні дані

[ { "result": JSON_RESULT_OBJECT, "id":UINT, "error": { "message": STR, "code": INT } }, ...N ]


«result»
Дані, які повернула збережена процедура. Наприклад, lua-функція
do_something(a, b)
повертає
return {1, 2}
"result": [[1, 2]]


«id»
Числовий ідентифікатор, встановлений клієнтом.

«error»
Якщо сталася помилка, в цьому полі будуть дані про причини.

Більш детальніше про протоколі тут: https://github.com/tarantool/nginx_upstream_module/blob/master/README.md

Hello World

Запусків Nginx

Nginx ми зберемо з исходников:

$ git clone https://github.com/tarantool/nginx_upstream_module.git
$ cd nginx_upstream_module
$ git submodule update --init --recursive
$ git clone https://github.com/nginx/nginx.git
$ cd nginx && git checkout release-1.9.7 && cd -
$ make build-all-debug 

Мета build-all-debug — це debug-версія. Робимо так, щоб менше конфігурувати Nginx. Для тих, хто хоче законфигурировать все з нуля, є мета
build-all
.

Файл
test-root/conf/nginx.conf


http
{
# Додає один Tarantool як backend
upstream echo
{
server 127.0.0.1:10001;
}
server
{
listen 8081 default; # Nginx повісимо на *:8081

server_name tnt_test;

location = /echo #*: 8081/echo вішаємо 'echo' Tarantool Upstream
{
tnt_pass echo;
}
}
}


$ ./nginx/obj/nginx # запускаємо nginx

Запускаємо Tarantool

Tarantool можна поставити з пакетів, або зібрати.

Файл
hello-world.lua


-- Це і є наша збережена процедура, вона гранично проста і не використовує Tarantool як DB.
-- Все що вона робить - це просто повертає свій 1-й аргумент.
function echo(a)
return {{a}}
end

box.cfg {
listen = 10001; -- вказуємо куди вішаємо Tarantool
}

Якщо ви поставили Tarantool з пакетів, запустити його можна так:

$ tarantool hello-world.lua # першим аргументом передаємо ім'я lua-скрипта.

Викликаємо збережену процедуру

Викликати збережену процедуру echo можна будь-яким HTTP-коннектором, все що потрібно зробити — HTTP POST по 127.0.0.1/echo і в тілі передати наступний JSON (див. Вхідні дані):

{
"method":"echo", // ім'я методу, має збігатися з ім'ям методу в Tarantool
"params":[
{"Hello world": "!"} // 1-й аргумент - об'єкт
],
"id":1 // ID повідомлення
}

Я викличу цю процедуру wget'ом

$ wget 127.0.0.1:8081/echo --post-data '{"method":"echo","params":[{"Hello world": "!"}],"id":1}'
$ cat echo
{"id":1,"result":[[{"hello world":"!"}]]}


Ще кілька прикладів:
https://github.com/tarantool/nginx_upstream_module/blob/master/examples/echo.html
https://github.com/tarantool/nginx_upstream_module/blob/master/test/client.py

Підведемо підсумки
Плюси використання Nginx Tarantool Upstream Module:

  • немає посередників, код і дані, як правило, на одному рівні;
  • щодо просте конфігурування;
  • балансування навантаження на N Tarantool;
  • висока швидкість роботи, низька latency;
  • JSON-based протокол замість бінарного, не треба шукати Tarantool Driver, JSON є скрізь;
  • Tarantool Sharding/Replication і Nginx = кластерний рішення, але це тема окремої статті;
  • рішення використовується в продакшені.
Мінуси:

  • Overhead JSON замість більш компактного і швидкого MspPack;
  • рішення не коробкове, потрібно конфігурувати, потрібно думати, як деплоить.
Плани:

  • підтримка OpenRasty і nginScript;
  • підтримка WebSocket і HTTP 2.0.


Результати бенчмарка, а вони дуже цікаві, будуть в іншій статті. Tarantool, як і Upstream Module, завжди відкритий для нових користувачів, якщо у вас є бажання це все спробувати, використовувати або висловити нову ідею — звертайтеся на github, google group.

Посилання
Сайт Tarantool — http://tarantool.org
Git Tarantool — https://github.com/tarantool/tarantool
Git Tarantool Nginx Upstream Module — github.com/tarantool/nginx_upstream_module
Google group — https://groups.google.com/forum/#!forum/tarantool

P. S. У наступній статті я покажу які завдання можна вирішити, використовуючи Tarantool.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.