В Tarantool можете да комбинирате супербърза база данни и приложение за работа с нея. Ето как се прави лесно.

Пет години преди опитах да работя с Tarantool, но тогава не ми допадна. Но наскоро проведох уебинар, където говорех за Hadoop и как работи MapReduce. Тогава ми зададоха въпрос — "Защо да не използвате Tarantool за тази задача?".

От любопитство реших да се върна към него, да тествам последната версия — и този път проектът ми хареса много. Сега ще покажа как да напиша просто приложение в Tarantool, ще го натоваря и ще проверя производителността, и ще видите колко е лесно и страхотно.

В Tarantool можете да комбинирате супербърза база данни и приложение за работа с нея. Ето как се прави лесно.

Какво е Tarantool

Tarantool се позиционира като свръхбърза база данни. Можете да добавяте всякакви данни, каквито искате. Освен това, можете да репликирате, шардирвате — т.е. да разпределяте огромно количество данни на няколко сървъра и да обединявате резултатите — да създавате отказоустойчиви връзки от типа „мастър-мастър“.

На второ място, това е приложен сървър. Можете да пишете свои приложения, да работите с данни, например да изтривате стари записи на фона на определени правила. Можете да създадете Http-сървър директно в Tarantool, който да работи с данни: да предоставя броя им, да записва нови данни и да редуцира всичко това на мастера.

Четох статия, как хора направиха опашка от съобщения с 300 реда, която буквално разцепва — те имат минимална производителност от 20 000 съобщения в секунда. Тук наистина можете да се развихрите и да напишете много голямо приложение, и това няма да е като в PostgreS.

Примерно такъв сървър, само по-прост, ще опитам да опиша в тази статия.

Инсталиране

За теста създадох три стандартни виртуални машини – твърд диск с 20 гигабайта, Ubuntu 18.04. 2 виртуални CPU и 4 гигабайта памет.

Инсталираме Tarantool — стартираме shell скрипт или добавяме хранилище и правим apt get install Tarantool. Връзка към скрипта — (curl -L https://tarantool.io/installer.sh | VER=2.4 sudo -E bash). Появяват се такива команди, като:

tarantoolctl — основната команда за управление на инстансите на Tarantool.
/etc/tarantool — тук е цялата конфигурация.
var/log/tarantool — тук са логовете.
var/lib/tarantool — тук са данните, и след това те са разпределени по инстанси.

Има папки instance-available и instance-enable — в тях се намира това, което ще се стартира — файл с конфигурация на инстанса с lua код, където е описано, на какви портове той слуша, каква памет му е достъпна, настройки на двигателя Vinyl, код, който сработва при стартиране на сървъра, шардирование, опашки, изтриване на остарели данни и така нататък.

Инстансите работят като в PostgreS. Например, ако искате да стартирате няколко копия на база данни, която работи на различни портове. Тоест, на един сървър се стартират няколко инстанса на бази данни, които работят на различни портове. Те могат да имат абсолютно различни настройки — един инстанс реализира една логика, а вторият — друга.

Управление на инстансите

Имаме команда tarantoolctl, която позволява управление на инстансите на Тарантула. Например, tarantoolctl check example ще провери файла с конфигурация и ще каже — файлът е ок, ако там няма синтактични грешки.

Може да се види статусът на инстанса — tarantoolctl status example. По същия начин могат да се извършват действия start, stop, restart.

Когато инстансът е стартиран, може да се свържете по два начина.

1. Административна конзола

По подразбиране Tarantool отваря сокет, където се предава обикновен ASCII текст за управление на Тарантула. Свързването с конзолата винаги се извършва под потребител admin, там няма аутентификация, затова не трябва да излагате конзолните портове навън за управление на Тарантула.

За да се свържете по този начин, трябва да въведете Tarantoolctl enter instance name. Командата ще стартира конзолата и ще се свърже под потребител admin. Никога не излагайте конзолния порт навън — по-добре оставете го като юнитсокет. Тогава възможността за свързване с Тарантул ще бъде само за тези, които имат достъп до запис в сокета.

Този метод е необходим за административни задачи. За работа с данни използвайте втория метод — бинарен протокол.

2. Използване на бинарен протокол за свързване към определен порт

В конфигурацията има директива listen, която отваря порт за външни комуникации. Този порт се използва с бинарния протокол и там е включена аутентификация.

За това свързване се използва tarantoolctl connect to port number. Използвайки я, може да се свързвате с отдалечени сървъри, да използвате аутентификация и да давате различни права на достъп.

Запис на данни и модул Box

Тъй като Tarantool е както база данни, така и приложение, в него има различни модули. Нас интересува модулът box – той реализира работа с данни. Когато запишете нещо в box, Tarantool записва данните на диск, запазва ги в паметта или извършва нещо друго с тях.

Запис

Например, влизаме в модула box и извикваме функцията box.once. Тя ще накара Tarantool да стартира нашия код при инициализацията на сървъра. Създаваме space, в който ще се съхраняват нашите данни.

local function bootstrap()
    local space = box.schema.create_space('example')
    space:create_index('primary')
    box.schema.user.grant('guest', 'read,write,execute', 'universe')

    -- Запазваме нещата безопасни по подразбиране
    --  box.schema.user.create('example', { password = 'secret' })
    --  box.schema.user.grant('example', 'replication')
    --  box.schema.user.grant('example', 'read,write,execute', 'space', 'example')
end

След това създаваме първичен индекс – primary – по който ще можем да търсим данни. По подразбиране, ако не зададете никакви параметри, ще се използва първото поле в записа за праймери-индекса.

След това правим грант на потребителя guest, с който се свързваме по бинарния протокол. Разрешаваме четене, писане и изпълнение във всичките инстанси.

Ако сравним с обикновените бази данни, тук всичко е доста просто. Имаме space – зона, в която просто се съхраняват нашите данни. Всеки запис се нарича кортеж. Той се опакова в MessagePack. Това е много интересен формат – той е бинарен и заема по-малко място – 18 байта срещу 27.

В Tarantool можете да комбинирате супербърза база данни и приложение за работа с нея. Ето как се прави лесно.

С него е доста удобно да се работи. Почти всеки ред, всеки запис може да има абсолютно различни колони.

Всички спейсове можем да видим с командата Box.space. За да изберем конкретен инстанс – пишем box.space example и получаваме пълна информация за него.

В Tarantool са вградени два типа движци: Memory и Vinyl. Memory запазва всичките данни в паметта. Затова всичко работи просто и бързо. Данните се записват на диск, а също така съществува механизъм write ahead log, така че нищо няма да загубим при падане на сървера.

Vinyl съхранява данните на диска в по-познат вид за нас – тоест може да се съхраняват повече данни, отколкото имаме памет, и Tarantool ще ги чете от диска.

Сега ще използваме Memory.

unix/:/var/run/tarantool/example.control> box.space.example
---
- engine: memtx
  before_replace: 'function: 0x41eb02c8'
  on_replace: 'function: 0x41eb0568'
  ck_constraint: []
  field_count: 0
  temporary: false
  index:
    0: &0
      unique: true
      parts:
      - type: unsigned
        is_nullable: false
        fieldno: 1
      id: 0
      space_id: 512
      type: TREE
      name: primary
    primary: *0
  is_local: false
  enabled: true
  name: example
  id: 512
...

unix/:/var/run/tarantool/example.control>

Индекс:

Първичният индекс трябва да се създаде за всяко пространство, защото без него нищо няма да работи. Както и в базата данни, ние създаваме първото поле – ID на записа.

Части:

Тук посочваме от какво се състои нашият индекс. Той се състои от една част – първото поле, което ще използваме, тип unsigned — положително цяло число. Доколкото помня от документацията, максималното число, което може да бъде – 18 квинтиллиона. Огромно.

След това можем да вмъкваме данни с помощта на командата insert.

unix/:/var/run/tarantool/example.control> box.space.example:insert{1, 'test1', 'test2'}
---
- [1, 'test1', 'test2']
...

unix/:/var/run/tarantool/example.control> box.space.example:insert{2, 'test2', 'test3', 'test4'}
---
- [2, 'test2', 'test3', 'test4']
...

unix/:/var/run/tarantool/example.control> box.space.example:insert{3, 'test3'}
---
- [3, 'test3']
...

unix/:/var/run/tarantool/example.control> box.space.example:insert{4, 'test4'}
---
- [4, 'test4']
...

unix/:/var/run/tarantool/example.control>

Първото поле се използва като първичен ключ, така че трябва да бъде уникално. Броят на колоните не е ограничен, така че можем да вмъкнем колкото искате данни. Те се посочват във формат MessagePack, който описах по-горе.

Извеждане на данни

След това можем да извеждаме данни с командата select.

Box.example.select с указание на ключа {1} ще извлече необходимата запис. Ако пропуснем ключа, ще видим всички записи, които имаме. Всички те са различни по брой колони, но тук принципно няма понятие за колони — има номера на полетата.

Данните може да бъдат абсолютно колкото искате. Например, ако ни трябва да ги търсим по второто поле. За целта правим нов вторичен индекс.


box.space.example:create_index( 'secondary', { type = 'TREE', unique = false, parts = {{field = 2, type ='string'} }}) 

Използваме командата Create_index.
Наричаме го Secondary.

След това трябва да посочим параметрите. Типът на индекса — TREE. Той може да не е уникален, затова въвеждаме Unique = false.

След това посочваме, от какви части се състои нашият индекс. Field — това е номерът на полето, към което свързваме индекса, и посочваме типа string. И ето, той е създаден.

unix/:/var/run/tarantool/example.control> box.space.example:create_index('secondary', { type = 'TREE', unique = false, parts = {{field = 2, type = 'string'}}})
---
- unique: false
  parts:
  - type: string
    is_nullable: false
    fieldno: 2
  id: 1
  space_id: 512
  type: TREE
  name: secondary
...

unix/:/var/run/tarantool/example.control>

Сега по този начин можем да го извикаме:

unix/:/var/run/tarantool/example.control> box.space.example.index.secondary:select('test1')
---
- - [1, 'test1', 'test2']
...

Запазване

Ако рестартираме инстанса и отново опитаме да извикаме данните — ще видим, че ги няма — всичко е празно. Това се случва, защото Tarantool прави чекпоинти и запазва данните на диск, но ако спрем работата преди ближайшото запазване, ще изгубим всички операции — защото ще се възстановим от последния чекпоинт, който е бил, например, преди два часа.

Не можем да запазваме всяка секунда — защото постоянното дампване на диск на 20 Гб е лоша идея.

За това е измислена и реализирана концепцията за write-ahead log. С нея за всяко изменение в данните се създава запис в малък файл write-ahead log.

Всеки запис до чекпоинта се запазва в тях. За тези файлове определяме размер — например, 64 MB. Когато файлът се запълни, записът започва да отива в втори файл. И след рестарта Tarantool се възстановява от последния чекпоинт и след това приложи всички по-късни транзакции до момента на спиране.

В Tarantool можете да комбинирате супербърза база данни и приложение за работа с нея. Ето как се прави лесно.

За да осъществим такова записване, трябва да зададем опция в настройките на box.cfg (в файла example.lua):

wal_mode = “write”;

Използване на данните

С това, което написахме сега, можете да използвате Тарантул за съхранение на данни, и той ще работи много бързо като база данни. А сега най-интересното – какво можем да правим с всичко това.

Пишем приложение

Например, ще напишем такова приложение за Тарантул

Приложението можете да видите под спойлера

box.cfg {
    listen = '0.0.0.0:3301';
    io_collect_interval = nil;
    readahead = 16320;
    memtx_memory = 128 * 1024 * 1024; -- 128Mb
    memtx_min_tuple_size = 16;
    memtx_max_tuple_size = 128 * 1024 * 1024; -- 128Mb
    vinyl_memory = 128 * 1024 * 1024; -- 128Mb
    vinyl_cache = 128 * 1024 * 1024; -- 128Mb
    vinyl_max_tuple_size = 128 * 1024 * 1024; -- 128Mb
    vinyl_write_threads = 2;
    wal_mode = "write";
    wal_max_size = 256 * 1024 * 1024;
    checkpoint_interval = 60 * 60; -- един час
    checkpoint_count = 6;
    force_recovery = true;
    log_level = 5;
    log_nonblock = false;
    too_long_threshold = 0.5;
    read_only   = false
}

local function bootstrap()
    local space = box.schema.create_space('example')
    space:create_index('primary')

    box.schema.user.create('example', { password = 'secret' })
    box.schema.user.grant('example', 'read,write,execute', 'space', 'example')

    box.schema.user.create('repl', { password = 'replication' })
    box.schema.user.grant('repl', 'replication')
end

-- за първоначално изпълнение създайте пространство и задайте права
box.once('replica', bootstrap)

-- активиране на достъп до конзолата
console = require('console')
console.listen('127.0.0.1:3302')

-- http конфигурация
local charset = {}  do -- [0-9a-zA-Z]
    for c = 48, 57  do table.insert(charset, string.char(c)) end
    for c = 65, 90  do table.insert(charset, string.char(c)) end
    for c = 97, 122 do table.insert(charset, string.char(c)) end
end

local function randomString(length)
    if not length or length <= 0 then return '' end
    math.randomseed(os.clock()^5)
    return randomString(length - 1) .. charset[math.random(1, #charset)]
end

local http_router = require('http.router')
local http_server = require('http.server')
local json = require('json')

local httpd = http_server.new('0.0.0.0', 8080, {
    log_requests = true,
    log_errors = true
})

local router = http_router.new()

local function get_count()
 local cnt = box.space.example:len()
 return cnt
end

router:route({method = 'GET', path = '\/count'}, function()
    return {status = 200, body = json.encode({count = get_count()})}
end)

router:route({method = 'GET', path = '\/token'}, function()
    local token = randomString(32)
    local last = box.space.example:len()
    box.space.example:insert{ last + 1, token }
    return {status = 200, body = json.encode({token = token})}
end)

prometheus = require('prometheus')

fiber = require('fiber')
tokens_count = prometheus.gauge("tarantool_tokens_count",
                              "Брой API токени")

function monitor_tokens_count()
  while true do
    tokens_count:set(get_count())
    fiber.sleep(5)
  end
end
fiber.create(monitor_tokens_count)

router:route( { method = 'GET', path = '\/metrics' }, prometheus.collect_http)

httpd:set_router(router)
httpd:start()

Обявяваме таблица в Lua, която определя символите. Тази таблица е необходима за генерирането на произволна низ.

local charset = {}  do -- [0-9a-zA-Z]
    for c = 48, 57  do table.insert(charset, string.char(c)) end
    for c = 65, 90  do table.insert(charset, string.char(c)) end
    for c = 97, 122 do table.insert(charset, string.char(c)) end
end

След това обявяваме функция – randomString и задаваме стойността на дължината в скобите.

local function randomString(length)
    if not length or length <= 0 then return '' end
    math.randomseed(os.clock()^5)
    return randomString(length - 1) .. charset[math.random(1, #charset)]
end

След това свързваме http роутера и http сървъра към нашия Tarantool сървър, JSON, който ще върнем на клиента.

local http_router = require('http.router')
local http_server = require('http.server')
local json = require('json')

След това стартираме http сървър на порт 8080 на всички интерфейси, който ще логва всички заявки и грешки.

local httpd = http_server.new('0.0.0.0', 8080, {
    log_requests = true,
    log_errors = true
})

След това обявяваме маршрут, че ако на порт 8080 /count бъде направена заявка с метод GET, то ние извикваме функция от един ред. Тя връща статус — 200, 404, 403 или всякакъв друг, който посочим.

router:route({method = 'GET', path = '/count'}, function()
    return {status = 200, body = json.encode({count = get_count()})}
end)

В тялото връщаме json.encode, в него посочваме count и getcount, която се извиква и показва броя записи в нашата база.

Втори метод

router:route({method = 'GET', path = '/token'}, function() 
    local token = randomString(32) 
    local last = box.space.example:len() 
    box.space.example:insert{ last + 1, token } 
    return {status = 200, body = json.encode({token = token})}
end)

Където в реда router:route({method = 'GET', path = '/token'}, function() ние извикваме функция и генерираме токен.

Редът local token = randomString(32) – това е случаен низ от 32 символа.
В реда local last = box.space.example:len() извличаме последния елемент.
А в реда box.space.example:insert{ last + 1, token } вписваме данни в нашата база, тоест просто увеличаваме ID на 1. Това може да се направи, между другото, не само по този не особенно елегантен начин. В Тарантула има секвенции за това.

Вписваме там токена.

По този начин написахме приложение в един файл. В него можем веднага да работим с данни, а модулът box ще свърши цялата мръсна работа за вас.

То слуша http и работи с данни, всичко е в един инстанс — както приложението, така и данните. Затова всичко става доста бързо.

За стартиране инсталираме http модула:

Как го правим, вижте под спойлера.

root@test2:⁄# tarantoolctl rocks install http
Инсталиране на http⁄rocks.tarantool.org⁄http-scm-1.src.rock
Липсват зависимости за http scm-1:
   checks >= 3.0.1 (не е инсталирано)

http scm-1 зависи от checks >= 3.0.1 (не е инсталирано)
Инсталиране на http⁄rocks.tarantool.org⁄checks-3.0.1-1.rockspec

Клониране в 'checks'...
remote: Изброяване на обекти: 28, готово.
remote: Броене на обекти: 100% (28⁄28), готово.
remote: Компресиране на обекти: 100% (19⁄19), готово.
remote: Общо 28 (delta 1), повторно използвани 16 (delta 1), pack-reused 0
Получаване на обекти: 100% (28⁄28), 12.69 KiB | 12.69 MiB⁄s, готово.
Решаване на делти: 100% (1⁄1), готово.
Забележка: проверка на '580388773ef11085015b5a06fe52d61acf16b201'.

Ти си в 'отделена HEAD' състояние. Можеш да разглеждаш, да правиш експериментални
промени и да ги комитваш, и можеш да отхвърлиш всички комити, които направиш в това
състояние, без да повлияеш на никакви клонове, като извършиш друга проверка.

Ако искаш да създадеш нов клон, за да запазиш комитите, които създаваш, можеш
да го направиш (сега или по-късно), като използваш -b с командата checkout отново. Пример:

  git checkout -b 

Няма съществуващ манифест. Опит за изграждане...
checks 3.0.1-1 в момента е инсталиран в ⁄.rocks (лиценз: BSD)

-- Идентификацията на C компилатора е GNU 7.5.0
-- Проверка за работещ C компилатор: ⁄usr⁄bin⁄cc
-- Проверка за работещ C компилатор: ⁄usr⁄bin⁄cc -- работи
-- Откриване на информация за C компилатора ABI
-- Откриване на информация за C компилатора ABI - готово
-- Откриване на функции за компилиране на C
-- Откриване на функции за компилиране на C - готово
-- Намерен TARANTOOL: ⁄usr⁄include (намерена версия "2.4.2-80-g18f2bc82d")
-- Tarantool LUADIR е ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lua
-- Tarantool LIBDIR е ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lib
-- Конфигуриране завършено
-- Генериране завършено
CMake Warning:
  Ръчно посочените променливи не бяха използвани от проекта:

    version


-- Файловете за компилиране са написани в: ⁄tmp⁄luarocks_http-scm-1-V4P9SM⁄http⁄build.luarocks
Сканиране на зависимости на цел httpd
[ 50%] Строене на C обект http⁄CMakeFiles⁄httpd.dir⁄lib.c.o
В файл включен от ⁄tmp⁄luarocks_http-scm-1-V4P9SM⁄http⁄http⁄lib.c:32:0:
⁄tmp⁄luarocks_http-scm-1-V4P9SM⁄http⁄http⁄lib.c: В функция ‘tpl_term’:
⁄usr⁄include⁄tarantool⁄lauxlib.h:144:15: warning: този израз може да премине [-Wimplicit-fallthrough=]
    (*(B)-p++ = (char)(c)))
    ~~~~~~~~~~~^~~~~~~~~~~~
⁄tmp⁄luarocks_http-scm-1-V4P9SM⁄http⁄http⁄lib.c:62:7: бележка: в разширението на макроса ‘luaL_addchar’
       luaL_addchar(b, '\');
       ^~~~~~~~~~~~
⁄tmp⁄luarocks_http-scm-1-V4P9SM⁄http⁄http⁄lib.c:63:6: бележка: тук
      по подразбиране:
      ^~~~~~~
В файл включен от ⁄tmp⁄luarocks_http-scm-1-V4P9SM⁄http⁄http⁄lib.c:39:0:
⁄tmp⁄luarocks_http-scm-1-V4P9SM⁄http⁄http⁄tpleval.h: В функция ‘tpe_parse’:
⁄tmp⁄luarocks_http-scm-1-V4P9SM⁄http⁄http⁄tpleval.h:147:9: warning: този израз може да премине [-Wimplicit-fallthrough=]
    type = TPE_TEXT;
    ~~~~~^~~~~~~~~~
⁄tmp⁄luarocks_http-scm-1-V4P9SM⁄http⁄http⁄tpleval.h:149:3: бележка: тук
   случай TPE_LINECODE:
   ^~~~
В файл включен от ⁄tmp⁄luarocks_http-scm-1-V4P9SM⁄http⁄http⁄lib.c:40:0:
⁄tmp⁄luarocks_http-scm-1-V4P9SM⁄http⁄http⁄httpfast.h: В функция ‘httpfast_parse’:
⁄tmp⁄luarocks_http-scm-1-V4P9SM⁄http⁄http⁄httpfast.h:372:22: warning: този израз може да премине [-Wimplicit-fallthrough=]
                 code = 0;
                 ~~~~~^~~
⁄tmp⁄luarocks_http-scm-1-V4P9SM⁄http⁄http⁄httpfast.h:374:13: бележка: тук
             случай status:
             ^~~~
⁄tmp⁄luarocks_http-scm-1-V4P9SM⁄http⁄http⁄httpfast.h:393:23: warning: този израз може да премине [-Wimplicit-fallthrough=]
                 state = message;
                 ~~~~~~^~~~~~~~~
⁄tmp⁄luarocks_http-scm-1-V4P9SM⁄http⁄http⁄httpfast.h:395:13: бележка: тук
             случай message:
             ^~~~
[100%] Линкване на C споделена библиотека lib.so
[100%] Построен цел httpd
[100%] Построен цел httpd
Инсталиране на проекта...
-- Инсталационна конфигурация: "Debug"
-- Инсталиране: ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lua⁄http⁄VERSION.lua
-- Инсталиране: ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lib⁄http⁄lib.so
-- Инсталиране: ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lua⁄http⁄server⁄init.lua
-- Инсталиране: ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lua⁄http⁄server⁄tsgi_adapter.lua
-- Инсталиране: ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lua⁄http⁄nginx_server⁄init.lua
-- Инсталиране: ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lua⁄http⁄router⁄init.lua
-- Инсталиране: ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lua⁄http⁄router⁄fs.lua
-- Инсталиране: ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lua⁄http⁄router⁄matching.lua
-- Инсталиране: ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lua⁄http⁄router⁄middleware.lua
-- Инсталиране: ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lua⁄http⁄router⁄request.lua
-- Инсталиране: ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lua⁄http⁄router⁄response.lua
-- Инсталиране: ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lua⁄http⁄tsgi.lua
-- Инсталиране: ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lua⁄http⁄utils.lua
-- Инсталиране: ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lua⁄http⁄mime_types.lua
-- Инсталиране: ⁄.rocks⁄share⁄tarantool⁄rocks⁄http⁄scm-1⁄lua⁄http⁄codes.lua
http scm-1 сега е инсталиран в ⁄.rocks (лиценз: BSD)

root@test2:⁄#

Също така, за стартиране ни е необходим prometheus:

root@test2:/# tarantoolctl rocks install prometheus
Installing http://rocks.tarantool.org/prometheus-scm-1.rockspec

Cloning into 'prometheus'...
remote: Enumerating objects: 19, done.
remote: Counting objects: 100% (19/19), done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 19 (delta 2), reused 5 (delta 0), pack-reused 0
Receiving objects: 100% (19/19), 10.73 KiB | 10.73 MiB/s, done.
Resolving deltas: 100% (2/2), done.
prometheus scm-1 is now installed in /.rocks (license: BSD)

root@test2:/#

Стартираме и можем да се свързваме с модулите

root@test2:/# curl -D - -s http://127.0.0.1:8080/token
HTTP/1.1 200 Ok
Content-length: 44
Server: Tarantool http (tarantool v2.4.2-80-g18f2bc82d)
Connection: keep-alive

{"token":"e2tPq9l5Z3QZrewRf6uuoJUl3lJgSLOI"}

root@test2:/# curl -D - -s http://127.0.0.1:8080/token
HTTP/1.1 200 Ok
Content-length: 44
Server: Tarantool http (tarantool v2.4.2-80-g18f2bc82d)
Connection: keep-alive

{"token":"fR5aCA84gj9eZI3gJcV0LEDl9XZAG2Iu"}

root@test2:/# curl -D - -s http://127.0.0.1:8080/count
HTTP/1.1 200 Ok
Content-length: 11
Server: Tarantool http (tarantool v2.4.2-80-g18f2bc82d)
Connection: keep-alive

{"count":2}root@test2:/#

/count отдает нам статус 200.
/token выдает токен и делает запись этого токена в базу.

Тестуваме скоростта

Нека стартираме бенчмарк за 50 000 заявки. Конкуренцията ще е 500 едновременно.

root@test2:/# ab -c 500 -n 50000 http://127.0.0.1:8080/token
This is ApacheBench, Version 2.3 
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)
Completed 5000 requests
Completed 10000 requests
Completed 15000 requests
Completed 20000 requests
Completed 25000 requests
Completed 30000 requests
Completed 35000 requests
Completed 40000 requests
Completed 45000 requests
Completed 50000 requests
Finished 50000 requests


Server Software:        Tarantool
Server Hostname:        127.0.0.1
Server Port:            8080

Document Path:          /token
Document Length:        44 bytes

Concurrency Level:      500
Time taken for tests:   14.578 seconds
Complete requests:      50000
Failed requests:        0
Total transferred:      7950000 bytes
HTML transferred:       2200000 bytes
Requests per second:    3429.87 [#/sec] (mean)
Time per request:       145.778 [ms] (mean)
Time per request:       0.292 [ms] (mean, across all concurrent requests)
Transfer rate:          532.57 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   10 103.2      0    3048
Processing:    12   69 685.1     15   13538
Waiting:       12   69 685.1     15   13538
Total:         12   78 768.2     15   14573

Percentage of the requests served within a certain time (ms)
  50%     15
  66%     15
  75%     16
  80%     16
  90%     16
  95%     16
  98%     21
  99%     42
 100%  14573 (longest request)
root@test2:/#

Токените се издават. И постоянно записваме данни. 99% от заявките се обработват за 42 милисекунди. Следователно, имаме около 3500 заявки в секунда на малка машина с 2 ядра и 4 гигабайта памет.

Също така можете да изберете произволен 50000-токен и да видите неговата стойност.

Можете да използвате не само http, а и да стартирате фонови функции, които обработват вашите данни. Освен това, има различни тригери. Например, можете да извиквате функции при актуализации, да проверявате нещо – да разрешавате конфликти.

Можете да пишете приложения-скриптове директно в самия сървър на базата данни и да нямате ограничения, да свързвате всякакви модули и да реализирате всяка логика.

Приложният сървър може да се свързва с външни сървъри, да извлича данни и да ги съхранява в своята база. Данните от тази база ще използват други приложения.

Това ще се направи от самия Тарантул и не е необходимо да се пише отделно приложение.

В заключение

Това е само първата част от голямата работа. Втората ще бъде публикувана съвсем скоро в блога на Mail.ru Group и ние непременно ще добавим линк към нея в този материал.

Ако ви интересува да участвате в събития, където създаваме такива неща онлайн и да задавате въпроси в реално време, присъединете се към канала DevOps by REBRAIN.

Ако ви е нужен преход към облака или имате въпроси относно вашата инфраструктура, смело оставяйте заявка.

P.S. Имаме 2 безплатни одита на месец, възможно е точно вашият проект да е в техния списък.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster