Dans Tarantool, vous pouvez combiner une base de données ultra-rapide et une application pour travailler avec eux. Voici à quel point c'est facile à faire

Il y a cinq ans, j'ai essayé de travailler avec Tarantool, mais cela n'a pas fonctionné pour moi. Mais récemment, j'ai organisé un webinaire où j'ai parlé de Hadoop, du fonctionnement de MapReduce. Là, on m'a posé la 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 vraiment aimé le projet. Maintenant, je vais montrer comment écrire une application simple dans Tarantool, la charger et vérifier les performances, et vous verrez à quel point tout est simple et cool.

Dans Tarantool, vous pouvez combiner une base de données ultra-rapide et une application pour travailler avec eux. Voici à quel point c'est facile à faire

Qu'est-ce que Tarantool

Tarantool se positionne comme une base de données ultra-rapide. Vous pouvez y mettre toutes les données que vous voulez. De plus, répliquez-les, fragmentez - c'est-à-dire divisez une énorme quantité de données sur plusieurs serveurs et combinez leurs résultats - créez des liens maître-maître tolérants aux pannes.

Deuxièmement, c'est un serveur d'applications. Vous pouvez écrire vos applications dessus, travailler avec des données, par exemple, supprimer les anciennes entrées en arrière-plan selon certaines règles. Vous pouvez écrire un serveur Http directement dans Tarantula qui fonctionnera avec des données : donnez leur numéro, écrivez-y de nouvelles données et réduisez le tout à un 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 se déchire - ils ont une performance minimale de 20 000 messages par seconde. Ici, vous pouvez vraiment faire demi-tour et écrire une application très volumineuse, et celles-ci ne seront pas stockées, comme dans PostgreS.

Environ un tel serveur, seulement simple, je vais essayer de 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 processeurs virtuels et 4 gigaoctets de mémoire.

Nous installons Tarantool - exécutez un script bash ou ajoutez un référentiel et installez Tarantool. Lien vers le script - (curl -L https://tarantool.io/installer.sh | VER=2.4 sudo -E bash). Nous avons des commandes comme :

tarantoolctl est la commande principale de gestion des instances de Tarantula.
/etc/tarantool - ici se trouve toute la configuration.
var/log/tarantool - voici les journaux.
var/lib/tarantool - ici se trouvent les données, puis elles sont divisées en instances.

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

Les instances fonctionnent comme dans 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 un serveur, qui se bloquent sur différents ports. 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 nous permet de gérer les instances de Tarantula. Par exemple, tarantoolctl check example vérifiera le fichier de configuration et dira que le fichier est correct s'il n'y a pas d'erreurs de syntaxe.

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

Une fois qu'une 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 et envoie du texte ASCII brut pour contrôler la tarentule. La connexion à la console se produit toujours sous l'utilisateur admin, il n'y a pas d'authentification, vous n'avez donc pas besoin de retirer le port de la console pour contrôler la tarentule à l'extérieur.

Pour vous connecter de cette manière, vous devez entrer Tarantoolctl entrer le nom de l'instance. La commande lancera la console et se connectera en tant qu'utilisateur administrateur. 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 un accès en écriture à la prise pourront se connecter à Tarantula.

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

2. Utiliser un protocole binaire pour se connecter à un port spécifique

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

Pour cette connexion, tarantoolctl se connecte au numéro de port est utilisé. En l'utilisant, vous pouvez vous connecter à des serveurs distants, utiliser l'authentification et donner divers droits d'accès.

Module d'enregistrement de données et de boîte

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

Record

Par exemple, nous entrons dans le module box et appelons la fonction box.once. Cela forcera Tarantool à exécuter notre code lorsque le serveur sera initialisé. Nous créons un espace où 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 aucun paramètre n'est spécifié, le premier champ de chaque entrée pour l'index d'amorce sera utilisé.

Ensuite, nous accordons une subvention à l'utilisateur invité, en vertu de laquelle nous nous connectons via un protocole binaire. Nous autorisons la lecture, l'écriture et l'exécution dans toute l'instance.

Par rapport aux bases de données classiques, tout est assez simple ici. Nous avons de l'espace - une zone dans laquelle nos données sont simplement stockées. Chaque entrée est appelée un tuple. Il est conditionné dans un MessagePack. C'est un format très sympa - il est binaire et prend moins de place - 18 octets contre 27.

Dans Tarantool, vous pouvez combiner une base de données ultra-rapide et une application pour travailler avec eux. Voici à quel point c'est facile à faire

C'est assez pratique de travailler avec lui. Presque chaque ligne, chaque entrée de données peut avoir des colonnes complètement différentes.

Nous pouvons afficher tous les espaces à l'aide de la commande Box.space. Pour sélectionner une instance spécifique, nous écrivons box.space example et obtenons des informations complètes à ce sujet.

Il existe deux types de moteurs intégrés à Tarantool : 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 déversées sur le disque et il existe également un mécanisme de journal d'écriture anticipée, de sorte que nous ne perdrons rien si le serveur tombe en panne.

Vinyl stocke les données sur disque sous une forme plus familière - c'est-à-dire que vous pouvez stocker plus de données que nous n'en avons de mémoire, et 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>

Indice:

Un index primaire doit être créé pour tout espace, car rien ne fonctionnera sans lui. Comme dans toute base de données, nous créons le premier champ - l'ID d'enregistrement.

Pièces:

C'est ici que nous spécifions en quoi consiste notre index. Il se compose d'une partie - le premier champ que nous utiliserons, de type non signé - un entier positif. Autant que je me souvienne de la documentation, le nombre maximum qui peut être est de 18 quintillions. Beaucoup de génial.

Nous pouvons ensuite 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 y 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'entrée souhaitée. 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 autant de données que vous le souhaitez. Et par exemple, nous devons les rechercher dans le deuxième champ. Pour ce faire, 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 en quelles parties notre index est composé. Field est le numéro du champ auquel nous lions l'index et spécifie le type de chaîne. 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, c'est comme ça qu'on peut 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 du dernier point de contrôle, qui était, par exemple, il y a deux heures.

Sauvegarder chaque seconde ne fonctionnera pas non plus - car le vidage constant de 20 Go sur le disque est une idée moyenne.

Pour cela, le concept de journal à écriture anticipée a été inventé et mis en œuvre. Avec son aide, pour chaque modification des données, un enregistrement est créé dans un petit fichier journal à écriture anticipée.

Chaque entrée jusqu'au point de contrôle y est stockée. Pour ces fichiers, nous définissons la taille - par exemple, 64 Mo. Lorsqu'il est plein, l'enregistrement commence à passer au deuxième fichier. Et après le redémarrage, Tarantool récupère du dernier point de contrôle, puis reconduit toutes les transactions ultérieures jusqu'à ce qu'il s'arrête.

Dans Tarantool, vous pouvez combiner une base de données ultra-rapide et une application pour travailler avec eux. Voici à quel point c'est facile à faire

Pour effectuer un tel enregistrement, vous devez spécifier une option dans les paramètres de 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 tarentule 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 avec tout cela.

Rédaction d'une candidature

Par exemple, écrivons une telle application pour la tarentule

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 table en lua qui définit les symboles. Cette table est nécessaire pour générer une chaîne 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 donnerons 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 de 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 une route que si une requête avec la méthode GET arrive sur le port 8080 /count, alors nous appelons la fonction à partir d'une ligne. Il renvoie un 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 renvoyons json.encode, nous y spécifions count et getcount, qui est appelé et affiche le nombre d'enregistrements dans notre base de données.

La 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.

Rangée jeton local = randomString(32) est une chaîne aléatoire de 32 caractères.
En ligne local dernier = box.space.example:len() nous retirons le dernier élément.
Et dans la ligne box.space.example:insert{ dernier + 1, jeton } nous écrivons les données dans notre base de données, c'est-à-dire que nous augmentons simplement l'ID de 1. Cela peut être fait, soit dit en passant, non seulement de manière aussi maladroite. Tarantula a des séquences pour cette affaire.

Nous y écrivons le jeton.

Ainsi, nous avons écrit une application dans un seul fichier. Vous pouvez accéder aux données tout de suite, et le module box fera tout le sale boulot pour vous.

Il écoute http et travaille 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, voir 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 function ‘tpl_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 function ‘tpe_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 function ‘httpfast_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 jeton et écrit ce jeton dans la base de données.

Vitesse de test

Exécutons un benchmark pour 50 000 requêtes. Les demandes concurrentielles seront de 500.

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 requêtes 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 50000 XNUMX jetons et voir sa valeur.

Vous pouvez utiliser non seulement http, exécuter des fonctions d'arrière-plan qui traitent vos données. De plus, il existe différents 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 applications de script directement dans le serveur de base de données lui-même, sans être limité par quoi que ce soit, connecter n'importe quel module et implémenter n'importe quelle logique.

Le serveur d'application peut accéder à des serveurs externes, collecter des données et les ajouter à 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 la tarentule elle-même, et il n'est pas nécessaire d'écrire une application distincte.

En conclusion

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

Si vous souhaitez assister à des événements où nous créons ces choses en ligne et poser des questions en temps réel, connectez-vous à DevOps par canal REBRAIN.

Si vous avez besoin de migrer vers le cloud ou avez des questions sur votre infrastructure, N'hésitez pas à faire une demande.

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

Source: habr.com

Ajouter un commentaire