Vor fünf Jahren habe ich versucht, mit Tarantool zu arbeiten, aber damals konnte ich mich nicht damit anfreunden. Kürzlich habe ich ein Webinar gehalten, in dem ich über Hadoop und die Funktionsweise von MapReduce gesprochen habe. Dort stellte jemand die Frage: "Warum sollte man für diese Aufgabe nicht Tarantool verwenden?"
Aus Neugierde habe ich beschlossen, zu ihm zurückzukehren, die neueste Version zu testen – und diesmal hat mir das Projekt wirklich gut gefallen. Jetzt zeige ich Ihnen, wie man eine einfache Anwendung in Tarantool schreibt, wie ich sie belaste und die Leistung überprüfe, und Sie werden sehen, wie einfach und großartig das Ganze ist.

Was ist Tarantool
Tarantool positioniert sich als ultraschnelle Datenbank. Dort können Sie beliebige Daten speichern, die Sie möchten. Außerdem können Sie sie replizieren und sharden – das heißt, eine große Menge an Daten auf mehrere Server aufzuteilen und die Ergebnisse zusammenzuführen – und ausfallsichere Cluster wie "Master-Master" zu erstellen.
Im zweiten Schritt handelt es sich um einen Application-Server. Sie können Ihre Anwendungen darauf schreiben, mit Daten arbeiten, zum Beispiel alte Datensätze im Hintergrund gemäß bestimmten Regeln löschen. Es ist möglich, direkt im Tarantool einen HTTP-Server zu schreiben, der mit Daten arbeitet: die Anzahl auszugeben, neue Daten zu schreiben und all dies auf den Master zu reduzieren.
Ich habe einen Artikel gelesen, wie die Leute eine Nachrichtenwarteschlange mit 300 Zeilen erstellt haben, die einfach durchstartet – sie haben eine Mindestleistung von 20.000 Nachrichten pro Sekunde. Hier kann man wirklich aufblühen und eine sehr große Anwendung schreiben, und das wird keine gespeicherten Objekte wie in PostgreSQL sein.
So ein Server, aber einfach, werde ich in diesem Artikel versuchen zu beschreiben.
Installation von
Für den Test habe ich drei Standard-VMs eingerichtet – eine Festplatte von 20 Gigabyte, Ubuntu 18.04, 2 virtuelle CPUs und 4 Gigabyte RAM.
Wir installieren Tarantool – starten ein Bash-Skript oder fügen das Repository hinzu und führen apt get install Tarantool aus. Der Link zum Skript ist (curl -L | VER=2.4 sudo -E bash). Dabei erhalten wir solche Befehle wie: tarantoolctl
— der Hauptbefehl zur Verwaltung von Tarantool-Instanzen. — hier liegt die gesamte Konfiguration.
/etc/tarantool var/log/tarantool
— hier liegen die Logs. — здесь лежат логи.
var/lib/tarantool — hier liegen die Daten, die weiter nach Instanzen unterteilt sind.
Es gibt die Ordner instance-available und instance-enable — darin befinden sich die Elemente, die gestartet werden sollen — die Konfigurationsdatei der Instanz mit Lua-Code, der beschreibt, an welchen Ports sie lauscht, wie viel Speicher ihr zur Verfügung steht, die Einstellungen der Vinyl-Engine, der Code, der beim Start des Servers ausgeführt wird, Sharding, Warteschlangen, das Löschen veralteter Daten usw.
Die Instanzen funktionieren ähnlich wie in PostgreS. Zum Beispiel, wenn Sie mehrere Kopien einer Datenbank starten möchten, die an verschiedenen Ports hängt. Das bedeutet, auf einem Server werden mehrere Instanzen von Datenbanken gestartet, die an unterschiedlichen Ports hängen. Sie können völlig unterschiedliche Einstellungen haben — eine Instanz implementiert eine Logik, die andere eine andere.
Instanzen verwalten
Wir haben das Kommando tarantoolctl, das es ermöglicht, die Instanzen von Tarantool zu verwalten. Zum Beispiel wird tarantoolctl check example die Konfigurationsdatei überprüfen und sagen — Datei ist in Ordnung, wenn es keine Syntaxfehler gibt.
Der Status der Instanz kann überprüft werden — tarantoolctl status example. Auf die gleiche Weise kann man start, stop, restart durchführen.
Wenn die Instanz gestartet ist, kann man sich auf zwei Arten verbinden.
1. Administrationskonsole
Standardmäßig öffnet Tarantool einen Socket, über den normaler ASCII-Text zur Steuerung von Tarantool übertragen wird. Die Verbindung zur Konsole erfolgt immer unter dem Benutzer admin, es gibt keine Authentifizierung, daher sollte der Konsolenport für die Verwaltung von Tarantool nicht nach außen geführt werden.
Um auf diese Weise eine Verbindung herzustellen, geben Sie Tarantoolctl enter instance name ein. Der Befehl startet die Konsole und verbindet sich mit dem Benutzer admin. Stellen Sie den Konsolenport niemals nach außen — es ist besser, ihn als Unix-Socket zu belassen. So kann sich nur verbinden, wer Zugriff auf den Socket hat.
Diese Methode wird für administrative Aufgaben benötigt. Für die Arbeit mit Daten verwenden Sie die zweite Methode — das binäre Protokoll.
2. Verwendung des binären Protokolls für die Verbindung zu einem bestimmten Port
In der Konfiguration gibt es die Direktive listen, die einen Port für externe Kommunikationen öffnet. Dieser Port wird mit dem binären Protokoll verwendet und umfasst eine Authentifizierung.
Für diese Verbindung wird tarantoolctl connect to port number verwendet. Damit kann man sich mit entfernten Servern verbinden, Authentifizierung nutzen und verschiedene Zugriffsrechte gewähren.
Datenspeicherung und Box-Modul
Da Tarantool sowohl eine Datenbank als auch ein Anwendungsserver ist, gibt es verschiedene Module. Uns interessiert das Modul box — es ermöglicht die Arbeit mit Daten. Wenn Sie etwas in box schreiben, speichert Tarantool die Daten auf der Festplatte, behält sie im Arbeitsspeicher oder führt andere Aktionen damit aus.
Speichern
Zum Beispiel gehen wir in das Modul box und rufen die Funktion box.once auf. Sie zwingt Tarantool dazu, unseren Code bei der Serverinitialisierung auszuführen. Wir erstellen einen space, in dem unsere Daten gespeichert werden.
local function bootstrap()
local space = box.schema.create_space('example')
space:create_index('primary')
box.schema.user.grant('guest', 'read,write,execute', 'universe')
-- Sicherheitsmaßnahmen standardmäßig aktivieren
-- box.schema.user.create('example', { password = 'secret' })
-- box.schema.user.grant('example', 'replication')
-- box.schema.user.grant('example', 'read,write,execute', 'space', 'example')
endAnschließend erstellen wir einen primären Index – primary –, über den die Daten abgerufen werden können. Standardmäßig, wenn keine Parameter angegeben sind, wird das erste Feld in jedem Datensatz für den Primärindex verwendet.
Dann gewähren wir dem Benutzer guest, mit dem wir uns über das binäre Protokoll verbinden, Berechtigungen. Wir erlauben das Lesen, Schreiben und Ausführen im gesamten Instanz.
Im Vergleich zu herkömmlichen Datenbanken ist alles hier recht einfach. Wir haben einen Space – einen Bereich, in dem unsere Daten einfach gespeichert werden. Jeder Datensatz wird als Tuple bezeichnet. Er wird in MessagePack verpackt. Dieses Format ist ziemlich cool – es ist binär und benötigt weniger Platz – 18 Byte statt 27.

Es ist sehr benutzerfreundlich. Fast jede Zeile, jeder Datensatz kann absolut unterschiedliche Spalten haben.
Wir können alle Spaces mit dem Befehl Box.space anzeigen. Um eine bestimmte Instanz auszuwählen – schreiben wir box.space example und erhalten alle Informationen dazu.
In Tarantool sind zwei Arten von Engines integriert: Memory und Vinyl. Memory speichert alle Daten im Speicher. Daher läuft alles einfach und schnell. Die Daten werden auf die Festplatte geschrieben und es gibt einen Mechanismus für das Write Ahead Log, sodass wir bei einem Serverausfall nichts verlieren.
Vinyl speichert die Daten auf der Festplatte in einem für uns gewohnten Format – das heißt, man kann mehr Daten speichern, als wir an Speicher haben, und Tarantool wird sie von der Festplatte lesen.
Jetzt werden wir Memory verwenden.
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:
Ein Primärindex muss für jeden Space erstellt werden, da ohne ihn nichts funktionieren wird. Wie in jeder Datenbank erstellen wir das erste Feld – die ID des Datensatzes.
Teile:
Hier geben wir an, aus welchen Teilen unser Index besteht. Er besteht aus einem Teil – dem ersten Feld, das wir verwenden werden, vom Typ unsigned — eine positive Ganzzahl. So viel ich aus der Dokumentation erinnere, beträgt die maximale Zahl 18 Trilliarden. Das ist unglaublich viel.
Jetzt können wir Daten mit dem Befehl insert einfügen.
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>Das erste Feld dient als Primärschlüssel und muss daher einzigartig sein. Wir sind nicht auf eine bestimmte Anzahl von Spalten beschränkt, sodass wir beliebig viele Daten einfügen können. Diese werden im MessagePack-Format angegeben, das ich oben beschrieben habe.
Datenausgabe
Als nächstes können wir die Daten mit dem Befehl select ausgeben.
Box.example.select mit dem Schlüssel {1} gibt den gewünschten Datensatz aus. Wenn wir den Schlüssel weglassen, sehen wir alle Datensätze, die wir haben. Diese unterscheiden sich in der Anzahl der Spalten, aber hier gibt es im Grunde keine Spalten — es gibt nur Feldnummern.
Es können beliebig viele Daten vorhanden sein. Zum Beispiel müssen wir sie nach dem zweiten Feld durchsuchen. Dazu erstellen wir einen neuen sekundären Index.
box.space.example:create_index( 'secondary', { type = 'TREE', unique = false, parts = {{field = 2, type ='string'} }}) Wir verwenden den Befehl Create_index.
Wir nennen ihn Secondary.
Anschließend müssen wir die Parameter angeben. Der Typ des Indexes ist TREE. Es kann nicht einzigartig sein, daher geben wir Unique = false ein.
Dann geben wir an, aus welchen Teilen unser Index besteht. Field ist die Nummer des Feldes, auf das wir den Index anwenden, und wir geben den Typ string an. Und schon wurde er erstellt.
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>Jetzt können wir es auf diese Weise aufrufen:
unix/:/var/run/tarantool/example.control> box.space.example.index.secondary:select('test1')
---
- - [1, 'test1', 'test2']
...
Speichern
Wenn wir die Instanz neu starten und erneut versuchen, die Daten abzurufen, werden wir feststellen, dass sie nicht vorhanden sind — alles ist leer. Das passiert, weil Tarantool Checkpoints erstellt und Daten auf die Festplatte speichert, aber wenn wir die Arbeit vor der nächsten Speicherung stoppen, verlieren wir alle Operationen — denn wir stellen auf den letzten Checkpoint zurück, der zum Beispiel vor zwei Stunden war.
Jede Sekunde zu speichern wird ebenfalls nicht funktionieren — es ist keine gute Idee, ständig 20 GB auf die Festplatte zu dumpen.
Dafür wurde das Konzept des Write-Ahead-Logs entwickelt und implementiert. Mit seiner Hilfe wird für jede Datenänderung ein Eintrag in einer kleinen Write-Ahead-Log-Datei erstellt.
Jeder Datensatz bis zum Checkpoint wird in diesen Dateien gespeichert. Für diese Dateien setzen wir eine Größe fest – zum Beispiel 64 MB. Wenn dieser voll ist, beginnt die Aufzeichnung in die zweite Datei. Nach einem Neustart wird Tarantool aus dem letzten Checkpoint wiederhergestellt und alle späteren Transaktionen bis zum Zeitpunkt des Stopps werden angewendet.

Um eine solche Aufzeichnung durchzuführen, muss die Option in den Einstellungen von box.cfg (in der Datei example.lua) angegeben werden:
wal_mode = “write”;Verwendung der Daten
Mit dem, was wir gerade geschrieben haben, können Sie Tarantool zur Speicherung von Daten verwenden, und es wird sehr schnell wie eine Datenbank arbeiten. Und jetzt das Sahnehäubchen – was man damit alles tun kann.
Wir schreiben eine Anwendung
Zum Beispiel schreiben wir eine solche Anwendung für Tarantool
Die Anwendung finden Sie unter dem 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; -- eine Stunde
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
-- für den ersten Lauf einen Space erstellen und Berechtigungen einrichten
box.once('replica', bootstrap)
-- Konsolezugang aktivieren
console = require('console')
console.listen('127.0.0.1:3302')
-- http Konfiguration
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 Anzahl")
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()Wir erklären eine Tabelle in Lua, die die Zeichen definiert. Diese Tabelle wird zur Generierung einer zufälligen Zeichenfolge benötigt.
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
endDanach deklarieren wir die Funktion – randomString und übergeben den Wert der Länge in Klammern.
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)]
endDann binden wir den HTTP-Router und den HTTP-Server an unseren Tarantool-Server, JSON, das wir dem Client übergeben werden.
local http_router = require('http.router')
local http_server = require('http.server')
local json = require('json')Danach starten wir den HTTP-Server auf Port 8080 auf allen Schnittstellen, der alle Anfragen und Fehler protokolliert.
local httpd = http_server.new('0.0.0.0', 8080, {
log_requests = true,
log_errors = true
})Wir deklarieren dann eine Route, die bei einer GET-Anfrage an Port 8080 /count die Funktion mit einer Zeile aufruft. Sie gibt den Status – 200, 404, 403 oder jeden anderen, den wir angeben.
router:route({method = 'GET', path = '/count'}, function()
return {status = 200, body = json.encode({count = get_count()})}
end)Im Body geben wir json.encode zurück, in dem wir die Anzahl und getcount angeben, die aufgerufen wird und die Anzahl der Einträge in unserer Datenbank anzeigt.
Die zweite Methode
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)Wo in der Zeile router:route({method = 'GET', path = '/token'}, function() rufen wir die Funktion auf und generieren ein Token.
Zeichenfolge local token = randomString(32) – das ist ein zufälliger String aus 32 Zeichen.
In der Zeile local last = box.space.example:len() entnehmen wir das letzte Element.
Und in der Zeile box.space.example:insert{ last + 1, token } speichern wir die Daten in unserer Datenbank, das heißt, wir erhöhen einfach die ID um 1. Das kann übrigens auch nicht nur auf diese umständliche Weise geschehen. In Tarantool gibt es Sequenzen dafür.
Wir speichern das Token dort.
So haben wir in einer Datei die Anwendung geschrieben. Man kann direkt mit den Daten arbeiten, und das Modul box erledigt die ganze mühsame Arbeit für Sie.
Es hört auf http und arbeitet mit Daten, alles befindet sich in einer einzigen Instanz – sowohl die Anwendung als auch die Daten. Daher geschieht alles ziemlich schnell.
Für den Start installieren wir das http-Modul:
Wie wir das machen, sehen Sie unter dem Spoiler
root@test2:/# tarantoolctl rocks install http
Installiere http://rocks.tarantool.org/http-scm-1.src.rock
Fehlende Abhängigkeiten für http scm-1:
checks >= 3.0.1 (nicht installiert)
http scm-1 hängt von checks >= 3.0.1 (nicht installiert) ab
Installiere http://rocks.tarantool.org/checks-3.0.1-1.rockspec
Klonen in 'checks'...
remote: Objekte zählen: 28, fertig.
remote: Zähle Objekte: 100% (28/28), fertig.
remote: Komprimiere Objekte: 100% (19/19), fertig.
remote: Insgesamt 28 (delta 1), wiederverwendet 16 (delta 1), pack-wiederverwendet 0
Empfange Objekte: 100% (28/28), 12.69 KiB | 12.69 MiB/s, fertig.
Delta werden aufgelöst: 100% (1/1), fertig.
Hinweis: Überprüfe '580388773ef11085015b5a06fe52d61acf16b201'.
Du bist im Zustand 'detached HEAD'. Du kannst dich umsehen, experimentelle
Änderungen vornehmen und diese committen, und du kannst alle Commits, die du in diesem
Zustand machst, ohne Auswirkungen auf irgendwelche Branches durch einen anderen Checkout verwerfen.
Wenn du einen neuen Branch erstellen möchtest, um die Commits zu behalten, die du erstellst, kannst du
das (jetzt oder später) tun, indem du -b mit dem Checkout-Befehl erneut verwendest. Beispiel:
git checkout -b <neuer-branch-name>
Kein bestehendes Manifest. Versuche, neu zu erstellen...
checks 3.0.1-1 ist jetzt in /.rocks installiert (Lizenz: BSD)
-- Die C-Compiler-Identifikation ist GNU 7.5.0
-- Überprüfe, ob der C-Compiler funktioniert: /usr/bin/cc
-- Überprüfe, ob der C-Compiler funktioniert: /usr/bin/cc -- funktioniert
-- Erkenne C-Compiler ABI-Informationen
-- Erkenne C-Compiler ABI-Informationen - fertig
-- Erkenne C-Kompilierungsmerkmale
-- Erkenne C-Kompilierungsmerkmale - fertig
-- Tarantool gefunden: /usr/include (Version gefunden "2.4.2-80-g18f2bc82d")
-- Tarantool LUADIR ist /.rocks/share/tarantool/rocks/http/scm-1/lua
-- Tarantool LIBDIR ist /.rocks/share/tarantool/rocks/http/scm-1/lib
-- Konfiguration abgeschlossen
-- Generierung abgeschlossen
CMake-Warnung:
Manuell angegebene Variablen wurden von dem Projekt nicht verwendet:
version
-- Build-Dateien wurden geschrieben in: /tmp/luarocks_http-scm-1-V4P9SM/http/build.luarocks
Scanne Abhängigkeiten des Ziels httpd
[ 50%] Baue C-Objekt http/CMakeFiles/httpd.dir/lib.c.o
In Datei inkludiert von /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:32:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c: In Funktion ‚tpl_term‘:
/usr/include/tarantool/lauxlib.h:144:15: Warnung: diese Anweisung könnte durchfallen [-Wimplicit-fallthrough=]
(*(B)->p++ = (char)(c)))
~~~~~~~~~~~^~~~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:62:7: Hinweis: in der Erweiterung des Makros ‚luaL_addchar‘
luaL_addchar(b, '\');
^~~~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:63:6: Hinweis: hier
default:
^~~~~~~
In Datei inkludiert von /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:39:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h: In Funktion ‚tpe_parse‘:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h:147:9: Warnung: diese Anweisung könnte durchfallen [-Wimplicit-fallthrough=]
type = TPE_TEXT;
~~~~~^~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h:149:3: Hinweis: hier
case TPE_LINECODE:
^~~~
In Datei inkludiert von /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:40:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h: In Funktion ‚httpfast_parse‘:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:372:22: Warnung: diese Anweisung könnte durchfallen [-Wimplicit-fallthrough=]
code = 0;
~~~~~^~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:374:13: Hinweis: hier
case status:
^~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:393:23: Warnung: diese Anweisung könnte durchfallen [-Wimplicit-fallthrough=]
state = message;
~~~~~~^~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:395:13: Hinweis: hier
case message:
^~~~
[100%] Verlinke C Shared Library lib.so
[100%] Ziel httpd erstellt
[100%] Ziel httpd erstellt
Installiere das Projekt...
-- Installationskonfiguration: "Debug"
-- Installiere: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/VERSION.lua
-- Installiere: /.rocks/share/tarantool/rocks/http/scm-1/lib/http/lib.so
-- Installiere: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/server/init.lua
-- Installiere: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/server/tsgi_adapter.lua
-- Installiere: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/nginx_server/init.lua
-- Installiere: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/init.lua
-- Installiere: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/fs.lua
-- Installiere: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/matching.lua
-- Installiere: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/middleware.lua
-- Installiere: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/request.lua
-- Installiere: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/response.lua
-- Installiere: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/tsgi.lua
-- Installiere: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/utils.lua
-- Installiere: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/mime_types.lua
-- Installiere: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/codes.lua
http scm-1 ist jetzt in /.rocks installiert (Lizenz: BSD)
root@test2:/#Für den Start benötigen wir auch 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 ist jetzt in /.rocks installiert (Lizenz: BSD)
root@test2:/#
Wir starten und können auf die Module zugreifen
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 выдает токен и делает запись этого токена в базу.
Wir testen die Geschwindigkeit
Lassen Sie uns einen Benchmark mit 50.000 Anfragen starten. Es wird 500 konkurrierende Anfragen geben.
root@test2:/# ab -c 500 -n 50000 http://127.0.0.1:8080/token
Das ist ApacheBench, Version 2.3
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Lizenzierte Software der Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (bitte Geduld haben)
5000 Anfragen abgeschlossen
10000 Anfragen abgeschlossen
15000 Anfragen abgeschlossen
20000 Anfragen abgeschlossen
25000 Anfragen abgeschlossen
30000 Anfragen abgeschlossen
35000 Anfragen abgeschlossen
40000 Anfragen abgeschlossen
45000 Anfragen abgeschlossen
50000 Anfragen abgeschlossen
50000 Anfragen beendet
Server-Software: Tarantool
Server-Hostname: 127.0.0.1
Server-Port: 8080
Dokumentenpfad: /token
Dokumentenlänge: 44 Byte
Konkurrenzlevel: 500
Zeit für Tests: 14,578 Sekunden
Vollständige Anfragen: 50000
Fehlerhafte Anfragen: 0
Gesamt übertragene Daten: 7950000 Byte
HTML übertragene Daten: 2200000 Byte
Anfragen pro Sekunde: 3429,87 [#/sec] (Durchschnitt)
Zeit pro Anfrage: 145,778 [ms] (Durchschnitt)
Zeit pro Anfrage: 0,292 [ms] (Durchschnitt, über alle gleichzeitig ausgeführten Anfragen)
Übertragungsrate: 532,57 [Kbytes/sec] empfangen
Verbindungszeiten (ms)
min mean[+/-sd] median max
Verbinden: 0 10 103,2 0 3048
Verarbeitung: 12 69 685,1 15 13538
Warten: 12 69 685,1 15 13538
Gesamt: 12 78 768,2 15 14573
Prozentsatz der Anfragen, die innerhalb einer bestimmten Zeit (ms) bedient wurden
50% 15
66% 15
75% 16
80% 16
90% 16
95% 16
98% 21
99% 42
100% 14573 (längste Anfrage)
root@test2:/#Tokens werden ausgegeben. Und wir zeichnen ständig Daten auf. 99% der Anfragen wurden innerhalb von 42 Millisekunden bearbeitet. Das bedeutet, wir haben etwa 3500 Anfragen pro Sekunde auf einem kleinen Server mit 2 Kernen und 4 Gigabyte RAM.
Sie können auch ein beliebiges 50000-Token auswählen und seinen Wert anzeigen.
Es ist nicht nur http möglich, sondern auch Hintergrundfunktionen auszuführen, die Ihre Daten verarbeiten. Zudem gibt es verschiedene Trigger. Beispielsweise können Sie Funktionen bei Updates aufrufen, etwas überprüfen – Konflikte beheben.
Sie können Anwendungen-Skripte direkt auf dem Datenbankserver schreiben und sich dabei nicht einschränken, alle Module anschließen und jede Logik umsetzen.
Der Anwendungsserver kann auf externe Server zugreifen, Daten abrufen und in seiner eigenen Datenbank speichern. Die Daten aus dieser Datenbank werden von anderen Anwendungen genutzt.
Das wird Tarantool selbst erledigen, sodass Sie keine separate Anwendung schreiben müssen.
Zusammenfassung
Das ist nur der erste Teil einer umfangreichen Arbeit. Der zweite Teil wird bald im Blog der Mail.ru Group veröffentlicht, und wir werden einen Link dazu in dieses Material aufnehmen.
Wenn Sie daran interessiert sind, Veranstaltungen zu besuchen, bei denen wir solche Dinge online erstellen und Fragen in Echtzeit stellen, schließen Sie sich uns an..
Wenn Sie einen Umzug in die Cloud benötigen oder Fragen zu Ihrer Infrastruktur haben, .
P.S. Wir haben zwei kostenlose Audits pro Monat, vielleicht ist gerade Ihr Projekt dabei.
Quelle: habr.com
