În Tarantool poți combina o bază de date super rapidă cu o aplicație pentru a lucra cu aceasta. Iată cât de simplu este să faci asta

Acum cinci ani am încercat să lucrez cu Tarantool, dar nu m-a convins pe atunci. Recent, am susținut un webinar unde am vorbit despre Hadoop și despre cum funcționează MapReduce. Acolo mi s-a pus întrebarea - „De ce nu folosiți Tarantool pentru această sarcină?”.

Din curiozitate, am decis să mă întorc la el, să testez ultima versiune - și de data aceasta proiectul mi-a plăcut foarte mult. Acum vă voi arăta cum să scrieți o aplicație simplă în Tarantool, să o încarc și să verific performanța, și veți vedea cât de simplu și grozav este totul.

În Tarantool poți combina o bază de date super rapidă cu o aplicație pentru a lucra cu aceasta. Iată cât de simplu este să faci asta

Ce este Tarantool

Tarantool se poziționează ca o bază de date extrem de rapidă. Puteți introduce orice fel de date doriți. În plus, le puteți replica, shardui - adică să împărțiți o cantitate uriașă de date pe mai multe servere și să combinați rezultatele de pe acestea - să creați combinații reziliente tip „master-master”.

În al doilea rând, este un server de aplicații. Puteți scrie aplicațiile dvs. pe el, lucra cu datele, de exemplu, să ștergeți în fundal înregistrările vechi conform unor reguli specifice. Puteți scrie direct în Tarantool un server Http care va lucra cu datele: va returna numărul acestora, va înregistra date noi și va reduce totul pe master.

Am citit un articol despre cum au realizat un sistem de mesagerie pe 300 de linii, care pur și simplu răstoarnă tot - au o performanță minimă de 20.000 de mesaje pe secundă. Aici se poate chiar dezvolta și scrie o aplicație foarte mare, care nu va fi ca în stocările din PostgreS.

Un server aproximativ de acest fel, doar simplificat, voi încerca să descriu în acest articol.

Instalare

Pentru test, am creat trei mașini virtuale standard - hard disk de 20 de gigaocteți, Ubuntu 18.04. 2 CPU virtuali și 4 giga de memorie.

Instalăm Tarantool - lansăm un script bash sau adăugăm depozitul și facem apt get install Tarantool. Linkul pentru script - (curl -L https://tarantool.io/installer.sh | VER=2.4 sudo -E bash). Ne apar comenzi precum:

tarantoolctl — comanda principală pentru gestionarea instanțelor de Tarantool.
/etc/tarantool — aici se află toată configurația.
var/log/tarantool — aici se află jurnalul.
var/lib/tarantool — aici se află datele, și mai departe sunt împărțite pe instanțe.

Există foldere instance-available și instance-enable — în acestea se află ceea ce va fi pornit — fișierul de configurare a instanței cu cod lua, care descrie pe ce porturi ascultă, ce memorie are disponibilă, setările motorului Vinyl, codul care se execută la pornirea serverului, shard-urile, coadă, eliminarea datelor vechi și așa mai departe.

Instanțele funcționează ca în PostgreS. De exemplu, doriți să porniți mai multe copiilor ale unei baze de date, care rulează pe porturi diferite. Astfel, pe un singur server sunt pornite mai multe instanțe de baze de date, care rulează pe porturi diferite. Acestea pot avea setări complet diferite — o instanță implementează o logică, iar cealaltă — alta.

Gestionarea instanțelor

Avem comanda tarantoolctl, care permite gestionarea instanțelor Tarantool. De exemplu, tarantoolctl check example va verifica fișierul de configurare și va spune — fișierul este ok, dacă nu există erori de sintaxă.

Se poate verifica starea instanței — tarantoolctl status example. În același mod se pot face start, stop, restart.

Când instanța este pornită, vă puteți conecta în două moduri.

1. Consola administrativă

În mod implicit, Tarantool deschide un socket, unde se transmite text ASCII obișnuit pentru gestionarea Tarantool-ului. Conexiunea la consolă se face întotdeauna sub utilizatorul admin, nu există autentificare, așa că nu trebuie să expuneți portul consolei pentru a gestiona Tarantool-ul.

Pentru a vă conecta prin acest mod, trebuie să introduceți Tarantoolctl enter instance name. Comanda va porni consola și se va conecta sub utilizatorul admin. Nu expuneți niciodată portul consolei în exterior — este mai bine să-l lăsați unit-socket. Atunci, posibilitatea de a se conecta la Tarantool va fi doar pentru cei care au acces la scriere pe socket.

Această metodă este destinată pentru lucruri administrative. Pentru a lucra cu date, utilizați a doua metodă — protocolul binar.

2. Utilizarea protocolului binar pentru a vă conecta la un port specific

În configurație există o directivă listen, care deschide un port pentru comunicații externe. Acest port este folosit cu protocolul binar, iar autentificarea este activată.

Pentru această conexiune se folosește tarantoolctl connect to port number. Folosind-o, vă puteți conecta la servere externe, utiliza autentificarea și acorda diferite drepturi de acces.

Scrierea datelor și modul Box

Deoarece Tarantool este atât o bază de date, cât și un server de aplicații, acesta are diferite module. Ne interesează modulul box — care implementează lucrul cu datele. Atunci când scrieți ceva în box, Tarantool scrie datele pe disc, le păstrează în memorie sau face altceva cu ele.

Scriere

De exemplu, intrăm în modulul box și apelăm funcția box.once. Aceasta va forța Tarantool să ruleze codul nostru la inițializarea serverului. Creăm un spațiu în care vor fi stocate datele noastre.

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

    -- Păstrează lucrurile în siguranță prin 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

După aceasta, creăm un index primar – primary – după care vom putea căuta date. Implicit, dacă nu se specifică alți parametri, se va folosi primul câmp din fiecare înregistrare pentru indexul primar.

Apoi, acordăm drepturi utilizatorului guest, cu care ne conectăm prin protocolul binar. Permitem citirea, scrierea și executarea în întreaga instanță.

Comparativ cu bazele de date obișnuite, aici totul este destul de simplu. Avem un spațiu – o zonă în care sunt stocate datele noastre. Fiecare înregistrare se numește tuplu. Este ambalată în MessagePack. Acesta este un format foarte interesant — este binar și ocupă mai puțin spațiu – 18 bytes față de 27.

În Tarantool poți combina o bază de date super rapidă cu o aplicație pentru a lucra cu aceasta. Iată cât de simplu este să faci asta

Este destul de ușor de lucrat cu el. Aproape fiecare linie, fiecare înregistrare de date poate avea coloane absolut diferite.

Toate spațiile le putem vizualiza folosind comanda Box.space. Pentru a evidenția o instanță specifică – scriem box.space example și obținem informații complete despre aceasta.

În Tarantool sunt încorporate două tipuri de motoare: Memory și Vinyl. Memory păstrează toate datele în memorie. De aceea, totul funcționează simplu și rapid. Datele sunt salvate pe disc, iar există și un mecanism de jurnal de scriere anticipată, așa că nu vom pierde nimic în caz de cădere a serverului.

Vinyl stochează datele pe disc într-o formă mai familiară pentru noi — adică putem stoca mai multe date decât avem memorie, iar Tarantool le va citi de pe disc.

Acum vom folosi 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>

Index:

Trebuie să creăm un index primar pentru orice spațiu, deoarece fără el nimic nu va funcționa. La fel ca în orice bază de date, creăm primul câmp – ID-ul înregistrării.

Părți:

Aici specificăm din ce constă indexul nostru. Acesta constă dintr-o singură parte – primul câmp pe care îl vom folosi, de tip unsigned — număr întreg pozitiv. Din câte îmi amintesc din documentație, numărul maxim care poate fi utilizat este de 18 quintilioane. Foarte mult.

Apoi putem insera date folosind comanda 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>

Primul câmp este folosit ca cheie primară, deci trebuie să fie unic. Nu există o limită a numărului de coloane, astfel că putem insera cât mai multe date dorim. Acestea sunt specificate în format MessagePack, pe care l-am descris mai sus.

Afișarea datelor

Apoi putem afișa datele folosind comanda select.

Box.example.select specificând cheia {1} va returna înregistrarea corectă. Dacă omitem cheia, vom vedea toate înregistrările pe care le avem. Acestea diferă în funcție de numărul coloanelor, dar în principiu nu există noțiunea de coloane – există numere de câmp.

Pot exista absolut oricât de multe date. De exemplu, dacă trebuie să le căutăm după al doilea câmp. În acest caz, facem un nou index secundar.


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

Folosim comanda Create_index.
Îi dăm numele Secondary.

După aceea, trebuie să specificăm parametrii. Tipul indexului — TREE. Acesta poate să nu fie unic, așa că introducem Unique = false.

Apoi specificăm din ce părți constă indexul nostru. Field — este numărul câmpului la care legăm indexul, și specificăm tipul string. Și iată că s-a creat.

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>

Acum putem să-l apelăm în acest mod:

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

Salvare

Dacă restartăm instanța și încercăm din nou să apelăm datele, vom vedea că acestea nu sunt disponibile — totul e gol. Acest lucru se întâmplă deoarece Tarantool face checkpoint-uri și salvează datele pe disc, dar dacă oprim funcționarea înainte de cea mai recentă salvare, pierdem toate operațiile — deoarece ne vom restaura de la ultimul checkpoint, care a fost, de exemplu, cu două ore în urmă.

Să salvăm în fiecare secundă nu va funcționa — deoarece a scurge constant 20 GB pe disc este o idee proastă.

Pentru aceasta a fost inventată și implementată concepția de write-ahead log. Cu ajutorul acesteia, pentru fiecare modificare a datelor se creează o înregistrare într-un mic fișier write-ahead log.

Fiecare înregistrare înainte de checkpoint este salvată în ele. Pentru aceste fișiere stabilim o dimensiune — de exemplu, 64 MB. Când acesta se umple, înregistrarea începe să se scrie în al doilea fișier. Și după restart, Tarantool se restaurează din ultimul checkpoint și apoi aplică toate tranzacțiile ulterioare până la momentul opririi.

În Tarantool poți combina o bază de date super rapidă cu o aplicație pentru a lucra cu aceasta. Iată cât de simplu este să faci asta

Pentru a realiza o astfel de înregistrare, trebuie să specificați o opțiune în setările box.cfg (în fișierul example.lua):

wal_mode = “write”;

Utilizarea datelor

Cu ceea ce am scris acum, puteți folosi Tarantool pentru a stoca date și va funcționa foarte rapid ca bază de date. Și acum, cireșa de pe tort – ce puteți face cu tot ceea ce există.

Scriem o aplicație

De exemplu, să scriem o aplicație pentru Tarantool

Aplicația poate fi vizualizată sub spoiler

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; -- o oră
    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

-- pentru prima rulare se creează un spațiu și se adaugă permisiuni
box.once('replica', bootstrap)

-- activarea accesului la consolă
console = require('console')
console.listen('127.0.0.1:3302')

-- configurația 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",
                              "Numărul de Token-uri 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()

Declarăm o tabelă în lua, care definește caracterele. Această tabelă este necesară pentru generarea unei șiruri aleatorii.

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

După aceea, declarem funcția – randomString și îi vom atribui în paranteză valoarea lungimii.

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

Apoi conectăm http-router-ul și serverul http la serverul nostru Tarantool, JSON-ul pe care îl vom trimite clientului.

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

După aceasta, pornim un server http pe portul 8080 pe toate interfețele, care va înregistra toate cererile și erorile.

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

Apoi, declarăm un route, astfel încât dacă pe portul 8080 /count vine o cerere cu metoda GET, vom apela o funcție de o linie. Aceasta returnează un status — 200, 404, 403 sau orice altul, pe care îl specificăm.

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

În corp, returnăm json.encode, în care specificăm count și get_count, care este apelată și arată numărul de înregistrări din baza noastră de date.

A doua metodă

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)

Unde în linia router:route({method = ‘GET’, path = ‘\/token’}, function() apelăm o funcție și generăm un token.

Șirul local token = randomString(32) – aceasta este un string aleatoriu de 32 de caractere.
În rândul local last = box.space.example:len() extragem ultimul element.
Iar în linia box.space.example:insert{ last + 1, token } înregistrăm datele în baza noastră, adică pur și simplu creștem ID-ul cu 1. Acest lucru se poate face, de altfel, nu doar într-un mod atât de incomod. În Tarantula sunt secvențe pentru aceasta.

Înscriem acolo token-ul.

Astfel, am scris o aplicație într-un singur fișier. În aceasta se poate interacționa cu datele, iar modulul box va face toată munca murdară pentru tine.

Ea ascultă http și lucrează cu datele, totul se află într-o singură instanță — atât aplicația, cât și datele. De aceea, totul se desfășoară destul de rapid.

Pentru a porni, instalăm modulul http:

Cum o facem, vedeți sub spoiler.

root@test2: /# tarantoolctl rocks install http
Instalare http://rocks.tarantool.org/http-scm-1.src.rock
Lipsesc dependențe pentru http scm-1:
   checks >= 3.0.1 (neinstalat)

http scm-1 depinde de checks >= 3.0.1 (neinstalat)
Instalare http://rocks.tarantool.org/checks-3.0.1-1.rockspec

Clonare în 'checks'...
remote: Enumerarea obiectelor: 28, finalizat.
remote: Numărarea obiectelor: 100% (28/28), finalizat.
remote: Comprimarea obiectelor: 100% (19/19), finalizat.
remote: Total 28 (delta 1), reutilizat 16 (delta 1), pachet reutilizat: 0
Primirea obiectelor: 100% (28/28), 12.69 KiB | 12.69 MiB/s, finalizat.
Rezolvarea delta-urilor: 100% (1/1), finalizat.
Notă: verificând '580388773ef11085015b5a06fe52d61acf16b201'.

Te afli în starea 'HEAD detașat'. Poți explora, efectua modificări experimentale
și le poți salva, iar orice comit pe care îl faci în această
stare poate fi șters fără a afecta branch-urile printr-un alt checkout.

Dacă vrei să creezi un nou branch pentru a păstra comitele pe care le creezi, poți
asta (acum sau mai târziu) prin utilizarea -b cu comanda checkout din nou. Exemplu:

  git checkout -b 

Nu există un manifest existent. Încercăm să reconstruim...
checks 3.0.1-1 este acum instalat în /.rocks (licență: BSD)

-- Identificarea compilatorului C este GNU 7.5.0
-- Verificare pentru compilator C funcțional: /usr/bin/cc
-- Verificare pentru compilator C funcțional: /usr/bin/cc -- funcționează
-- Detectarea informațiilor ABI pentru compilator C
-- Detectarea informațiilor ABI pentru compilator C - finalizat
-- Detectarea caracteristicilor de compilare C
-- Detectarea caracteristicilor de compilare C - finalizat
-- Am găsit TARANTOOL: /usr/include (versiune găsită "2.4.2-80-g18f2bc82d")
-- Tarantool LUADIR este /.rocks/share/tarantool/rocks/http/scm-1/lua
-- Tarantool LIBDIR este /.rocks/share/tarantool/rocks/http/scm-1/lib
-- Configurarea a fost finalizată
-- Generarea a fost finalizată
Avertizare CMake:
  Variabilele specificate manual nu au fost utilizate de proiect:

    version


-- Fișierele de construire au fost scrise în: /tmp/luarocks_http-scm-1-V4P9SM/http/build.luarocks
Să scanăm dependențele țintei httpd
[ 50%] Crearea obiectului C http/CMakeFiles/httpd.dir/lib.c.o
În fișierul inclus din /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:32:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c: În funcția 'tpl_term':
/usr/include/tarantool/lauxlib.h:144:15: avertizare: această declarație poate trece [-Wimplicit-fallthrough=]
    (*(B)->p++ = (char)(c)))
    ~~~~~~~~~~~^~~~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:62:7: notă: în expansiunea macro-ului 'luaL_addchar'
       luaL_addchar(b, '\');
       ^~~~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:63:6: notă: aici
      default:
      ^~~~~~~
În fișierul inclus din /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:39:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h: În funcția 'tpe_parse':
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h:147:9: avertizare: această declarație poate trece [-Wimplicit-fallthrough=]
    type = TPE_TEXT;
    ~~~~~^~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h:149:3: notă: aici
   case TPE_LINECODE:
   ^~~~
În fișierul inclus din /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:40:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h: În funcția 'httpfast_parse':
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:372:22: avertizare: această declarație poate trece [-Wimplicit-fallthrough=]
                 code = 0;
                 ~~~~~^~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:374:13: notă: aici
             case status:
             ^~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:393:23: avertizare: această declarație poate trece [-Wimplicit-fallthrough=]
                 state = message;
                 ~~~~~~^~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:395:13: notă: aici
             case message:
             ^~~~
[100%] Legarea bibliotecii partajate C lib.so
[100%] Ținta httpd construită
[100%] Ținta httpd construită
Instalați proiectul...
-- Configurația instalării: "Debug"
-- Instalare: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/VERSION.lua
-- Instalare: /.rocks/share/tarantool/rocks/http/scm-1/lib/http/lib.so
-- Instalare: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/server/init.lua
-- Instalare: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/server/tsgi_adapter.lua
-- Instalare: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/nginx_server/init.lua
-- Instalare: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/init.lua
-- Instalare: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/fs.lua
-- Instalare: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/matching.lua
-- Instalare: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/middleware.lua
-- Instalare: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/request.lua
-- Instalare: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/response.lua
-- Instalare: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/tsgi.lua
-- Instalare: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/utils.lua
-- Instalare: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/mime_types.lua
-- Instalare: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/codes.lua
http scm-1 este acum instalat în /.rocks (licență: BSD)

root@test2: /#

De asemenea, pentru a rula avem nevoie de prometheus:

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

Clonare în '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.
Rezolvarea deltazilor: 100% (2/2), done.
prometheus scm-1 este acum instalat în /.rocks (licență: BSD)

root@test2:~#

Începem și putem să ne referim la module

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 выдает токен и делает запись этого токена в базу.

Testăm viteza

Hai să lansăm un benchmark pentru 50.000 de cereri. Cererile concurente vor fi 500.

root@test2:~# ab -c 500 -n 50000 http://127.0.0.1:8080/token
Aceasta este ApacheBench, Versiunea 2.3 
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licențiat către Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (fii răbdător)
Finalizat 5000 cereri
Finalizat 10000 cereri
Finalizat 15000 cereri
Finalizat 20000 cereri
Finalizat 25000 cereri
Finalizat 30000 cereri
Finalizat 35000 cereri
Finalizat 40000 cereri
Finalizat 45000 cereri
Finalizat 50000 cereri
Finalizat 50000 cereri


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

Calea Documentului:          /token
Lungimea Documentului:        44 bytes

Nivel Concurență:      500
Timp necesar pentru teste:   14.578 secunde
Cereri complete:      50000
Cereri eșuate:        0
Total transferat:      7950000 bytes
HTML transferat:       2200000 bytes
Cereri pe secundă:    3429.87 [#/sec] (medie)
Timp pe cerere:       145.778 [ms] (medie)
Timp pe cerere:       0.292 [ms] (medie, pentru toate cererile concurente)
Rată de transfer:          532.57 [Kbytes/sec] primite

Timpuri de Conexiune (ms)
              min  medie[+/-sd] median   max
Conectare:        0   10 103.2      0    3048
Procesare:    12   69 685.1     15   13538
Așteptare:       12   69 685.1     15   13538
Total:         12   78 768.2     15   14573

Procentajul cererilor servite într-un anumit timp (ms)
  50%     15
  66%     15
  75%     16
  80%     16
  90%     16
  95%     16
  98%     21
  99%     42
 100%  14573 (cea mai lungă cerere)
root@test2:~#

Tokenurile sunt emise. Și noi continuăm să scriem datele. 99% din cereri au fost procesate în 42 de milisecunde. Astfel, avem aproximativ 3500 de cereri pe secundă pe o mașină mică, cu 2 nuclee și 4 gigabytes de memorie.

De asemenea, se poate selecta un token de 50000 și verifica valoarea acestuia.

Nu se poate folosi doar http, ci se pot rula funcții în fundal care prelucrează datele. De asemenea, există diverse trigger-uri. De exemplu, poți apela funcții la actualizări, pentru a verifica ceva - pentru a rezolva conflicte.

Puteți scrie aplicații-script direct pe serverul bazei de date, fără nicio restricție, conectând orice module și implementând orice logică.

Serverul de aplicații poate accesa servere externe, extrăgând date și stocându-le în baza sa de date. Acele date vor fi folosite de alte aplicații.

Aceasta va fi realizat de Tarantool, fără a fi nevoie să scrieți o aplicație separată.

În concluzie

Aceasta este doar prima parte a unei lucrări mari. Partea a doua va fi publicată foarte curând pe blogul Mail.ru Group, iar noi vom adăuga cu siguranță un link către aceasta în acest material.

Dacă sunteți interesat să participați la evenimente unde creăm astfel de lucruri online și să adresați întrebări în timp real, conectați-vă la canalul DevOps by REBRAIN.

Dacă aveți nevoie de migrare în cloud sau aveți întrebări despre infrastructura dumneavoastră, nu ezitați să lăsați o cerere.

P.S. Avem 2 audituri gratuite pe lună, poate proiectul dumneavoastră va fi printre ele.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster