Dans Tarantool, vous pouvez combiner une base de données et une application ultra-rapides pour travailler avec elles. Voilà comment c'est facile

Il y a cinq ans, j'ai essayé de travailler avec Tarantool, mais cela ne m'est pas venu. Mais récemment, j'ai organisé un webinaire où j'ai parlé de Hadoop, du fonctionnement de MapReduce. Là, on m'a posé une question - "Pourquoi ne pas utiliser Tarantool pour cette tâche?"



Par curiosité, j'ai décidé d'y revenir, de tester la dernière version - et cette fois j'ai beaucoup aimé le projet. Maintenant, je vais vous montrer comment écrire une application simple dans Tarantool, la charger et tester les performances, et vous verrez à quel point tout est facile et cool.







Qu'est-ce que Tarantool



Tarantool se positionne comme une base de données ultra-rapide. Vous pouvez y envoyer toutes les données de votre choix. De plus, répliquez-les, fragmentez - c'est-à-dire divisez une énorme quantité de données sur plusieurs serveurs et combinez les résultats à partir de ceux-ci - pour créer des ensembles «maître-maître» tolérants aux pannes.



Deuxièmement, c'est un serveur d'applications. Vous pouvez y écrire vos applications, travailler avec des données, par exemple supprimer d'anciens enregistrements en arrière-plan selon certaines règles. Vous pouvez écrire un serveur Http directement dans Tarantula, qui fonctionnera avec les données: émettez leur quantité, y écrivez de nouvelles données et réduisez tout cela au maître.



J'ai lu un article sur la façon dont les gars ont créé une file d'attente de messages de 300 lignes qui se déchire et s'envole - ils ont une performance minimale de 20 000 messages par seconde. Ici, vous pouvez vraiment développer et écrire une application très volumineuse, et elle ne sera pas stockée comme dans PostgreS.



À propos d'un tel serveur, juste un simple, je vais essayer de le décrire dans cet article.



Installation



Pour le test, j'ai démarré trois machines virtuelles standard - un disque dur de 20 gigaoctets, Ubuntu 18.04. 2 CPU virtuels et 4 gigaoctets de mémoire.



Nous installons Tarantool - exécutons le script bash ou ajoutons un référentiel et faisons installer Tarantool. Le lien vers le script est (curl -L https://tarantool.io/installer.sh | VER = 2.4 sudo -E bash). Nous avons des commandes telles que:



tarantoolctl - la commande principale pour gérer les instances de Tarantula.

/ etc / tarantool - toute la configuration se trouve ici.

var / log / tarantool - c'est là que se trouvent les journaux.

var / lib / tarantool - c'est là que les données sont stockées , puis elles sont divisées en instances.



Il existe des dossiers disponibles et activables pour l'instance - il contient ce qui sera lancé - un fichier de configuration d'instance avec du code lua, qui décrit sur quels ports il écoute, quelle mémoire est disponible, les paramètres du moteur Vinyl, le code qui est déclenché au démarrage serveurs, partitionnement, files d'attente, suppression de données obsolètes, etc.



Les instances fonctionnent comme PostgreS. Par exemple, vous souhaitez exécuter plusieurs copies d'une base de données qui se bloque sur différents ports. Il s'avère que plusieurs instances de base de données sont lancées sur le même serveur, qui se bloquent sur des ports différents. Ils peuvent avoir des paramètres complètement différents - une instance implémente une logique, la seconde - une autre.



Gestion des instances



Nous avons la commande tarantoolctl qui vous permet de gérer vos instances Tarantula. Par exemple, tarantoolctl check example vérifiera le fichier de configuration et dira - le fichier est ok s'il n'y a pas d'erreurs de syntaxe.



Vous pouvez voir l'état de l'instance - exemple d'état tarantoolctl. De la même manière, vous pouvez démarrer, arrêter, redémarrer.



Lorsque l'instance est en cours d'exécution, il existe deux façons de s'y connecter.



1. Console d'administration



Par défaut, Tarantool ouvre un socket, où il transmet du texte ASCII brut pour contrôler la Tarantula. La connexion à la console se fait toujours sous l'utilisateur admin, il n'y a pas d'authentification, vous n'avez donc pas besoin de déplacer le port de la console pour gérer la Tarantula.



Pour vous connecter de cette manière, entrez Tarantoolctl entrez le nom de l'instance. La commande lancera la console et se connectera en tant qu'utilisateur admin. N'exposez jamais le port de la console à l'extérieur - il est préférable de le laisser comme prise d'unité. Ensuite, seuls ceux qui ont accès en écriture au socket pourront se connecter à la Tarantula.



Cette méthode est nécessaire pour les choses administratives. Pour travailler avec des données, utilisez la deuxième méthode - le protocole binaire.



2. Utilisation d'un protocole binaire pour se connecter à un port spécifique



Il existe une directive d'écoute dans la configuration, qui ouvre le port pour les communications externes. Ce port est utilisé avec un protocole binaire et l'authentification y est activée.



Pour cette connexion, tarantoolctl connect to port number est utilisé. En l'utilisant, vous pouvez vous connecter à des serveurs distants, utiliser l'authentification et donner divers droits d'accès.



Enregistreur de données et module Box



Étant donné que Tarantool est à la fois une base de données et un serveur d'applications, il dispose de divers modules. Nous sommes intéressés par le module box - il implémente le travail avec des données. Lorsque vous écrivez quelque chose dans la boîte, Tarantool écrit les données sur le disque, les stocke en mémoire ou fait autre chose avec.



Enregistrement



Par exemple, nous allons dans le module box et appelons la fonction box.once. Cela obligera Tarantool à exécuter notre code lorsque le serveur sera initialisé. Nous créons un espace dans lequel nos données seront stockées.



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

    -- Keep things safe by default
    --  box.schema.user.create('example', { password = 'secret' })
    --  box.schema.user.grant('example', 'replication')
    --  box.schema.user.grant('example', 'read,write,execute', 'space', 'example')
end


Après cela, nous créons un index primaire - primaire - par lequel nous pouvons rechercher des données. Par défaut, si vous ne spécifiez aucun paramètre, le premier champ de chaque entrée pour l'index d'amorce sera utilisé.



Ensuite, nous accordons une subvention à l'utilisateur invité, sous laquelle nous nous connectons via un protocole binaire. Autoriser la lecture, l'écriture et l'exécution sur l'ensemble de l'instance.



Comparé aux bases de données conventionnelles, tout est assez simple ici. Nous avons un espace - une zone qui stocke simplement nos données. Chaque entrée est appelée un tuple. Il est emballé dans un MessagePack. C'est un format très cool - il est binaire et prend moins de place - 18 octets contre 27.







Il est assez pratique de travailler avec. Presque chaque ligne, chaque enregistrement de données peut avoir des colonnes complètement différentes.



Nous pouvons regarder tous les espaces en utilisant la commande Box.space. Pour sélectionner une instance spécifique - écrivez l'exemple box.space et obtenez des informations complètes à ce sujet.



Tarantool a deux moteurs intégrés: Memory et Vinyl. La mémoire stocke toutes les données en mémoire. Par conséquent, tout fonctionne simplement et rapidement. Les données sont sauvegardées sur le disque, et il existe également un mécanisme de journalisation en écriture anticipée, nous ne perdrons donc rien si le serveur tombe en panne.



Le vinyle stocke les données sur le disque sous une forme plus familière - c'est-à-dire que vous pouvez stocker plus de données que nous n'avons de mémoire, et la Tarantula les lira à partir du disque.



Nous allons maintenant utiliser 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:



L'index principal doit être créé pour n'importe quel espace, car sans lui rien ne fonctionnera. Comme pour toute base de données, nous créons le premier champ - l'ID d'enregistrement.



Parties:



Ici, nous indiquons en quoi consiste notre index. Il se compose d'une partie - le premier champ que nous utiliserons est non signé, un entier positif. Comme je me souviens de la documentation, le nombre maximum qui peut être est de 18 quintillions. Beaucoup de choses.



Ensuite, nous pouvons insérer des données à l'aide de la commande 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>


Le premier champ est utilisé comme clé primaire, il doit donc être unique. Nous ne sommes pas limités par le nombre de colonnes, nous pouvons donc insérer autant de données que nous le souhaitons. Ils sont spécifiés dans le format MessagePack que j'ai décrit ci-dessus.



Sortie de données



Ensuite, nous pouvons afficher les données avec la commande select.



Box.example.select avec la touche {1} affichera l'enregistrement requis. Si nous omettons la clé, nous verrons tous les enregistrements que nous avons. Ils sont tous différents dans le nombre de colonnes, mais ici, en principe, il n'y a pas de concept de colonnes - il y a des numéros de champ.



Il peut y avoir absolument n'importe quelle quantité de données. Et par exemple, nous devons les rechercher par le deuxième champ. Pour cela, nous créons un nouvel index secondaire.




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


Nous utilisons la commande Create_index.

Nous l'appelons Secondaire.



Après cela, vous devez spécifier les paramètres. Le type d'index est TREE. Il peut ne pas être unique, nous entrons donc Unique = false.



Ensuite, nous indiquons les parties de notre index. Field est le numéro du champ auquel nous lions l'index et spécifiez la chaîne de type. Et c'est ainsi qu'il a été créé.



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>


Maintenant, voici comment nous pouvons l'appeler:



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


Préservation



Si nous redémarrons l'instance et essayons d'appeler à nouveau les données, nous verrons qu'elles ne sont pas là - tout est vide. Cela se produit parce que Tarantool crée des points de contrôle et enregistre les données sur le disque, mais si nous arrêtons de travailler avant la prochaine sauvegarde, nous perdrons toutes les opérations - car nous récupérerons à partir du dernier point de contrôle, qui était, par exemple, il y a deux heures.



Enregistrer chaque seconde ne fonctionnera pas non plus - car le vidage constant de 20 Go sur le disque est moyen.



Pour cela, le concept de journal à écriture anticipée a été inventé et implémenté. Il crée une entrée dans un petit fichier journal à écriture anticipée pour chaque modification des données.



Chaque entrée avant le point de contrôle y est enregistrée. Pour ces fichiers, nous définissons la taille - par exemple, 64 Mo. Lorsqu'il se remplit, l'enregistrement commence à aller au deuxième fichier. Et après le redémarrage, Tarantool restaure à partir du dernier point de contrôle, puis annule toutes les transactions ultérieures jusqu'à ce qu'il s'arrête.







Pour effectuer un tel enregistrement, vous devez spécifier l'option dans les paramètres box.cfg (dans le fichier example.lua):



wal_mode = “write”;


l'utilisation de données



Avec ce que nous avons écrit maintenant, vous pouvez utiliser la Tarantula pour stocker des données, et cela fonctionnera très rapidement comme base de données. Et maintenant, la cerise sur le gâteau - que pouvez-vous faire de tout.



Rédaction d'une candidature



Par exemple, écrivons une telle application pour Tarantula



Voir l'application sous le 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; -- one hour
    checkpoint_count = 6;
    force_recovery = true;
    log_level = 5;
    log_nonblock = false;
    too_long_threshold = 0.5;
    read_only   = false
}

local function bootstrap()
    local space = box.schema.create_space('example')
    space:create_index('primary')

    box.schema.user.create('example', { password = 'secret' })
    box.schema.user.grant('example', 'read,write,execute', 'space', 'example')

    box.schema.user.create('repl', { password = 'replication' })
    box.schema.user.grant('repl', 'replication')
end

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

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

-- http config
local charset = {}  do -- [0-9a-zA-Z]
    for c = 48, 57  do table.insert(charset, string.char(c)) end
    for c = 65, 90  do table.insert(charset, string.char(c)) end
    for c = 97, 122 do table.insert(charset, string.char(c)) end
end

local function randomString(length)
    if not length or length <= 0 then return '' end
    math.randomseed(os.clock()^5)
    return randomString(length - 1) .. charset[math.random(1, #charset)]
end

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

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

local router = http_router.new()

local function get_count()
 local cnt = box.space.example:len()
 return cnt
end

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

router:route({method = 'GET', path = '/token'}, function()
    local token = randomString(32)
    local last = box.space.example:len()
    box.space.example:insert{ last + 1, token }
    return {status = 200, body = json.encode({token = token})}
end)

prometheus = require('prometheus')

fiber = require('fiber')
tokens_count = prometheus.gauge("tarantool_tokens_count",
                              "API Tokens Count")

function monitor_tokens_count()
  while true do
    tokens_count:set(get_count())
    fiber.sleep(5)
  end
end
fiber.create(monitor_tokens_count)

router:route( { method = 'GET', path = '/metrics' }, prometheus.collect_http)

httpd:set_router(router)
httpd:start()




Nous déclarons une étiquette dans lua qui définit des symboles. Cette plaque est nécessaire pour générer une ligne aléatoire.



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


Après cela, nous déclarons une fonction - randomString et donnons la valeur de longueur entre parenthèses.



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


Ensuite, nous connectons le routeur http et le serveur http à notre serveur Tarantula, JSON, que nous enverrons au client.



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


Après cela, nous commençons sur le port 8080 sur toutes les interfaces du serveur http, qui enregistrera toutes les requêtes et erreurs.



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


Ensuite, nous déclarons route que si une requête avec la méthode GET arrive au port 8080 / count, alors nous appelons la fonction à partir d'une ligne. Il renvoie le statut - 200, 404, 403 ou tout ce que nous spécifions.



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


Dans le corps, nous retournons json.encode, dans lequel nous spécifions count et getcount, qui est appelé et montre le nombre d'enregistrements dans notre base de données.



Deuxième méthode



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)


Où dans la ligne router: route ({method = ' GET', path = '/ token'}, function () , nous appelons la fonction et générons un jeton.



Bar local token = randomString (32) - est une chaîne Randomnaya de 32 caractères.

Ligne local last = box.space.example: len () nous sortons le dernier élément,

et dans la ligne box.space.example: insert {last + 1, token} nous écrivons dans notre base de données, c'est-à-dire que nous augmentons simplement l'ID de 1. Cela peut être fait au fait, non seulement d'une manière aussi maladroite. Dans Tarantula, il y a des séquences pour cette entreprise. Nous y



écrivons un jeton.



Ainsi, nous avons écrit une application dans un seul fichier. Dans celui-ci, vous pouvez immédiatement gérer les données, et le module box fera tout le sale boulot pour vous ...



Il écoute http et fonctionne avec des données, tout est dans une seule instance - à la fois l'application et les données. Par conséquent, tout se passe assez rapidement.



Pour exécuter, nous installons le module http:



Comment on fait, regarde sous le spoiler
root@test2:/# tarantoolctl rocks install http
Installing http://rocks.tarantool.org/http-scm-1.src.rock
Missing dependencies for http scm-1:
   checks >= 3.0.1 (not installed)

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

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

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

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

  git checkout -b <new-branch-name>

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

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

    version


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

root@test2:/#




Nous avons également besoin de prometheus pour exécuter:



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

Cloning into 'prometheus'...
remote: Enumerating objects: 19, done.
remote: Counting objects: 100% (19/19), done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 19 (delta 2), reused 5 (delta 0), pack-reused 0
Receiving objects: 100% (19/19), 10.73 KiB | 10.73 MiB/s, done.
Resolving deltas: 100% (2/2), done.
prometheus scm-1 is now installed in /.rocks (license: BSD)

root@test2:/#


Nous commençons et pouvons accéder aux modules



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 nous donne le statut 200.

/ token émet un token et écrit ce token dans la base de données.



Vitesse de test



Exécutons un benchmark avec 50 000 requêtes. Il y aura 500 demandes concurrentielles.



root@test2:/# ab -c 500 -n 50000 http://127.0.0.1:8080/token
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)
Completed 5000 requests
Completed 10000 requests
Completed 15000 requests
Completed 20000 requests
Completed 25000 requests
Completed 30000 requests
Completed 35000 requests
Completed 40000 requests
Completed 45000 requests
Completed 50000 requests
Finished 50000 requests


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

Document Path:          /token
Document Length:        44 bytes

Concurrency Level:      500
Time taken for tests:   14.578 seconds
Complete requests:      50000
Failed requests:        0
Total transferred:      7950000 bytes
HTML transferred:       2200000 bytes
Requests per second:    3429.87 [#/sec] (mean)
Time per request:       145.778 [ms] (mean)
Time per request:       0.292 [ms] (mean, across all concurrent requests)
Transfer rate:          532.57 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   10 103.2      0    3048
Processing:    12   69 685.1     15   13538
Waiting:       12   69 685.1     15   13538
Total:         12   78 768.2     15   14573

Percentage of the requests served within a certain time (ms)
  50%     15
  66%     15
  75%     16
  80%     16
  90%     16
  95%     16
  98%     21
  99%     42
 100%  14573 (longest request)
root@test2:/#


Les jetons sont émis. Et nous enregistrons constamment des données. 99% des demandes ont été traitées en 42 millisecondes. En conséquence, nous avons environ 3500 requêtes par seconde sur une petite machine, où il y a 2 cœurs et 4 gigaoctets de mémoire.



Vous pouvez également sélectionner environ 50 000 jetons et voir sa valeur.



Vous pouvez utiliser non seulement http, vous pouvez exécuter des fonctions d'arrière-plan qui traitent vos données. De plus, il existe divers déclencheurs. Par exemple, vous pouvez appeler des fonctions sur les mises à jour, vérifier quelque chose - résoudre les conflits.



Vous pouvez écrire des scripts d'application directement dans le serveur de base de données lui-même, sans vous limiter à quoi que ce soit, connecter des modules et implémenter n'importe quelle logique.



Le serveur d'applications peut accéder à des serveurs externes, collecter des données et les stocker dans sa base de données. Les données de cette base de données seront utilisées par d'autres applications.



Cela sera fait par Tarantula lui-même, et il n'est pas nécessaire d'écrire une application séparée.



finalement



Ce n'est que la première partie de beaucoup de travail. Le second sera publié très prochainement sur le blog du groupe Mail.ru, et nous y ajouterons certainement un lien dans cet article.



Si vous souhaitez assister à des événements où nous créons de telles choses en ligne et posons des questions en temps réel, rejoignez le canal DevOps by REBRAIN .



Si vous avez besoin d'une migration vers le cloud ou avez des questions sur votre infrastructure, n'hésitez pas à laisser une demande .



PS Nous avons 2 audits gratuits par mois, peut-être que votre projet en fera partie.



All Articles