En Tarantool, puede combinar una base de datos y una aplicación súper rápidas para trabajar con ellos. Así de fácil es

Hace cinco años intenté trabajar con Tarantool, pero luego no se me ocurrió. Pero recientemente organicé un seminario web en el que hablé sobre Hadoop, sobre cómo funciona MapReduce. Allí me hicieron una pregunta: "¿Por qué no usar Tarantool para esta tarea?"



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







Que es Tarantool



Tarantool se posiciona como una base de datos súper rápida. Allí puede guardar los datos que desee. Además, replicarlos, fragmentarlos, es decir, dividir una gran cantidad de datos en varios servidores y combinar los resultados de ellos, para crear paquetes "maestro-maestro" tolerantes a fallas.



En segundo lugar, es un servidor de aplicaciones. Puede escribir sus aplicaciones en él, trabajar con datos, por ejemplo, eliminar registros antiguos en segundo plano de acuerdo con ciertas reglas. Puede escribir un servidor Http directamente en Tarantula, que funcionará con datos: emitir su cantidad, escribir nuevos datos allí y reducirlo todo al maestro.



Leí un artículo sobre cómo los chicos hicieron una cola de mensajes de 300 líneas que simplemente se desgarra y vuela: tienen un rendimiento mínimo de 20.000 mensajes por segundo. Aquí realmente puede expandir y escribir una aplicación muy grande, y no se almacenará como en PostgreS.



Acerca de tal servidor, simplemente simple, intentaré describirlo en este artículo.



Instalación



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



Instalamos Tarantool: ejecutamos el script bash o agregamos un repositorio y hacemos para instalar Tarantool. El enlace al script es (curl -L https://tarantool.io/installer.sh | VER = 2.4 sudo -E bash). Tenemos comandos como:



tarantoolctl : el comando principal para administrar instancias de Tarantula.

/ etc / tarantool : toda la configuración se encuentra aquí.

var / log / tarantool : aquí es donde se encuentran los registros.

var / lib / tarantool : aquí es donde se almacenan los datos y luego se dividen en instancias.



Hay carpetas disponibles para instancias y habilitadas para instancias: contiene lo que se lanzará: un archivo de configuración de instancia con código lua, que describe en qué puertos escucha, qué memoria está disponible, configuración del motor de vinilo, código que se activa al inicio servidores, fragmentación, colas, eliminación de datos obsoletos, etc.



Las instancias funcionan como en PostgreS. Por ejemplo, desea ejecutar varias copias de una base de datos que se cuelga en diferentes puertos. Resulta que varias instancias de base de datos se lanzan en el mismo servidor, que cuelgan de diferentes puertos. Pueden tener configuraciones completamente diferentes: una instancia implementa una lógica, la segunda, otra.



Gestión de instancias



Tenemos el comando tarantoolctl que le permite administrar sus instancias de Tarantula. Por ejemplo, tarantoolctl check example comprobará el archivo de configuración y dirá: el archivo está bien si no hay errores de sintaxis.



Puede ver el estado de la instancia - ejemplo de estado de tarantoolctl. De la misma manera puede iniciar, detener, reiniciar.



Cuando la instancia se está ejecutando, hay dos formas de conectarse a ella.



1. Consola administrativa



De forma predeterminada, Tarantool abre un socket, donde transmite texto ASCII sin formato para controlar Tarantula. La conexión a la consola siempre se realiza bajo el usuario administrador, no hay autenticación, por lo que no es necesario mover el puerto de la consola para administrar el Tarantula.



Para conectarse de esta manera, ingrese Tarantoolctl ingrese el nombre de la instancia. El comando iniciará la consola y se conectará como usuario administrador. Nunca exponga el puerto de la consola al exterior; es mejor dejarlo como un enchufe de unidad. Entonces solo aquellos que tengan acceso de escritura al enchufe podrán conectarse a la Tarántula.



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



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



Hay una directiva de escucha en la configuración, que abre el puerto para comunicaciones externas. Este puerto se usa con un protocolo binario y la autenticación está habilitada allí.



Para esta conexión, se utiliza tarantoolctl connect to port number. Al usarlo, puede conectarse a servidores remotos, usar la autenticación y otorgar varios derechos de acceso.



Registrador de datos y módulo Box



Dado que Tarantool es tanto una base de datos como un servidor de aplicaciones, tiene varios módulos. Estamos interesados ​​en el módulo de caja: implementa el trabajo con datos. Cuando escribe algo en la caja, Tarantool escribe los datos en el disco, los almacena en la memoria o hace algo más con ellos.



Grabación



Por ejemplo, vamos al módulo box y llamamos a la función box.once. Hará que Tarantool ejecute nuestro código cuando se inicialice el servidor. Creamos un espacio en el que 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')

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


Después de eso, creamos un índice primario, primario, mediante el cual podemos buscar datos. De forma predeterminada, si no especifica ningún parámetro, se utilizará el primer campo de cada entrada para el índice del cebador.



Luego hacemos una concesión al usuario invitado, bajo la cual nos conectamos a través de un protocolo binario. Permitiendo leer, escribir y ejecutar en toda la instancia.



En comparación con las bases de datos convencionales, aquí todo es bastante simple. Tenemos un espacio, un área que simplemente almacena nuestros datos. Cada entrada se llama tupla. Está empaquetado en un MessagePack. Este es un formato muy bueno, es binario y ocupa menos espacio, 18 bytes frente a 27.







Es bastante conveniente trabajar con él. Casi todas las líneas, cada registro de datos pueden tener columnas completamente diferentes.



Podemos mirar todos los espacios usando el comando Box.space. Para seleccionar una instancia específica, escriba el ejemplo de box.space y obtenga información completa sobre él.



Tarantool tiene dos motores integrados: Memory y Vinyl. La memoria almacena todos los datos en la memoria. Por tanto, todo funciona de forma sencilla y rápida. Los datos se vuelcan al disco, y también hay un mecanismo de registro de escritura anticipada, por lo que no perderemos nada si el servidor falla.



Vinyl almacena datos en el disco de una forma más familiar, es decir, puede almacenar más datos de los que tenemos en memoria, y Tarantula 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:



el índice principal debe crearse para cualquier espacio, porque sin él nada funcionará. Como con cualquier base de datos, creamos el primer campo: el ID de registro.



Partes:



Aquí te indicamos en qué consiste nuestro índice. Consiste en una parte: el primer campo que usaremos es unsigned, un entero positivo. Como recuerdo de la documentación, el número máximo que puede ser es de 18 quintillones. Lote impresionante.



Entonces podemos insertar datos usando el comando insertar.



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 principal, por lo que debe ser único. No estamos limitados por el número de columnas, por lo que podemos insertar tantos datos como queramos. Se especifican en el formato MessagePack que describí anteriormente.



Salida de datos



Entonces podemos mostrar datos con el comando de selección.



Box.example.select con la tecla {1} mostrará el registro requerido. Si omitimos la clave, veremos todos los registros que tenemos. Todos son diferentes en el número de columnas, pero en principio no existe el concepto de columnas; hay números de campo.



Puede haber absolutamente cualquier cantidad de datos. Y, por ejemplo, debemos buscarlos por el segundo campo. Para ello creamos 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, debe especificar los parámetros. El tipo de índice es ÁRBOL. Puede que no sea único, por lo que ingresamos Único = falso.



Luego indicamos en qué partes consta nuestro índice. Campo es el número del campo al que vinculamos el índice y especificamos el tipo de cadena. Y así fue creado.



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 así es como podemos llamarlo:



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


Preservación



Si reiniciamos la instancia e intentamos llamar a los datos nuevamente, veremos que no están allí, todo está vacío. Esto sucede porque Tarantool hace puntos de control y guarda los datos en el disco, pero si dejamos de trabajar antes del siguiente guardado, perderemos todas las operaciones, porque nos recuperaremos del último punto de control, que fue, por ejemplo, hace dos horas.



Ahorrar cada segundo tampoco funcionará, porque descargar constantemente 20 GB en el disco es regular.



Para ello, se inventó e implementó el concepto de registro de escritura anticipada. Crea una entrada en un pequeño archivo de registro de escritura anticipada para cada cambio en los datos.



Cada entrada antes del punto de control se guarda en ellos. Para estos archivos, establecemos el tamaño, por ejemplo, 64 MB. Cuando se llena, la grabación comienza a ir al segundo archivo. Y después de reiniciar, Tarantool se restaura desde el último punto de control y luego transfiere todas las transacciones posteriores hasta que se detiene.







Para realizar una grabación de este tipo, debe especificar la opción en la configuración de box.cfg (en el archivo example.lua):



wal_mode = “write”;


Uso de datos



Con lo que hemos escrito ahora, puede usar Tarantula para almacenar datos y funcionará muy rápidamente como una base de datos. Y ahora la guinda del pastel: qué puedes hacer con todo.



Escribir una solicitud



Por ejemplo, escribamos una aplicación de este tipo para Tarantula.



Ver la aplicación debajo del 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()




Declaramos alguna etiqueta en lua que define símbolos. Esta placa es necesaria para generar una línea 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 eso, declaramos una función - randomString y damos el valor de longitud entre paréntesis.



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 Tarantula, JSON, que enviaremos al cliente.



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


Después de eso, comenzamos en el puerto 8080 en todas las interfaces del servidor http, 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 route que si una solicitud con el método GET llega al puerto 8080 / count, entonces llamamos a la función desde una línea. Devuelve el estado: 200, 404, 403 o lo que especifiquemos.



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


En el cuerpo, devolvemos json.encode, en él especificamos count y getcount, que se llama y muestra el número de registros en nuestra base de datos.



Método dos



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 ({método = ' GET', path = '/ token'}, function () , llamamos a la función y generamos un token.



Bar local token = randomString (32) - es una cadena aleatoria de 32 caracteres.

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 aumentamos el ID en 1. Esto se puede hacer por cierto, no solo de una manera tan torpe. En Tarantula hay secuencias para este caso. Escribimos



un token allí.



Por lo tanto, escribimos una aplicación en un archivo. En él, puedes manejar los datos de inmediato, y el módulo de caja hará todo el trabajo sucio por ti. ...



Escucha http y trabaja con datos, todo está en una sola instancia, tanto la aplicación como los datos. Por lo tanto, todo sucede con la suficiente rapidez.



Para ejecutar, instalamos el módulo http:



Cómo lo hacemos, mira debajo del 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:/#




También necesitamos prometheus para ejecutar:



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:/#


Empezamos 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
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 nos da el estado 200.

/ token emite un token y escribe este token en la base de datos.



Velocidad de prueba



Ejecutemos un punto de referencia con 50.000 consultas. Habrá 500 solicitudes competitivas.



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:/#


Se emiten tokens. Y estamos constantemente registrando datos. El 99% de las solicitudes se completaron en 42 milisegundos. En consecuencia, 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 puede seleccionar unas 50.000 fichas y ver su valor.



No solo puede usar http, puede ejecutar funciones en segundo plano que procesan sus datos. Además, existen varios factores desencadenantes. Por ejemplo, puede llamar a funciones en actualizaciones, verificar algo, solucionar conflictos.



Puede escribir scripts de aplicación directamente en el servidor de la base de datos y ser ilimitado, conectar cualquier módulo e implementar cualquier lógica.



El servidor de aplicaciones puede acceder a servidores externos, recopilar datos y almacenarlos en su base de datos. Los datos de esta base de datos serán utilizados por otras aplicaciones.



Esto lo hará la propia Tarantula y no es necesario que escriba una solicitud por separado.



Finalmente



Esta es solo la primera parte de mucho trabajo. El segundo se publicará muy pronto en el blog del grupo Mail.ru, y definitivamente agregaremos un enlace en este artículo.



Si está interesado en asistir a eventos en los que creamos este tipo de cosas en línea y hacer preguntas en tiempo real, únase al canal DevOps by REBRAIN .



Si necesita un cambio a la nube o tiene preguntas sobre su infraestructura, no dude en dejar una solicitud .



PD: Tenemos 2 auditorías gratuitas al mes, quizás su proyecto esté entre ellas.



All Articles