W Tarantool można połączyć super szybką bazę danych z aplikacją do ich obsługi. Oto jak prosto to zrobić

Pięć lat temu próbowałem pracować z Tarantool, ale wtedy mi się nie spodobał. Niedawno prowadziłem webinar, w którym opowiadałem o Hadoop i o tym, jak działa MapReduce. Zostało mi zadane pytanie — „Dlaczego nie użyć do tego zadania Tarantool?”.

Z ciekawości postanowiłem wrócić do niego, przetestować najnowszą wersję — i tym razem projekt bardzo mi się spodobał. Teraz pokażę, jak napisać w Tarantool proste aplikacje, obciążyć je i sprawdzić wydajność, a zobaczycie, jak to wszystko jest łatwe i świetne.

W Tarantool można połączyć super szybką bazę danych z aplikacją do ich obsługi. Oto jak prosto to zrobić

Co to jest Tarantool

Tarantool pozycjonuje się jako superszybka baza danych. Można do niego wprowadzać dowolne dane, jakie tylko zechcesz. Dodatkowo, można je replikować, shardować — czyli dzielić ogromne ilości danych na kilka serwerów i łączyć wyniki — tworzyć odporne na awarie zestawy typu „master-master”.

Po drugie, to serwer aplikacji. Możesz na nim pisać swoje aplikacje, pracować z danymi, na przykład w tle usuwać stare rekordy według określonych reguł. Można napisać bezpośrednio w Tarantool serwer Http, który będzie pracować z danymi: wydawać ich ilość, zapisywać nowe dane i redukować to wszystko na maestra.

Czytałem artykuł, jak goście zrobili kolejkę wiadomości na 300 linijek, która po prostu rozwija i zrywa — mają minimalną wydajność od 20 000 wiadomości na sekundę. Tutaj można naprawdę się rozwinąć i napisać bardzo dużą aplikację, która nie będzie takimi archiwami jak w PostgreS.

Taki serwer, tylko prosty, postaram się opisać w tym artykule.

Instalacja

Na potrzeby testu założyłem trzy standardowe maszyny wirtualne – dysk twardy o pojemności 20 gigabajtów, Ubuntu 18.04, 2 wirtualne CPU i 4 gigabajty pamięci.

Instalujemy Tarantool — uruchamiamy skrypt bashowy lub dodajemy repozytorium i wykonujemy apt get install Tarantool. Link do skryptu — (curl -L https://tarantool.io/installer.sh | VER=2.4 sudo -E bash). Pojawiają się takie komendy, jak:

tarantoolctl — główna komenda do zarządzania instancjami Tarantoola.
/etc/tarantool — tutaj znajduje się cała konfiguracja.
var/log/tarantool — tutaj znajdują się logi.
var/lib/tarantool — tutaj znajdują się dane, które dalej są podzielone według instancji.

Są foldery instance-available i instance-enable — w tym ostatnim znajduje się to, co będzie uruchamiane — plik konfiguracyjny instancji z kodem lua, w którym opisano, na jakich portach nasłuchuje, jaka pamięć jest mu dostępna, ustawienia silnika Vinyl, kod, który uruchamia się przy starcie serwera, shardowanie, kolejki, usuwanie przestarzałych danych i tak dalej.

Instancje działają podobnie jak w PostgreS. Na przykład, chcesz uruchomić kilka kopii bazy danych, które działają na różnych portach. Oznacza to, że na jednym serwerze uruchamiane są różne instancje baz danych, które działają na różnych portach. Mogą mieć zupełnie różne ustawienia — jedna instancja realizuje jedną logikę, druga — inną.

Zarządzanie instancjami

Mamy komendę tarantoolctl, która pozwala zarządzać instancjami Tarantula. Na przykład, tarantoolctl check example sprawdzi plik konfiguracyjny i powie — plik jest w porządku, jeśli nie ma w nim błędów składniowych.

Możesz sprawdzić status instancji — tarantoolctl status example. W ten sam sposób można wykonywać start, stop, restart.

Kiedy instancja jest uruchomiona, można się do niej podłączyć na dwa sposoby.

1. Konsola administracyjna

Domyślnie Tarantool otwiera gniazdo, w którym przesyłany jest zwykły tekst ASCII do zarządzania Tarantulem. Podłączenie do konsoli odbywa się zawsze jako użytkownik admin, nie ma tam uwierzytelnienia, dlatego nie ma potrzeby wystawiania portu konsoli na zewnątrz do zarządzania Tarantulem.

Aby połączyć się w ten sposób, należy wpisać Tarantoolctl enter instance name. Komenda uruchomi konsolę i połączy się jako użytkownik admin. Nigdy nie wystawiaj portu konsoli na zewnątrz — lepiej zostawić go jako gniazdo jednostkowe. Wtedy możliwość podłączenia się do Tarantula będzie miała tylko ta osoba, która ma dostęp do zapisu w gniazdo.

Ten sposób jest potrzebny do rzeczy administracyjnych. Do pracy z danymi użyj drugiego sposobu — protokołu binarnego.

2. Użycie protokołu binarnego do połączenia z określonym portem

W konfiguracji jest dyrektywa listen, która otwiera port dla zewnętrznych komunikacji. Ten port jest używany z protokołem binarnym i tam włączona jest autoryzacja.

Do tego połączenia używa się tarantoolctl connect to port number. Używając tej komendy, można podłączać się do zdalnych serwerów, używać autoryzacji i nadawać różne prawa dostępu.

Zapis danych i moduł Box

Ponieważ Tarantool jest zarówno bazą danych, jak i serwerem aplikacji, zawiera różne moduły. Interesuje nas moduł box — realizuje on pracę z danymi. Kiedy zapisujesz coś w box, Tarantool zapisuje dane na dysku, przechowuje w pamięci lub wykonuje z nimi inne operacje.

Zapisz

Na przykład wchodzimy do modułu box i wywołujemy funkcję box.once. Zmusza ona Tarantoola do uruchomienia naszego kodu podczas inicjalizacji serwera. Tworzymy space, w którym będą przechowywane nasze dane.

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

    -- Zabezpieczamy domyślnie
    --  box.schema.user.create('example', { password = 'secret' })
    --  box.schema.user.grant('example', 'replication')
    --  box.schema.user.grant('example', 'read,write,execute', 'space', 'example')
end

Następnie tworzymy indeks podstawowy – primary, według którego będzie można wyszukiwać dane. Domyślnie, jeśli nie podamy żadnych parametrów, zostanie użyte pierwsze pole w każdym rekordzie do indeksu podstawowego.

Następnie nadajemy uprawnienia użytkownikowi guest, z którym łączymy się za pomocą protokołu binarnego. Pozwalamy na odczyt, zapis i wykonanie w całym instancie.

W porównaniu do zwykłych baz danych, wszystko jest tutaj dość proste. Mamy space – obszar, w którym po prostu przechowujemy nasze dane. Każdy rekord nazywa się krotką. Jest pakowany w MessagePack. To bardzo ciekawy format — jest binarny i zajmuje mniej miejsca – 18 bajtów w porównaniu do 27.

W Tarantool można połączyć super szybką bazę danych z aplikacją do ich obsługi. Oto jak prosto to zrobić

Bardzo wygodnie się z nim pracuje. Prawie każdy wiersz, każdy zapis danych może mieć zupełnie różne kolumny.

Wszystkie spacje możemy zobaczyć za pomocą polecenia Box.space. Aby wyróżnić konkretny instans – piszemy box.space example i otrzymujemy pełne informacje o nim.

W Tarantool wbudowane są dwa typy silników: Memory i Vinyl. Memory przechowuje wszystkie dane w pamięci. Dlatego wszystko działa prosto i szybko. Dane są dumpowane na dysk, a także istnieje mechanizm write ahead log, więc nic nie stracimy w przypadku awarii serwera.

Vinyl przechowuje dane na dysku w bardziej znanym nam formacie — co oznacza, że można przechowywać więcej danych, niż mamy pamięci, a Tarantool będzie je odczytywał z dysku.

Teraz będziemy używać 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>

Indeks:

Indeks podstawowy musi być tworzony dla każdej przestrzeni, ponieważ bez niego nic nie będzie działać. Tak jak w każdej bazie, tworzymy pierwsze pole – ID wpisu.

Części:

Tutaj wskazujemy, z czego składa się nasz indeks. Składa się z jednej części – pierwszego pola, które będziemy używać, typu unsigned — liczba całkowita dodatnia. Z tego, co pamiętam z dokumentacji, maksymalna liczba, jaka może być – 18 kwintylionów. Naprawdę dużo.

Następnie możemy wstawiać dane za pomocą polecenia 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>

Pierwsze pole jest używane jako klucz podstawowy, więc musi być unikalne. Liczbą kolumn nie jesteśmy ograniczeni, więc możemy wstawiać dowolną ilość danych. Wskazują one w formacie MessagePack, który opisałem powyżej.

Wyświetlanie danych

Następnie możemy wyświetlać dane za pomocą polecenia select.

Box.example.select z kluczem {1} wyświetli żądany wpis. Jeśli pominemy klucz, zobaczymy wszystkie wpisy, jakie mamy. Różnią się one liczba kolumn, ale zasadniczo nie ma tu pojęcia kolumn – są tylko numery pól.

Może być ich absolutnie nieograniczona ilość. Na przykład, musimy je wyszukiwać według drugiego pola. W tym celu tworzymy nowy indeks wtórny.


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

Używamy polecenia Create_index.
Nazywamy go Secondary.

Następnie należy wskazać parametry. Typ indeksu — TREE. Może być nieunikalny, dlatego wprowadzamy Unique = false.

Następnie wskazujemy, z jakich części składa się nasz indeks. Field — to numer pola, do którego przypinamy indeks, i wskazujemy typ string. I tak został utworzony.

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>

Teraz możemy go wywołać w ten sposób:

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

Zapis

Jeśli zrestartujemy instancję i ponownie spróbujemy wywołać dane — zobaczymy, że ich nie ma — wszystko puste. Tak się dzieje, ponieważ Tarantool wykonuje punkty kontrolne i zapisuje dane na dysku, ale jeśli zatrzymamy pracę przed najbliższym zapisaniem, stracimy wszystkie operacje — ponieważ przywrócimy się do ostatniego punktu kontrolnego, który był, na przykład, dwie godziny temu.

Zapis każdą sekundę też nie jest możliwy — ponieważ ciągłe zrzucanie 20 GB na dysk to niezbyt dobry pomysł.

W tym celu opracowano i wdrożono koncepcję logu zapisu wstecznego. Dzięki temu każda zmiana w danych tworzy wpis w małym pliku logu zapisu wstecznego.

Każdy wpis przed punktem kontrolnym jest w nim zapisywany. Dla tych plików ustalamy rozmiar — na przykład 64 MB. Gdy się zapełni, zapis zaczyna trafiać do drugiego pliku. Po restarcie Tarantool przywraca się z ostatniego punktu kontrolnego, a następnie nawiązuje wszystkie późniejsze transakcje do momento zatrzymania.

W Tarantool można połączyć super szybką bazę danych z aplikacją do ich obsługi. Oto jak prosto to zrobić

Aby zrealizować taki zapis, należy wskazać opcję w ustawieniach box.cfg (w pliku example.lua):

wal_mode = “write”;

Użycie danych

Z tym, co właśnie napisaliśmy, możecie używać Tarantoola do przechowywania danych, a będzie on działał bardzo szybko jako baza danych. A teraz wisienka na torcie – co można z tym wszystkim zrobić.

Tworzymy aplikację

Na przykład, napiszemy dla Tarantoola taką aplikację

Zobacz aplikację pod spoilerem

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; -- jedna godzina
    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

-- przy pierwszym uruchomieniu twórz przestrzeń i skonfiguruj uprawnienia
box.once('replica', bootstrap)

-- włączanie dostępu do konsoli
console = require('console')
console.listen('127.0.0.1:3302')

-- konfiguracja 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",
                              "Liczba tokenów 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()

Ogłaszamy pewną tablicę w lua, która definiuje znaki. Ta tablica jest potrzebna do generowania losowego ciągu.

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

Następnie ogłaszamy funkcję – randomString i w nawiasach przypiszemy wartość długości.

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

Następnie do naszego serwera Tarantool podłączamy http-router oraz http-server, JSON, które będziemy zwracać klientowi.

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

Następnie uruchamiamy serwer http na porcie 8080 na wszystkich interfejsach, który będzie rejestrował wszystkie żądania i błędy.

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

Następnie ogłaszamy trasę, że jeśli na port 8080 /count przychodzi żądanie metodą GET, to wywołujemy funkcję z jednej linijki. Zwraca ona status — 200, 404, 403 lub inny, który wskażemy.

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

W ciele zwracamy json.encode, w której wskazujemy count oraz get_count, która jest wywoływana i pokazuje liczbę rekordów w naszej bazie.

Druga metoda

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)

Gdzie w linijce router:route({method = ‘GET’, path = ‘ /token’}, function() wywołujemy funkcję i generujemy token.

Ciąg local token = randomString(32) – to losowy ciąg składający się z 32 znaków.
W linii local last = box.space.example:len() wyciągamy ostatni element.
A w linijce box.space.example:insert{ last + 1, token } zapisujemy dane do naszej bazy, czyli po prostu zwiększamy ID o 1. Można to zresztą zrobić nie tylko w taki niezgrabny sposób. W Tarantule są sekwencje do tego celu.

Zapisujemy tam token.

W ten sposób, w jednym pliku napisaliśmy aplikację. Może ona od razu obsługiwać dane, a moduł box wykona całą brudną robotę za Ciebie.

Słucha http i pracuje z danymi, wszystko jest w jednym instansie — zarówno aplikacja, jak i dane. Dlatego wszystko przebiega wystarczająco szybko.

Aby uruchomić, instalujemy moduł http:

Jak to robimy, zobacz w spoilerze

root@test2:₩ tarantoolctl rocks install http
Instalowanie http://rocks.tarantool.org/http-scm-1.src.rock
Brakujące zależności dla http scm-1:
   checks >= 3.0.1 (niezainstalowane)

http scm-1 wymaga checks >= 3.0.1 (niezainstalowane)
Instalowanie http://rocks.tarantool.org/checks-3.0.1-1.rockspec

Klontowanie do '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.
Uwaga: sprawdzanie '580388773ef11085015b5a06fe52d61acf16b201'.

Jesteś w stanie 'detached HEAD'. Możesz rozglądać się, wprowadzać eksperymentalne
zmiany i je zatwierdzać, a także możesz zignorować wszelkie zatwierdzenia, które wprowadzisz w tym
stanie, nie wpływając na żadne gałęzie, wykonując kolejne checkout.

Jeśli chcesz stworzyć nową gałąź, aby zachować dokonane zatwierdzenia, możesz
to zrobić (teraz lub później) używając -b z poleceniem checkout ponownie. Przykład:

  git checkout -b 

Brak istniejącego manifestu. Próbuję odbudować...
checks 3.0.1-1 jest teraz zainstalowane w /.rocks (licencja: BSD)

-- Identyfikacja kompilatora C to GNU 7.5.0
-- Sprawdzenie, czy kompilator C działa: /usr/bin/cc
-- Sprawdzenie, czy kompilator C działa: /usr/bin/cc -- działa
-- Wykrywanie informacji ABI kompilatora C
-- Wykrywanie informacji ABI kompilatora C - zakończone
-- Wykrywanie funkcji kompilacji C
-- Wykrywanie funkcji kompilacji C - zakończone
-- Znaleziono TARANTOOL: /usr/include (znaleziono wersję "2.4.2-80-g18f2bc82d")
-- Tarantool LUADIR to /.rocks/share/tarantool/rocks/http/scm-1/lua
-- Tarantool LIBDIR to /.rocks/share/tarantool/rocks/http/scm-1/lib
-- Konfiguracja zakończona
-- Generowanie zakończone
CMake Warning:
  Ręcznie określone zmienne nie zostały użyte przez projekt:

    version


-- Pliki budowy zostały zapisane do: /tmp/luarocks_http-scm-1-V4P9SM/http/build.luarocks
Skanowanie zależności dla celu httpd
[ 50%] Budowanie obiektu C http/CMakeFiles/httpd.dir/lib.c.o
W pliku zawartym z /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:32:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c: W funkcji ‘tpl_term’:
/usr/include/tarantool/lauxlib.h:144:15: ostrzeżenie: to stwierdzenie może przejść [-Wimplicit-fallthrough=]
    (*(B)->p++ = (char)(c)))
    ~~~~~~~~~~~^~~~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:62:7: uwaga: w rozbudowie makra ‘luaL_addchar’
       luaL_addchar(b, '\');
       ^~~~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:63:6: uwaga: tutaj
      domyślnie:
      ^~~~~~~
W pliku zawartym z /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:39:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h: W funkcji ‘tpe_parse’:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h:147:9: ostrzeżenie: to stwierdzenie może przejść [-Wimplicit-fallthrough=]
    type = TPE_TEXT;
    ~~~~~^~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h:149:3: uwaga: tutaj
   przypadek TPE_LINECODE:
   ^~~~
W pliku zawartym z /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:40:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h: W funkcji ‘httpfast_parse’:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:372:22: ostrzeżenie: to stwierdzenie może przejść [-Wimplicit-fallthrough=]
                 code = 0;
                 ~~~~~^~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:374:13: uwaga: tutaj
             przypadek status:
             ^~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:393:23: ostrzeżenie: to stwierdzenie może przejść [-Wimplicit-fallthrough=]
                 state = message;
                 ~~~~~~^~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:395:13: uwaga: tutaj
             przypadek message:
             ^~~~
[100%] Linkowanie biblioteki współdzielonej C lib.so
[100%] Zbudowany cel httpd
[100%] Zbudowany cel httpd
Zainstaluj projekt...
-- Konfiguracja instalacji: "Debug"
-- Instalowanie: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/VERSION.lua
-- Instalowanie: /.rocks/share/tarantool/rocks/http/scm-1/lib/http/lib.so
-- Instalowanie: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/server/init.lua
-- Instalowanie: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/server/tsgi_adapter.lua
-- Instalowanie: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/nginx_server/init.lua
-- Instalowanie: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/init.lua
-- Instalowanie: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/fs.lua
-- Instalowanie: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/matching.lua
-- Instalowanie: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/middleware.lua
-- Instalowanie: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/request.lua
-- Instalowanie: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/response.lua
-- Instalowanie: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/tsgi.lua
-- Instalowanie: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/utils.lua
-- Instalowanie: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/mime_types.lua
-- Instalowanie: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/codes.lua
http scm-1 jest teraz zainstalowane w /.rocks (licencja: BSD)

root@test2:₩

Do uruchomienia potrzebujemy także prometheus:

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

Klonowanie do 'prometheus'...
remote: Enumerowanie obiektów: 19, gotowe.
remote: Zliczanie obiektów: 100% (19/19), gotowe.
remote: Kompresowanie obiektów: 100% (19/19), gotowe.
remote: Całkowita liczba 19 (delta 2), ponownie użyto 5 (delta 0), pakiet ponownie użyty 0
Odbieranie obiektów: 100% (19/19), 10.73 KiB | 10.73 MiB/s, gotowe.
Rozwiązywanie deltas: 100% (2/2), gotowe.
prometheus scm-1 jest teraz zainstalowany w /.rocks (licencja: BSD)

root@test2:~#

Uruchamiamy i możemy korzystać z modułów

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

Testujemy szybkość

Uruchommy benchmark z 50 000 żądaniami. Równoległych żądań będzie 500.

root@test2:~# ab -c 500 -n 50000 http://127.0.0.1:8080/token
To jest ApacheBench, Wersja 2.3 
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licencjonowane dla Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (bądź cierpliwy)
Zrealizowano 5000 żądań
Zrealizowano 10000 żądań
Zrealizowano 15000 żądań
Zrealizowano 20000 żądań
Zrealizowano 25000 żądań
Zrealizowano 30000 żądań
Zrealizowano 35000 żądań
Zrealizowano 40000 żądań
Zrealizowano 45000 żądań
Zrealizowano 50000 żądań
Zrealizowano 50000 żądań


Oprogramowanie serwera: Tarantool
Nazwa hosta serwera: 127.0.0.1
Port serwera: 8080

Ścieżka dokumentu: /token
Długość dokumentu: 44 bajty

Poziom konkurencyjności: 500
Czas potrzebny na testy: 14.578 sekundy
Kompletne żądania: 50000
Nieudane żądania: 0
Całkowita ilość przesyłanych danych: 7950000 bajtów
HTML przesyłane: 2200000 bajtów
Żądania na sekundę: 3429.87 [# /sec] (średnio)
Czas na żądanie: 145.778 [ms] (średnio)
Czas na żądanie: 0.292 [ms] (średnio, w całym zestawie równoległych żądań)
Wskaźnik transferu: 532.57 [Kbytes /sec] odebrane

Czasy połączeń (ms)
              min  średni[+/-sd] mediana   max
Połączenie:        0   10 103.2      0    3048
Przetwarzanie:    12   69 685.1     15   13538
Oczekiwanie:       12   69 685.1     15   13538
Całkowity:         12   78 768.2     15   14573

Procent żądań zrealizowanych w określonym czasie (ms)
  50%     15
  66%     15
  75%     16
  80%     16
  90%     16
  95%     16
  98%     21
  99%     42
  100%  14573 (najdłuższe żądanie)
root@test2:~#

Tokeny są wydawane. I stale zapisujemy dane. 99% żądań zostało obsłużonych w ciągu 42 milisekund. Oznacza to, że osiągamy około 3500 żądań na sekundę na małej maszynie, która ma 2 rdzenie i 4 gigabajty pamięci.

Można również wybrać jakiś 50000-token i sprawdzić jego wartość.

Można używać nie tylko http, uruchamiać funkcje w tle, które przetwarzają twoje dane. Dodatkowo dostępne są różne wyzwalacze. Na przykład, możesz wywoływać funkcje przy aktualizacjach, coś sprawdzać – naprawiać konflikty.

Można pisać aplikacje-skrypty bezpośrednio na serwerze bazy danych, nie mając żadnych ograniczeń, podłączać dowolne moduły i realizować dowolną logikę.

Serwer aplikacji może łączyć się z zewnętrznymi serwerami, pobierać dane i przechowywać je w swojej bazie. Dane z tej bazy będą używane przez inne aplikacje.

To będzie robił sam Tarantool, więc nie trzeba będzie pisać osobnej aplikacji.

Na zakończenie

To dopiero pierwsza część dużej pracy. Druga zostanie opublikowana już wkrótce na blogu Mail.ru Group, a my na pewno dodamy do niej link w tym materiale.

Jeśli chcesz uczestniczyć w wydarzeniach, gdzie tworzymy takie rzeczy na żywo i zadawać pytania w czasie rzeczywistym, dołącz do kanału DevOps by REBRAIN.

Jeśli potrzebujesz migracji do chmury lub masz pytania dotyczące swojej infrastruktury, śmiało zostawiaj zgłoszenie.

P.S. Mamy dwa bezpłatne audyty miesięcznie, być może to właśnie Twój projekt znajdzie się w ich gronie.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster