У Tarantool можна сумясціць суперхуткі базу дадзеных і прыкладанне для працы з імі. Вось як проста гэта робіцца

Пяць гадоў таму я паспрабаваў працаваць з Tarantool, але тады ен мне не зайшоў. Але нядаўна я праводзіў вэбінар, дзе расказваў пра Hadoop, пра тое, як працуе MapReduce. Там мне задалі пытанне – "А чаму пад гэтую задачу не выкарыстоўваць Tarantool?".

Дзеля цікаўнасці я вырашыў вярнуцца да яго, пратэставаць апошнюю версію - і на гэты раз праект мне вельмі спадабаўся. Цяпер я пакажу, як напісаць у Tarantool простае дадатак, нагружаю яго і праверу прадукцыйнасць, і вы ўбачыце, як там усё лёгка і крута.

У Tarantool можна сумясціць суперхуткі базу дадзеных і прыкладанне для працы з імі. Вось як проста гэта робіцца

Што такое Tarantool

Tarantool пазіцыянуе сябе як звышхуткая БД. Туды можна штурхаць любыя дадзеныя, якія захочаце. Плюс, рэплікаваць іх, шаліць - гэта значыць разбіваць велізарную колькасць дадзеных па некалькіх серверам і аб'ядноўваць з іх вынікі - рабіць адмоваўстойлівыя звязкі тыпу «майстар-майстар».

У другую чаргу, гэта application-сервер. Вы можаце пісаць на ім свае прыкладанні, працаваць з дадзенымі, напрыклад, выдаляць у фоне старыя запісы па пэўных правілах. Можна напісаць прама ў Тарантуле Http-сервер, які будзе працаваць з дадзенымі: выдаваць іх колькасць, запісваць туды новыя дадзеныя і рэдукаваць гэта ўсё на майстра.

Я чытаў артыкул, як хлопцы зрабілі чаргу паведамленняў на 300 радкоў, якое проста рве і кідае – у іх мінімальная прадукцыйнасць ад 20 000 паведамленняў у секунду. Тут можна сапраўды разгарнуцца і напісаць вельмі вялікае дадатак, і гэта будуць не захоўвамкі, як у PostgreS.

Прыкладна такі сервер, толькі просты, я і паспрабую апісаць у гэтым артыкуле.

Ўстаноўка

Для тэсту я завёў тры стандартныя віртуальныя машыны жорсткі дыск на 20 гігабайт, Ubuntu 18.04/2. 4 віртуал CPU і XNUMX гіга памяці.

Мы ставім Tarantool - запускаем вежавы скрыпт або дадаем рэпазітар і робім apt get install Tarantool. Спасылка на скрыпт - (curl -L https://tarantool.io/installer.sh | VER = 2.4 sudo -E bash). У нас нас з'яўляюцца такія каманды, як:

tarantoolctl - Асноўная каманда для кіравання інстансамі Тарантула.
/etc/tarantool - тут ляжыць уся канфігурацыя.
var/log/tarantool - тут ляжаць логі.
var/lib/tarantool - тут ляжаць дадзеныя, і далей яны разбітыя па інстанс.

Ёсць тэчкі instance-available і instance-enable - у ёй знаходзіцца тое, што будзе запускацца - файл канфігурацыі інстанса з lua кодам, дзе апісана, на якіх партах ён слухае, якая памяць яму даступная, налады рухавічка Vinyl, код, які спрацоўвае пры старце сервера, шардзіраванне, чэргі, выдаленне састарэлых дадзеных і гэтак далей.

Інстансы працуюць як у PostgreS. Напрыклад, вы хочаце запусціць некалькі копій базы дадзеных, якая вісіць на розных партах. Атрымліваецца, на адным серверы запускаюцца некалькі інстансаў баз дадзеных, якія вісяць на розных партах. У іх могуць абсалютна розныя налады - адзін інстанс рэалізуе адну логіку, другі - іншую.

Кіраванне інстансамі

У нас ёсць каманда tarantoolctl, якая дазваляе кіраваць інстанс Тарантула. Напрыклад, tarantoolctl check example праверыць файл з канфігурацыяй і скажа - файл is ok, калі там няма ніякіх сінтаксічных памылак.

Можна паглядзець статус інстансу - tarantoolctl status example. Такой жа выявай можна рабіць start, stop, restart.

Калі instance запушчаны, да яго можна падлучыцца двума спосабамі.

1. Адміністрацыйная кансоль

Па змаўчанні Tarantool адчыняе сокет, тамака перадаецца звычайны ASCII-тэкст для кіравання Тарантулам. Падлучэнне да кансолі адбываецца заўсёды пад карыстачом admin, тамака няма аўтэнтыфікацыі, таму выносіць кансольны порт для кіравання Тарантулам па-за не трэба.

Для падлучэння гэтым спосабам трэба ўвесці Tarantoolctl enter instance name. Каманда запусціць кансоль і падключыцца пад карыстачом admin. Ніколі не выстаўляйце кансольны порт вонкі - лепш пакінуць яго юнітсокет. Тады магчымасць падключыцца да Тарантул будзе толькі ў тых, у каго ёсць доступ да запісу ў сокет.

Гэты спосаб патрэбен для адміністрацыйных рэчаў. Для працы з дадзенымі выкарыстоўвайце другі спосаб - бінарны пратакол.

2. Выкарыстанне бінарнага пратакола для падлучэння да вызначанага порта

У канфігурацыі ёсць дырэктыва listen, якая адчыняе порт для вонкавых камунікацый. Гэты порт выкарыстоўваецца з бінарным пратаколам, і там уключана аўтэнтыфікацыя.

Для гэтага падлучэння выкарыстоўваецца tarantoolctl connect to port number. Выкарыстоўваючы яе, можна падлучацца да выдаленых сервераў, выкарыстоўваць аўтэнтыфікацыю і даваць розныя правы доступу.

Запіс дадзеных і модуль Box

Бо Tarantool з'яўляецца і базай дадзеных, і application-серверам, у ім ёсць розныя модулі. Нас цікавіць модуль 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')

    -- Keep things safe by default
    --  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 захоўвае дадзеныя на дыску ў больш звыклым нам выглядзе - гэта значыць можна захоўваць больш дадзеных, чым у нас ёсць памяці, і Тарантул будзе чытаць іх з дыска.

Цяпер мы будзем выкарыстоўваць 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 мб. Калі ён запаўняецца, запіс пачынае ісці ў другі файл. І пасля рэстарту 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; -- one hour
    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

-- for first run create a space and add set up grants
box.once('replica', bootstrap)

-- enabling console access
console = require('console')
console.listen('127.0.0.1:3302')

-- http config
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 Tokens Count")

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-сервер у наш Тарантул-сервер, JSON, якія будзем аддаваць кліенту.

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

Пасля гэтага стартуем на порце 8080 на ўсіх інтэрфейсах http server, які будзе лагіраваць усе запыты і памылкі.

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

Далей мы аб'яўляем route, што калі на порт 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
Installing http://rocks.tarantool.org/http-scm-1.src.rock
Missing dependencies for http scm-1:
   checks >= 3.0.1 (not installed)

http scm-1 depends on checks >= 3.0.1 (not installed)
Installing http://rocks.tarantool.org/checks-3.0.1-1.rockspec

Cloning into 'checks'...
remote: Enumerating objects: 28, done.
remote: Counting objects: 100% (28/28), done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 28 (delta 1), reused 16 (delta 1), pack-reused 0
Receiving objects: 100% (28/28), 12.69 KiB | 12.69 MiB/s, done.
Resolving deltas: 100% (1/1), done.
Note: checking out '580388773ef11085015b5a06fe52d61acf16b201'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

No existing manifest. Attempting to rebuild...
checks 3.0.1-1 is now installed in /.rocks (license: BSD)

-- The C compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Found TARANTOOL: /usr/include (found version "2.4.2-80-g18f2bc82d")
-- Tarantool LUADIR is /.rocks/share/tarantool/rocks/http/scm-1/lua
-- Tarantool LIBDIR is /.rocks/share/tarantool/rocks/http/scm-1/lib
-- Configuring done
-- Generating done
CMake Warning:
  Manually-specified variables were not used by the project:

    version


-- Build files have been written to: /tmp/luarocks_http-scm-1-V4P9SM/http/build.luarocks
Scanning dependencies of target httpd
[ 50%] Building C object http/CMakeFiles/httpd.dir/lib.c.o
In file included from /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:32:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c: In function ‘tpl_term’:
/usr/include/tarantool/lauxlib.h:144:15: warning: this statement may fall through [-Wimplicit-fallthrough=]
    (*(B)->p++ = (char)(c)))
    ~~~~~~~~~~~^~~~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:62:7: note: in expansion of macro ‘luaL_addchar’
       luaL_addchar(b, '\');
       ^~~~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:63:6: note: here
      default:
      ^~~~~~~
In file included from /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:39:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h: In function ‘tpe_parse’:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h:147:9: warning: this statement may fall through [-Wimplicit-fallthrough=]
    type = TPE_TEXT;
    ~~~~~^~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h:149:3: note: here
   case TPE_LINECODE:
   ^~~~
In file included from /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:40:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h: In function ‘httpfast_parse’:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:372:22: warning: this statement may fall through [-Wimplicit-fallthrough=]
                 code = 0;
                 ~~~~~^~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:374:13: note: here
             case status:
             ^~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:393:23: warning: this statement may fall through [-Wimplicit-fallthrough=]
                 state = message;
                 ~~~~~~^~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:395:13: note: here
             case message:
             ^~~~
[100%] Linking C shared library lib.so
[100%] Built target httpd
[100%] Built target httpd
Install the project...
-- Install configuration: "Debug"
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/VERSION.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lib/http/lib.so
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/server/init.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/server/tsgi_adapter.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/nginx_server/init.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/init.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/fs.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/matching.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/middleware.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/request.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/response.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/tsgi.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/utils.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/mime_types.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/codes.lua
http scm-1 is now installed in /.rocks (license: 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 <$Revision: 1807734 $>
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.

Калі вам патрэбен пераезд у воблака ці ёсць пытанні па вашай інфраструктуры, смела пакідайце заяўку.

PS У нас ёсць 2 бясплатных аўдыту ў месяц, магчыма, менавіта ваш праект будзе ў іх ліку.

Крыніца: habr.com

Дадаць каментар