In Tarantool è possibile combinare un database super veloce e un'applicazione per lavorarci. Ecco come si fa in modo semplice.

Cinque anni fa ho provato a lavorare con Tarantool, ma all'epoca non mi ha convinto. Recentemente ho tenuto un webinar, durante il quale parlavo di Hadoop e di come funziona MapReduce. In quella sede mi è stata fatta una domanda: "Perché non usare Tarantool per questo compito?".

Per curiosità ho deciso di tornare indietro, testare l'ultima versione e, questa volta, il progetto mi è piaciuto molto. Ora vi mostrerò come scrivere un'applicazione semplice in Tarantool, la caricherò e verificherò le prestazioni, e vedrete quanto sia facile e interessante.

In Tarantool è possibile combinare un database super veloce e un'applicazione per lavorarci. Ecco come si fa in modo semplice.

Cos'è Tarantool

Tarantool si presenta come un database super veloce. Puoi inserire qualsiasi tipo di dato tu voglia. Inoltre, è possibile replicarli, shardarli - ovvero suddividere un'enorme quantità di dati tra diversi server e unire i risultati - creando configurazioni di alta disponibilità tipo "master-master".

In secondo luogo, è un server applicativo. Puoi scrivere le tue applicazioni, lavorare con i dati, per esempio, eliminare in background le vecchie registrazioni secondo regole specifiche. È possibile creare direttamente in Tarantool un server Http che gestisce i dati: restituisce il numero di dati, scrive nuovi dati e riduce tutto questo sul master.

Ho letto un articolo in cui i ragazzi hanno creato una coda di messaggi di 300 righe che funziona veramente bene - hanno una massima prestazione di 20.000 messaggi al secondo. Qui è davvero possibile sviluppare e scrivere un'applicazione molto grande, e non saranno memorie temporanee come in PostgreS.

Proverò a descrivere un server di questo tipo, ma in modo semplice, in questo articolo.

Installazione

Per il test ho creato tre macchine virtuali standard - hard disk da 20 gigabyte, Ubuntu 18.04, 2 CPU virtuali e 4 giga di memoria.

Installa Tarantool - esegui uno script bash oppure aggiungi un repository e fai apt get install Tarantool. Il link allo script è (curl -L https://tarantool.io/installer.sh | VER=2.4 sudo -E bash). Abbiamo a disposizione comandi come:

tarantoolctl — il comando principale per gestire le istanze di Tarantool.
/etc/tarantool — qui si trova tutta la configurazione.
var/log/tarantool — qui si trovano i log.
var/lib/tarantool — qui si trovano i dati, e in seguito sono suddivisi per istanze.

Ci sono le cartelle instance-available e instance-enable: in essa si trova ciò che verrà avviato, il file di configurazione dell'istanza con codice lua, dove è descritto su quali porte ascolta, quanta memoria ha a disposizione, le impostazioni del motore Vinyl, il codice che viene eseguito all'avvio del server, lo sharding, le code, la rimozione dei dati obsoleti e così via.

Le istanze funzionano come in PostgreS. Ad esempio, se desideri avviare più copie di un database che stanno su porte diverse. Quindi, su un singolo server vengono avviate più istanze di database su porte diverse. Possono avere impostazioni completamente diverse: un'istanza implementa una logica, l'altra un'altra.

Gestione delle istanze

Abbiamo il comando tarantoolctl, che consente di gestire le istanze di Tarantool. Ad esempio, tarantoolctl check example controllerà il file di configurazione e dirà se il file è corretto, se non ci sono errori di sintassi.

Puoi controllare lo stato dell'istanza con tarantoolctl status example. Allo stesso modo puoi fare start, stop, restart.

Quando l'istanza è avviata, può essere connessa in due modi.

1. Console amministrativa

Per impostazione predefinita, Tarantool apre un socket, dove viene trasferito del testo ASCII normale per gestire Tarantool. La connessione alla console avviene sempre con l'utente admin, non ci sono autenticazioni, quindi non è necessario esporre la porta della console per la gestione di Tarantool all'esterno.

Per connettersi in questo modo, è necessario inserire Tarantoolctl enter instance name. Il comando avvierà la console e si connetterà con l'utente admin. Non esporre mai la porta della console all'esterno: è meglio lasciarla come unit socket. In questo modo, la possibilità di connettersi a Tarantool sarà solo per coloro che hanno accesso in scrittura al socket.

Questo metodo è necessario per le cose amministrative. Per lavorare con i dati, utilizza il secondo metodo: il protocollo binario.

2. Utilizzo del protocollo binario per connettersi a una porta specifica

Nella configurazione c'è la direttiva listen, che apre una porta per comunicazioni esterne. Questa porta è utilizzata con il protocollo binario e include l'autenticazione.

Per questa connessione si utilizza tarantoolctl connect to port number. Utilizzando questo, è possibile connettersi a server remoti, utilizzare l'autenticazione e concedere diversi diritti di accesso.

Scrittura dei dati e modulo Box

Dal momento che Tarantool è sia un database che un server applicativo, contiene vari moduli. Il modulo che ci interessa è box: gestisce l'operazione con i dati. Quando scrivi qualcosa in box, Tarantool salva i dati su disco, li memorizza in memoria o fa qualcos'altro con essi.

Scrittura

Ad esempio, accediamo al modulo box e chiamiamo la funzione box.once. Questa farà sì che Tarantool esegua il nostro codice all'inizializzazione del server. Creiamo uno space che conterrà i nostri dati.

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

    -- Mantieni tutto sicuro per impostazione predefinita
    --  box.schema.user.create('example', { password = 'secret' })
    --  box.schema.user.grant('example', 'replication')
    --  box.schema.user.grant('example', 'read,write,execute', 'space', 'example')
end

Dopo di che, creiamo l'indice primario – primary – tramite il quale potremo cercare i dati. Per impostazione predefinita, se non vengono specificati parametri, verrà utilizzato il primo campo di ogni record per l'indice primario.

Poi facciamo un grant all'utente guest, con cui ci connettiamo tramite il protocollo binario. Permettiamo di leggere, scrivere ed eseguire in tutta l'istanza.

Se confrontato con i database tradizionali, qui tutto è abbastanza semplice. Abbiamo uno space: un'area in cui vengono semplicemente memorizzati i nostri dati. Ogni record è chiamato tupla. Viene imballato in MessagePack. Questo è un formato molto interessante: è binario e occupa meno spazio – 18 byte contro 27.

In Tarantool è possibile combinare un database super veloce e un'applicazione per lavorarci. Ecco come si fa in modo semplice.

È abbastanza comodo lavorarci. Quasi ogni riga, ogni record di dati può avere colonne assolutamente diverse.

Possiamo vedere tutti gli spazi usando il comando Box.space. Per evidenziare un'istanza specifica, digitiamo box.space example e otteniamo informazioni complete su di essa.

In Tarantool sono integrati due tipi di motori: Memory e Vinyl. Memory memorizza tutti i dati in memoria. Quindi tutto funziona in modo semplice e veloce. I dati vengono salvati su disco, e c'è anche un meccanismo di write ahead log, quindi non perderemo nulla in caso di crash del server.

Vinyl memorizza i dati su disco in una forma a noi più familiare, ovvero si possono archiviare più dati di quanti ne abbiamo in memoria, e Tarantool li leggerà dal disco.

Ora utilizzeremo 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>

Indice:

È necessario creare un indice primario per ogni spazio, perché senza di esso nulla funzionerà. Proprio come in qualsiasi database, creiamo il primo campo: l'ID del record.

Parti:

Qui indichiamo da cosa è composto il nostro indice. È composto da una sola parte: il primo campo che utilizzeremo, di tipo unsigned — un numero intero positivo. Se non ricordo male dalla documentazione, il numero massimo che può essere è 18 quintilioni. Davvero molto.

Dopo possiamo inserire dati utilizzando il comando 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>

Il primo campo è utilizzato come chiave primaria, quindi deve essere unico. Non siamo limitati nel numero di colonne, quindi possiamo inserire quanti più dati vogliamo. Vengono specificati in formato MessagePack, che ho descritto sopra.

Output dei dati

Ora possiamo visualizzare i dati con il comando select.

Box.example.select specificando la chiave {1} restituirà il record desiderato. Se saltiamo la chiave, vedremo tutti i record che abbiamo. Sono tutti diversi nel numero di colonne, ma qui in realtà non esiste il concetto di colonne — ci sono solo numeri di campo.

I dati possono essere assolutamente tanti. E ad esempio, se vogliamo cercarli per il secondo campo. Per fare questo facciamo un nuovo indice secondario.


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

Utilizziamo il comando Create_index.
Lo chiamiamo Secondario.

Dopo dobbiamo specificare i parametri. Il tipo di indice è TREE. Può non essere unico, quindi impostiamo Unique = false.

Poi indichiamo da quali parti è composto il nostro indice. Field è il numero del campo a cui colleghiamo l'indice, e specifichiamo il tipo string. Ed ecco che è stato creato.

unix/:/var/run/tarantool/example.control> box.space.example:create_index('secondario', { 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: secondario
...

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

Ora possiamo invocarlo in questo modo:

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

Salvataggio

Se riavviamo l'istanza e proviamo a richiamare i dati, vedremo che non ci sono — tutto è vuoto. Questo accade perché Tarantool effettua checkpoint e salva i dati su disco, ma se interrompiamo il funzionamento prima del salvataggio più vicino, perderemo tutte le operazioni — perché ci ripristineremo dall'ultimo checkpoint, che è stato, ad esempio, due ore fa.

Non possiamo nemmeno salvare ogni secondo — perché fare continuamente dump su disco da 20 Gb non è una buona idea.

Per questo è stata concepita e implementata la logica del write-ahead log. Con essa, per ogni modifica nei dati viene creata una registrazione in un piccolo file write-ahead log.

Ogni registrazione fino al checkpoint viene salvata in essi. Per questi file impostiamo una dimensione — ad esempio, 64 mb. Quando si riempie, la registrazione inizia a scrivere nel secondo file. E dopo il riavvio, Tarantool si ripristina dall'ultimo checkpoint e poi applica tutte le transazioni più recenti fino al momento di arresto.

In Tarantool è possibile combinare un database super veloce e un'applicazione per lavorarci. Ecco come si fa in modo semplice.

Per effettuare questa registrazione, è necessario specificare un'opzione nelle impostazioni di box.cfg (nel file example.lua):

wal_mode = “write”;

Utilizzo dei dati

Con ciò che abbiamo scritto ora, puoi usare Tarantool per memorizzare dati, e funzionerà molto velocemente come un database. E ora il colpo di grazia – cosa si può fare con tutto questo.

Scriviamo un'applicazione

Ad esempio, scriviamo un'applicazione per Tarantool

Guarda l'applicazione sotto il 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; -- un'ora
    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

-- per il primo avvio crea uno spazio e imposta i permessi
box.once('replica', bootstrap)

-- abilitare l'accesso alla console
console = require('console')
console.listen('127.0.0.1:3302')

-- configurazione 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",
                              "Conteggio Token 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()

Dichiaramo una tabella in lua che definisce i caratteri. Questa tabella è necessaria per generare una stringa casuale.

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

Dopo di che dichiariamo la funzione – randomString e le passiamo il valore della lunghezza come argomento.

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

Poi colleghiamo l'http-router e l'http-server al nostro server Tarantool, JSON che restituiremo al cliente.

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

Dopo questo, iniziamo ad utilizzare la porta 8080 su tutte le interfacce del server http, che registrerà tutte le richieste e gli errori.

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

Successivamente dichiariamo la route che, se sulla porta 8080 viene ricevuta una richiesta con il metodo GET a /count, chiamiamo una funzione in una sola riga. Essa restituisce uno stato — 200, 404, 403 o qualsiasi altro che specifichiamo.

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

Nel corpo restituiamo json.encode, in cui indichiamo il conteggio e getcount, che viene chiamato e mostra il numero di record nel nostro database.

Secondo metodo

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)

Dove nella riga router:route({method = ‘GET’, path = ‘\/token’}, function() chiamiamo una funzione e generiamo un token.

Riga local token = randomString(32) — è una stringa casuale di 32 caratteri.
Nella riga local last = box.space.example:len() estirpiamo l'elemento più recente.
E nella riga box.space.example:insert{ last + 1, token } registriamo i dati nel nostro database, cioè semplicemente incrementiamo l'ID di 1. Questo può essere fatto, tra l'altro, non solo in questo modo goffo. In Tarantool ci sono sequenze per questo compito.

Registriamo lì il token.

Così, abbiamo scritto un'applicazione in un unico file. In essa è possibile interagire immediatamente con i dati, e il modulo box farà tutto il lavoro sporco per te.

Ascolta http e lavora con i dati, tutto è in un'unica istanza — sia l'applicazione che i dati. Pertanto, tutto avviene piuttosto rapidamente.

Per avviare, installiamo il modulo http:

Come facciamo, guarda sotto il spoiler

root@test2:\/ # tarantoolctl rocks install http
Installazione di http:\/\/rocks.tarantool.org\/http-scm-1.src.rock
Dipendenze mancanti per http scm-1:
   checks >= 3.0.1 (non installato)

http scm-1 dipende da checks >= 3.0.1 (non installato)
Installazione di http:\/\/rocks.tarantool.org\/checks-3.0.1-1.rockspec

Clonazione in 'checks'...
remote: Enumerazione oggetti: 28, completato.
remote: Conteggio oggetti: 100% (28\/28), completato.
remote: Compressione oggetti: 100% (19\/19), completato.
remote: Totale 28 (delta 1), riutilizzati 16 (delta 1), pacchetto riutilizzato 0
Ricezione oggetti: 100% (28\/28), 12.69 KiB | 12.69 MiB\/s, completato.
Risoluzione dei delta: 100% (1\/1), completato.
Nota: controllo di '580388773ef11085015b5a06fe52d61acf16b201'.

Sei in stato 'HEAD distaccato'. Puoi esplorare, apportare modifiche sperimentali
 e impegnarle, e puoi scartare eventuali commit che fai in questo
 stato senza influenzare alcun ramo eseguendo un altro checkout.

Se vuoi creare un nuovo ramo per mantenere i commit che crei, puoi
 farlo (ora o più tardi) utilizzando -b con il comando di checkout di nuovo. Esempio:

  git checkout -b <nome-nuovo-ramo>

Nessun manifesto esistente. Tentativo di ricostruzione...
checks 3.0.1-1 è ora installato in \/ .rocks (licenza: BSD)

-- L'identificazione del compilatore C è GNU 7.5.0
-- Verifica del funzionamento del compilatore C: \/usr\/bin\/cc
-- Verifica del funzionamento del compilatore C: \/usr\/bin\/cc -- funziona
-- Rilevamento informazioni ABI del compilatore C
-- Rilevamento informazioni ABI del compilatore C - completato
-- Rilevamento delle funzionalità di compilazione C
-- Rilevamento delle funzionalità di compilazione C - completato
-- Trovato TARANTOOL: \/usr\/include (versione trovata "2.4.2-80-g18f2bc82d")
-- La DIR LUADIR di Tarantool è \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lua
-- La LIBDIR di Tarantool è \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lib
-- Configurazione completata
-- Generazione completata
CMake Warning:
  Le variabili specificate manualmente non sono state utilizzate dal progetto:

    version


-- I file di build sono stati scritti in: \/tmp\/luarocks_http-scm-1-V4P9SM\/http\/build.luarocks
Scansione delle dipendenze del target httpd
[ 50%] Creazione del file oggetto C http\/CMakeFiles\/httpd.dir\/lib.c.o
Nel file incluso da \/tmp\/luarocks_http-scm-1-V4P9SM\/http\/http\/lib.c:32:0:
\/tmp\/luarocks_http-scm-1-V4P9SM\/http\/http\/lib.c: Nel funzione 'tpl_term':
\/usr\/include\/tarantool\/lauxlib.h:144:15: avviso: questa dichiarazione potrebbe passare attraverso [-Wimplicit-fallthrough=]
    (*(B)->p++ = (char)(c)))
    ~~~~~~~~~~~^~~~~~~~~~~~
\/tmp\/luarocks_http-scm-1-V4P9SM\/http\/http\/lib.c:62:7: nota: nell'espansione della macro 'luaL_addchar'
       luaL_addchar(b, '\');
       ^~~~~~~~~~~~
\/tmp\/luarocks_http-scm-1-V4P9SM\/http\/http\/lib.c:63:6: nota: qui
      default:
      ^~~~~~~
Nel file incluso da \/tmp\/luarocks_http-scm-1-V4P9SM\/http\/http\/lib.c:39:0:
\/tmp\/luarocks_http-scm-1-V4P9SM\/http\/http\/tpleval.h: Nel funzione 'tpe_parse':
\/tmp\/luarocks_http-scm-1-V4P9SM\/http\/http\/tpleval.h:147:9: avviso: questa dichiarazione potrebbe passare attraverso [-Wimplicit-fallthrough=]
    type = TPE_TEXT;
    ~~~~~^~~~~~~~~~
\/tmp\/luarocks_http-scm-1-V4P9SM\/http\/http\/tpleval.h:149:3: nota: qui
   case TPE_LINECODE:
   ^~~~
Nel file incluso da \/tmp\/luarocks_http-scm-1-V4P9SM\/http\/http\/lib.c:40:0:
\/tmp\/luarocks_http-scm-1-V4P9SM\/http\/http\/httpfast.h: Nel funzione 'httpfast_parse':
\/tmp\/luarocks_http-scm-1-V4P9SM\/http\/http\/httpfast.h:372:22: avviso: questa dichiarazione potrebbe passare attraverso [-Wimplicit-fallthrough=]
                 code = 0;
                 ~~~~~^~~
\/tmp\/luarocks_http-scm-1-V4P9SM\/http\/http\/httpfast.h:374:13: nota: qui
             case status:
             ^~~~
\/tmp\/luarocks_http-scm-1-V4P9SM\/http\/http\/httpfast.h:393:23: avviso: questa dichiarazione potrebbe passare attraverso [-Wimplicit-fallthrough=]
                 state = message;
                 ~~~~~~^~~~~~~~~
\/tmp\/luarocks_http-scm-1-V4P9SM\/http\/http\/httpfast.h:395:13: nota: qui
             case message:
             ^~~~
[100%] Collegamento della libreria condivisa C lib.so
[100%] Target httpd costruito
[100%] Target httpd costruito
Installa il progetto...
-- Configurazione di installazione: "Debug"
-- Installazione: \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lua\/http\/VERSION.lua
-- Installazione: \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lib\/http\/lib.so
-- Installazione: \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lua\/http\/server\/init.lua
-- Installazione: \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lua\/http\/server\/tsgi_adapter.lua
-- Installazione: \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lua\/http\/nginx_server\/init.lua
-- Installazione: \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lua\/http\/router\/init.lua
-- Installazione: \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lua\/http\/router\/fs.lua
-- Installazione: \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lua\/http\/router\/matching.lua
-- Installazione: \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lua\/http\/router\/middleware.lua
-- Installazione: \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lua\/http\/router\/request.lua
-- Installazione: \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lua\/http\/router\/response.lua
-- Installazione: \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lua\/http\/tsgi.lua
-- Installazione: \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lua\/http\/utils.lua
-- Installazione: \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lua\/http\/mime_types.lua
-- Installazione: \/ .rocks\/share\/tarantool\/rocks\/http\/scm-1\/lua\/http\/codes.lua
http scm-1 è ora installato in \/ .rocks (licenza: BSD)

root@test2:\/ #

Inoltre, per avviare abbiamo bisogno di prometeo:

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

Clonazione in 'prometheus'...
remote: Enumerazione degli oggetti: 19, completato.
remote: Conteggio oggetti: 100% (19/19), completato.
remote: Compressione oggetti: 100% (19/19), completato.
remote: Totale 19 (delta 2), riutilizzati 5 (delta 0), pack-riutilizzati 0
Ricezione oggetti: 100% (19/19), 10.73 KiB | 10.73 MiB/s, completato.
Risoluzione dei delta: 100% (2/2), completato.
prometheus scm-1 è ora installato in /.rocks (licenza: BSD)

root@test2:~#

Avviamo e possiamo accedere ai moduli

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

{"token":"e2tPq9l5Z3QZrewRf6uuoJUl3lJgSLOI"}

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

{"token":"fR5aCA84gj9eZI3gJcV0LEDl9XZAG2Iu"}

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

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

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

Testiamo la velocità

Facciamo partire un benchmark di 50.000 richieste. Le richieste concorrenti saranno 500.

root@test2:~# ab -c 500 -n 50000 http://127.0.0.1:8080/token
Questa è ApacheBench, Versione 2.3 
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licenza alla Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (abbi pazienza)
Completate 5000 richieste
Completate 10000 richieste
Completate 15000 richieste
Completate 20000 richieste
Completate 25000 richieste
Completate 30000 richieste
Completate 35000 richieste
Completate 40000 richieste
Completate 45000 richieste
Completate 50000 richieste
Finito 50000 richieste


Software server: Tarantool
Nome host server: 127.0.0.1
Porta server: 8080

Percorso documento: /token
Lunghezza documento: 44 byte

Livello di concorrenza: 500
Tempo impiegato per i test: 14.578 secondi
Richieste completate: 50000
Richieste fallite: 0
Totale trasferito: 7950000 byte
HTML trasferito: 2200000 byte
Richieste al secondo: 3429.87 [# /sec] (media)
Tempo per richiesta: 145.778 [ms] (media)
Tempo per richiesta: 0.292 [ms] (media, su tutte le richieste concorrenti)
Tasso di trasferimento: 532.57 [Kbytes /sec] ricevuti

Tempi di connessione (ms)
              min  medio[+/-sd] mediana   max
Connessione:        0   10 103.2      0    3048
Elaborazione:    12   69 685.1     15   13538
Attesa:       12   69 685.1     15   13538
Totale:         12   78 768.2     15   14573

Percentuale di richieste servite entro un certo tempo (ms)
  50%     15
  66%     15
  75%     16
  80%     16
  90%     16
  95%     16
  98%     21
  99%     42
 100%  14573 (richiesta più lunga)
root@test2:~#

I token vengono emessi. E stiamo costantemente registrando dati. Il 99% delle richieste sono state elaborate in 42 millisecondi. Di conseguenza, abbiamo circa 3500 richieste al secondo su una piccola macchina con 2 core e 4 gigabyte di RAM.

Inoltre, puoi selezionare un token da 50000 e vedere il suo valore.

Puoi utilizzare non solo http, ma avviare funzioni in background che elaborano i tuoi dati. Inoltre ci sono vari trigger. Ad esempio, puoi invocare funzioni sugli aggiornamenti, controllare qualcosa - risolvere conflitti.

È possibile scrivere applicazioni-script direttamente nel server del database, senza alcuna limitazione, collegare moduli qualsiasi e implementare qualsiasi logica.

Il server delle applicazioni può accedere a server esterni, prelevare dati e archiviare nella sua base. I dati di questa base saranno utilizzati da altre applicazioni.

Questo sarà fatto da Tarantool stesso, quindi non sarà necessario scrivere un'applicazione separata.

In conclusione

Questa è solo la prima parte di un grande lavoro. La seconda sarà pubblicata molto presto sul blog di Mail.ru Group, e aggiungeremo sicuramente il link a questo materiale.

Se sei interessato a partecipare a eventi in cui creiamo queste cose online e fare domande in tempo reale, collegati a canale DevOps by REBRAIN.

Se hai bisogno di migrare nel cloud o hai domande sulla tua infrastruttura, non esitare a lasciare un'applicazione.

P.S. Abbiamo 2 audit gratuiti al mese, forse il tuo progetto sarà tra questi.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster