En Tarantool se puede combinar una base de datos ultrarrápida y una aplicación para trabajar con ella. Así de simple es hacerlo.

Hace cinco años intenté trabajar con Tarantool, pero en ese momento no me convenció. Sin embargo, recientemente realicé un seminario web en el que hablé sobre Hadoop y cómo funciona MapReduce. Allí me hicieron la pregunta: "¿Por qué no utilizar Tarantool para esta tarea?".

Por curiosidad, decidí volver a él, probar la última versión, y esta vez el proyecto me gustó mucho. Ahora les mostraré cómo escribir una aplicación simple en Tarantool, la cargaré y verificaré el rendimiento, y verán lo fácil y genial que es.

En Tarantool se puede combinar una base de datos ultrarrápida y una aplicación para trabajar con ella. Así de simple es hacerlo.

¿Qué es Tarantool?

Tarantool se posiciona como una base de datos ultrarrápida. Se pueden almacenar los datos que se deseen. Además, se pueden replicar y fragmentar, es decir, dividir una gran cantidad de datos en varios servidores y combinar los resultados, creando configuraciones tolerantes a fallas tipo "maestro-maestro".

En segundo lugar, es un servidor de aplicaciones. Puede escribir sus propias aplicaciones en él, trabajar con los datos, por ejemplo, eliminando en segundo plano registros antiguos según ciertas reglas. Se puede crear directamente en Tarantool un servidor Http que trabaje con los datos: devuelva la cantidad de datos, inserte nuevos datos y reduzca todo esto al maestro.

Leí un artículo sobre cómo un grupo de chicos creó una cola de mensajes de 300 líneas que simplemente vuela: tienen un rendimiento mínimo de 20,000 mensajes por segundo. Aquí realmente se puede desplegar y escribir una aplicación muy grande, y no serán bases de datos como en PostgreSQL.

Un servidor más o menos así, pero simple, es lo que intentaré describir en este artículo.

Instalación

Para la prueba, configuré tres máquinas virtuales estándar: un disco duro de 20 gigabytes, Ubuntu 18.04. 2 CPU virtuales y 4 gigas de memoria.

Instalamos Tarantool: ejecutamos un script de bash o añadimos el repositorio y hacemos apt get install Tarantool. El enlace al script es (curl -L https://tarantool.io/installer.sh | VER=2.4 sudo -E bash). Ahora tenemos comandos como:

tarantoolctl — el comando principal para gestionar las instancias de Tarantool.
/etc/tarantool — aquí se encuentra toda la configuración.
var/log/tarantool — aquí se encuentran los registros.
var/lib/tarantool — aquí se encuentran los datos, que luego están repartidos entre las instancias.

Existen las carpetas instance-available e instance-enable; en esta última se encuentra lo que se ejecutará: el archivo de configuración de la instancia con código lua, donde se describe en qué puertos escucha, qué memoria tiene disponible, la configuración del motor Vinyl, el código que se ejecuta al iniciar el servidor, el sharding, las colas, la eliminación de datos obsoletos, y así sucesivamente.

Los instancias funcionan como en PostgreS. Por ejemplo, si desea ejecutar varias copias de la base de datos, que está en diferentes puertos. Esto significa que en un servidor se ejecutan varias instancias de bases de datos, que están en diferentes puertos. Pueden tener configuraciones completamente diferentes: una instancia implementa una lógica, la segunda implementa otra.

Gestión de instancias

Tenemos el comando tarantoolctl, que permite gestionar las instancias de Tarantool. Por ejemplo, tarantoolctl check example revisará el archivo de configuración y dirá — el archivo está bien, si no hay errores de sintaxis.

Se puede ver el estado de la instancia — tarantoolctl status example. De la misma manera se puede hacer start, stop, restart.

Cuando la instancia está en ejecución, se puede conectar de dos maneras.

1. Consola administrativa

Por defecto, Tarantool abre un socket, donde se transmite texto ASCII normal para gestionar Tarantool. La conexión a la consola siempre se realiza como el usuario admin, no hay autenticación, por lo que no es necesario exponer el puerto de la consola para gestionar Tarantool externamente.

Para conectarse de esta manera, debe introducir Tarantoolctl enter instance name. El comando abrirá la consola y se conectará como el usuario admin. Nunca exponga el puerto de la consola al exterior; es mejor dejarlo como un socket de unidad. De esta manera, solo aquellos que tienen acceso de escritura al socket podrán conectarse a Tarantool.

Este método es necesario para tareas administrativas. Para trabajar con datos, utilice el segundo método: el protocolo binario.

2. Uso del protocolo binario para conectarse a un puerto específico

En la configuración hay una directiva listen, que abre un puerto para comunicaciones externas. Este puerto se utiliza con el protocolo binario y tiene habilitada la autenticación.

Para esta conexión se utiliza tarantoolctl connect to port number. Usando este comando, se puede conectar a servidores remotos, utilizar autenticación y otorgar diferentes permisos de acceso.

Registro de datos y módulo Box

Dado que Tarantool es tanto una base de datos como un servidor de aplicaciones, cuenta con varios módulos. Nos interesa el módulo box: se encarga del manejo de datos. Cuando escribes algo en el box, Tarantool guarda los datos en el disco, los mantiene en memoria o hace algo más con ellos.

Escritura

Por ejemplo, entramos en el módulo box y llamamos a la función box.once. Esta hará que Tarantool ejecute nuestro código al inicializar el servidor. Creamos un espacio donde se almacenarán nuestros datos.

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

    -- Mantener las cosas seguras por defecto
    --  box.schema.user.create('example', { password = 'secret' })
    --  box.schema.user.grant('example', 'replication')
    --  box.schema.user.grant('example', 'read,write,execute', 'space', 'example')
end

Después de esto, creamos un índice primario – primary – por el que se podrá buscar información. Por defecto, si no se especifican parámetros, se usará el primer campo de cada registro para el índice primario.

Luego, otorgamos permisos al usuario guest, con el que nos conectamos a través del protocolo binario. Permitimos leer, escribir y ejecutar en toda la instancia.

Comparado con las bases de datos convencionales, aquí todo es bastante simple. Tenemos un space: un área donde simplemente se almacenan nuestros datos. Cada registro se llama tuple. Se empaqueta en MessagePack. Es un formato muy interesante: es binario y ocupa menos espacio: 18 bytes frente a 27.

En Tarantool se puede combinar una base de datos ultrarrápida y una aplicación para trabajar con ella. Así de simple es hacerlo.

Es bastante conveniente trabajar con él. Casi cada línea, cada registro de datos puede tener columnas completamente diferentes.

Podemos ver todos los spaces utilizando el comando Box.space. Para destacar una instancia específica, escribimos box.space example y obtenemos toda la información sobre ella.

Tarantool incluye dos tipos de motores: Memory y Vinyl. Memory guarda todos los datos en memoria, por lo tanto, todo funciona de forma simple y rápida. Los datos se guardan en disco, y también hay un mecanismo de write ahead log, por lo que no perderemos nada si el servidor falla.

Vinyl almacena los datos en disco de una manera más familiar para nosotros; es decir, se pueden almacenar más datos de los que tenemos en memoria, y Tarantool los leerá desde el disco.

Ahora usaremos 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>

Índice:

Es necesario crear un índice primario para cualquier espacio, porque sin él nada funcionará. Al igual que en cualquier base de datos, creamos el primer campo: el ID de la entrada.

Partes:

Aquí especificamos de qué está compuesto nuestro índice. Se compone de una parte: el primer campo que utilizaremos, tipo unsigned — un número entero positivo. Según recuerdo de la documentación, el número máximo puede ser 18 quintillones. Es un número increíblemente grande.

A continuación, podemos insertar datos utilizando el comando insert.

unix/:/var/run/tarantool/example.control> box.space.example:insert{1, 'test1', 'test2'}
---
- [1, 'test1', 'test2']
...

unix/:/var/run/tarantool/example.control> box.space.example:insert{2, 'test2', 'test3', 'test4'}
---
- [2, 'test2', 'test3', 'test4']
...

unix/:/var/run/tarantool/example.control> box.space.example:insert{3, 'test3'}
---
- [3, 'test3']
...

unix/:/var/run/tarantool/example.control> box.space.example:insert{4, 'test4'}
---
- [4, 'test4']
...

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

El primer campo se utiliza como clave primaria, por lo que debe ser único. No tenemos un límite en la cantidad de columnas, por lo que podemos insertar tantos datos como queramos. Estos se especifican en formato MessagePack, como mencioné anteriormente.

Salida de datos

Luego podemos mostrar los datos con el comando select.

Box.example.select con la clave {1} mostrará la entrada deseada. Si omitemos la clave, veremos todas las entradas que tenemos. Todas son diferentes en la cantidad de columnas, pero aquí en principio no hay un concepto de columnas, solo hay números de campo.

Puede haber absolutamente muchos datos. Por ejemplo, necesitamos buscarlos por el segundo campo. Para eso, hacemos un nuevo índice secundario.


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

Usamos el comando Create_index.
Lo llamamos Secundario.

Después de eso, necesitamos especificar los parámetros. El tipo de índice es TREE. Puede que no sea único, así que lo ingresamos Unique = false.

Luego especificamos de qué partes está compuesto nuestro índice. Field — este es el número del campo al que vinculamos el índice, y especificamos el tipo string. Y así se creó.

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>

Ahora podemos invocarlo de esta manera:

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

Guardar

Si reiniciamos la instancia y volvemos a intentar obtener los datos, veremos que no hay nada: todo está vacío. Esto sucede porque Tarantool hace puntos de control y guarda los datos en disco, pero si detenemos el trabajo antes del último guardado, perderemos todas las operaciones, porque nos recuperaremos del último punto de control que fue, por ejemplo, hace dos horas.

Tampoco es posible guardar cada segundo, porque volcar constantemente 20 GB en disco no es una buena idea.

Para esto se ideó y realizó el concepto de write-ahead log. Con su ayuda, se crea una entrada en un pequeño archivo de write-ahead log para cada cambio en los datos.

Cada entrada hasta el punto de control se guarda en ellos. Para estos archivos, establecemos un tamaño, por ejemplo, 64 MB. Cuando se llena, la entrada comienza a ir al segundo archivo. Y después de reiniciar, Tarantool se restaura desde el último punto de control y luego aplica todas las transacciones más recientes hasta el momento de la detención.

En Tarantool se puede combinar una base de datos ultrarrápida y una aplicación para trabajar con ella. Así de simple es hacerlo.

Para llevar a cabo tal registro, es necesario especificar una opción en la configuración de box.cfg (en el archivo example.lua):

wal_mode = “write”;

Uso de los datos

Con lo que hemos escrito ahora, puedes utilizar Tarantool para almacenar datos, y funcionará muy rápido como base de datos. Y ahora la guinda del pastel: qué se puede hacer con todo esto.

Escribimos una aplicación

Por ejemplo, vamos a escribir una aplicación para Tarantool

Mira la aplicación bajo el 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; -- una hora
    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 = 'secreto' })
    box.schema.user.grant('example', 'read,write,execute', 'space', 'example')

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

-- para la primera ejecución crea un espacio y configura los permisos
box.once('replica', bootstrap)

-- habilitando acceso a la consola
console = require('console')
console.listen('127.0.0.1:3302')

-- configuración 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",
                              "Conteo de Tokens 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()

Declaramos una tabla en lua que define los caracteres. Esta tabla es necesaria para generar una cadena aleatoria.

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

Después de esto, declaramos la función – randomString y pasamos como argumento el valor de la longitud.

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

Luego, conectamos el enrutador http y el servidor http a nuestro servidor Tarantool, junto con el JSON que entregaremos al cliente.

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

Después de esto, iniciamos el servidor http en el puerto 8080 en todas las interfaces, que registrará todas las solicitudes y errores.

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

A continuación, declaramos una ruta, de modo que si llega una solicitud con el método GET al puerto 8080 /count, llamamos a una función de una sola línea. Esta devuelve un estado: 200, 404, 403 o cualquier otro que indiquemos.

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

En el cuerpo, devolvemos json.encode, en el que indicamos el count y getcount, que se llama y muestra la cantidad de registros en nuestra base.

El segundo método

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)

Donde en la línea router:route({method = ‘GET’, path = ‘\/token’}, function() llamamos a una función y generamos un token.

Cadena local token = randomString(32) – es una cadena aleatoria de 32 caracteres.
En la línea local last = box.space.example:len() sacamos el último elemento.
Y en la línea box.space.example:insert{ last + 1, token } escribimos en nuestra base de datos, es decir, simplemente incrementamos el ID en 1. Esto se puede hacer, por cierto, no solo de esta manera torpe. En Tarantool hay secuencias para eso.

Escribimos allí el token.

Así, hemos escrito una aplicación en un solo archivo. En él se puede acceder inmediatamente a los datos, y el módulo box hará todo el trabajo pesado por usted.

Escucha http y trabaja con los datos, todo se encuentra en una única instancia: tanto la aplicación como los datos. Por lo tanto, todo sucede bastante rápido.

Para iniciar, instalamos el módulo http:

Cómo hacemos esto, véalo bajo el spoiler.

root@test2:/# tarantoolctl rocks install http
Instalando http://rocks.tarantool.org/http-scm-1.src.rock
Dependencias faltantes para http scm-1:
   checks >= 3.0.1 (no instalado)

http scm-1 depende de checks >= 3.0.1 (no instalado)
Instalando http://rocks.tarantool.org/checks-3.0.1-1.rockspec

Clonando en 'checks'...
remote: Enumerando objetos: 28, listo.
remote: Contando objetos: 100% (28/28), listo.
remote: Comprimiendo objetos: 100% (19/19), listo.
remote: Total 28 (delta 1), reutilizado 16 (delta 1), pack-reused 0
Recibiendo objetos: 100% (28/28), 12.69 KiB | 12.69 MiB/s, listo.
Resolviendo deltas: 100% (1/1), listo.
Nota: verificando '580388773ef11085015b5a06fe52d61acf16b201'.

Estás en estado 'HEAD separado'. Puedes mirar alrededor, hacer cambios experimentales
y confirmarlos, y puedes descartar cualquier commit que hagas en este
estado sin afectar a ninguna rama realizando otro checkout.

Si deseas crear una nueva rama para retener los commits que creas, puedes
hacerlo (ahora o más tarde) utilizando -b con el comando checkout nuevamente. Ejemplo:

  git checkout -b 

No hay un manifiesto existente. Intentando reconstruir...
checks 3.0.1-1 ahora está instalado en /.rocks (licencia: BSD)

-- La identificación del compilador C es GNU 7.5.0
-- Comprobando si el compilador C funciona: /usr/bin/cc
-- Comprobando si el compilador C funciona: /usr/bin/cc -- funciona
-- Detectando información de ABI del compilador C
-- Detectando información de ABI del compilador C - listo
-- Detectando características de compilación C
-- Detectando características de compilación C - listo
-- Encontrado TARANTOOL: /usr/include (versión encontrada "2.4.2-80-g18f2bc82d")
-- La carpeta LUADIR de Tarantool es /.rocks/share/tarantool/rocks/http/scm-1/lua
-- La carpeta LIBDIR de Tarantool es /.rocks/share/tarantool/rocks/http/scm-1/lib
-- Configuración completada
-- Generación completada
Advertencia de CMake:
  Variables especificadas manualmente no utilizadas por el proyecto:

    version


-- Los archivos de construcción se han escrito en: /tmp/luarocks_http-scm-1-V4P9SM/http/build.luarocks
Escaneando dependencias del objetivo httpd
[ 50%] Construyendo objeto C http/CMakeFiles/httpd.dir/lib.c.o
En el archivo incluido desde /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:32:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c: En la función 'tpl_term':
/usr/include/tarantool/lauxlib.h:144:15: advertencia: esta sentencia puede caer [-Wimplicit-fallthrough=]
    (*(B)->p++ = (char)(c)))
    ~~~~~~~~~~~^~~~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:62:7: nota: en expansión de la macro 'luaL_addchar'
       luaL_addchar(b, '\');
       ^~~~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:63:6: nota: aquí
      por defecto:
      ^~~~~~~
En el archivo incluido desde /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:39:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h: En la función 'tpe_parse':
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h:147:9: advertencia: esta sentencia puede caer [-Wimplicit-fallthrough=]
    type = TPE_TEXT;
    ~~~~~^~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h:149:3: nota: aquí
   caso TPE_LINECODE:
   ^~~~
En el archivo incluido desde /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:40:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h: En la función 'httpfast_parse':
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:372:22: advertencia: esta sentencia puede caer [-Wimplicit-fallthrough=]
                 code = 0;
                 ~~~~~^~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:374:13: nota: aquí
             caso estado:
             ^~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:393:23: advertencia: esta sentencia puede caer [-Wimplicit-fallthrough=]
                 state = message;
                 ~~~~~~^~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:395:13: nota: aquí
             caso mensaje:
             ^~~~
[100%] Enlazando la biblioteca compartida C lib.so
[100%] Construido el objetivo httpd
[100%] Construido el objetivo httpd
Instalando el proyecto...
-- Configuración de instalación: "Debug"
-- Instalando: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/VERSION.lua
-- Instalando: /.rocks/share/tarantool/rocks/http/scm-1/lib/http/lib.so
-- Instalando: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/server/init.lua
-- Instalando: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/server/tsgi_adapter.lua
-- Instalando: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/nginx_server/init.lua
-- Instalando: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/init.lua
-- Instalando: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/fs.lua
-- Instalando: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/matching.lua
-- Instalando: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/middleware.lua
-- Instalando: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/request.lua
-- Instalando: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/response.lua
-- Instalando: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/tsgi.lua
-- Instalando: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/utils.lua
-- Instalando: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/mime_types.lua
-- Instalando: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/codes.lua
http scm-1 ahora está instalado en /.rocks (licencia: BSD)

root@test2:/#

También necesitamos prometheus para iniciar:

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

Clonando en 'prometheus'...
remoto: Enumerando objetos: 19, hecho.
remoto: Contando objetos: 100% (19/19), hecho.
remoto: Comprimiendo objetos: 100% (19/19), hecho.
remoto: Total 19 (delta 2), reutilizados 5 (delta 0), empaquetados reutilizados 0
Recibiendo objetos: 100% (19/19), 10.73 KiB | 10.73 MiB/s, hecho.
Resolviendo deltas: 100% (2/2), hecho.
prometheus scm-1 está ahora instalado en ~/.rocks (licencia: BSD)

root@test2:~#

Iniciamos y podemos acceder a los módulos

root@test2:~# curl -D - -s http://127.0.0.1:8080/token
HTTP/1.1 200 OK
Content-length: 44
Servidor: Tarantool http (tarantool v2.4.2-80-g18f2bc82d)
Conexión: keep-alive

{"token":"e2tPq9l5Z3QZrewRf6uuoJUl3lJgSLOI"}

root@test2:~# curl -D - -s http://127.0.0.1:8080/token
HTTP/1.1 200 OK
Content-length: 44
Servidor: Tarantool http (tarantool v2.4.2-80-g18f2bc82d)
Conexión: keep-alive

{"token":"fR5aCA84gj9eZI3gJcV0LEDl9XZAG2Iu"}

root@test2:~# curl -D - -s http://127.0.0.1:8080/count
HTTP/1.1 200 OK
Content-length: 11
Servidor: Tarantool http (tarantool v2.4.2-80-g18f2bc82d)
Conexión: keep-alive

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

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

Probando la velocidad

Hagamos una prueba de rendimiento con 50,000 solicitudes. Habrá 500 solicitudes concurrentes.

root@test2:~# ab -c 500 -n 50000 http://127.0.0.1:8080/token
Esta es ApacheBench, Versión 2.3 
Derechos de autor 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licenciado a The Apache Software Foundation, http://www.apache.org/

Evaluando 127.0.0.1 (se paciente)
Completadas 5000 solicitudes
Completadas 10000 solicitudes
Completadas 15000 solicitudes
Completadas 20000 solicitudes
Completadas 25000 solicitudes
Completadas 30000 solicitudes
Completadas 35000 solicitudes
Completadas 40000 solicitudes
Completadas 45000 solicitudes
Completadas 50000 solicitudes
Terminadas 50000 solicitudes


Software del Servidor:        Tarantool
Nombre del Servidor:        127.0.0.1
Puerto del Servidor:            8080

Ruta del Documento:          /token
Longitud del Documento:        44 bytes

Nivel de Concurrencia:      500
Tiempo tomado para pruebas:   14.578 segundos
Solicitudes completadas:      50000
Solicitudes fallidas:        0
Total transferido:      7950000 bytes
HTML transferido:       2200000 bytes
Solicitudes por segundo:    3429.87 [# /sec] (promedio)
Tiempo por solicitud:       145.778 [ms] (promedio)
Tiempo por solicitud:       0.292 [ms] (promedio, en todas las solicitudes concurrentes)
Tasa de transferencia:          532.57 [Kbytes /sec] recibidos

Tiempos de Conexión (ms)
              min  medio[+/-sd] mediana   max
Conectar:        0   10 103.2      0    3048
Procesamiento:    12   69 685.1     15   13538
Esperando:       12   69 685.1     15   13538
Total:         12   78 768.2     15   14573

Porcentaje de las solicitudes atendidas dentro de un cierto tiempo (ms)
  50%     15
  66%     15
  75%     16
  80%     16
  90%     16
  95%     16
  98%     21
  99%     42
  100%  14573 (solicitud más larga)
root@test2:~#

Los tokens se emiten. Y estamos registrando constantemente datos. El 99% de las solicitudes se procesaron en 42 milisegundos. Por lo tanto, tenemos alrededor de 3500 solicitudes por segundo en una máquina pequeña, donde hay 2 núcleos y 4 gigabytes de memoria.

También puedes seleccionar algún token de 50000 y ver su valor.

No solo se puede usar http, se pueden ejecutar funciones en segundo plano que procesan tus datos. Además, hay varios triggers. Por ejemplo, puedes llamar a funciones en actualizaciones, verificar algo - reparar conflictos.

Se pueden escribir aplicaciones y scripts directamente en el propio servidor de la base de datos, sin ninguna limitación, conectando cualquier módulo y realizando cualquier lógica.

El servidor de aplicaciones puede comunicarse con servidores externos, recoger datos y almacenarlos en su base de datos. Otros aplicativos utilizarán los datos de esta base.

Esto lo hará el propio Tarantool, y no será necesario escribir una aplicación por separado.

En conclusión

Esta es solo la primera parte de un gran trabajo. La segunda parte se publicará muy pronto en el blog de Mail.ru Group, y nos aseguraremos de agregar un enlace a este material.

Si te interesa asistir a eventos donde creamos estas cosas en línea y hacer preguntas en tiempo real, conéctate a el canal DevOps by REBRAIN.

Si necesitas migrar a la nube o tienes preguntas sobre tu infraestructura, no dudes en dejar tu solicitud.

P.S. Tenemos 2 auditorías gratuitas al mes, tal vez tu proyecto sea uno de ellos.

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster