En Tarantool, puede combinar una base de datos súper rápida y una aplicación para trabajar con ellos. Esto es lo fácil que es hacerlo

Hace cinco años intenté trabajar con Tarantool, pero luego no funcionó. Pero recientemente realicé un seminario web en el que hablé sobre Hadoop y cómo funciona MapReduce. Allí me hicieron una pregunta: “¿Por qué no utilizar 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 sencilla en Tarantool, cargarla y comprobar su rendimiento, y verás lo fácil y genial que es todo.

En Tarantool, puede combinar una base de datos súper rápida y una aplicación para trabajar con ellos. Esto es lo fácil que es hacerlo

¿Qué es Tarantool?

Tarantool se posiciona como una base de datos ultrarrápida. Puedes poner allí los datos que quieras. Además, replíquelos, fragmente, es decir, divida una gran cantidad de datos en varios servidores y combine los resultados de ellos, para crear conexiones maestro-maestro tolerantes a fallas.

En segundo lugar, este 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 funcione con datos: proporcione su cantidad, escriba nuevos datos allí y redúzcalos todos al maestro.

Leí un artículo sobre cómo los chicos crearon una cola de mensajes de 300 líneas, que simplemente está abarrotada y apresurada: tienen un rendimiento mínimo de 20 mensajes por segundo. Aquí realmente puedes darte la vuelta y escribir una aplicación muy grande, y no habrá almacenamiento, como en PostgreS.

Intentaré describir algo como este servidor, sólo que simple, en este artículo.

Instalación

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

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

tarantoolctl — el comando principal para gestionar instancias de Tarantula.
/etc/tarantool - aquí está la configuración completa.
var/log/tarantool - Aquí están los registros.
var/lib/tarantool — los datos se encuentran aquí y luego se dividen en instancias.

Hay carpetas instancia-disponible e instancia-enable - contiene lo que se ejecutará - 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 Vinyl, código que se ejecuta 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 en un servidor se inician varias instancias de bases de datos que cuelgan en 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 permite gestionar 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 allí.

Puede ver el estado de la instancia: ejemplo de estado de tarantoolctl. De la misma manera puedes hacer iniciar, detener, reiniciar.

Una vez que la instancia se está ejecutando, puede conectarse a ella de dos maneras.

1. Consola administrativa

De forma predeterminada, Tarantool abre un socket, allí se envía texto ASCII normal para controlar Tarantool. La conexión a la consola siempre ocurre bajo el usuario administrador, no hay autenticación, por lo que no es necesario externalizar el puerto de la consola para administrar Tarantula.

Para conectarse usando este método, debe ingresar Tarantoolctl e ingresar el nombre de la instancia. El comando iniciará la consola y se conectará como usuario administrador. Nunca expongas el puerto de la consola al exterior; es mejor dejarlo como enchufe de la unidad. Entonces sólo aquellos que tengan acceso para escribir en el socket podrán conectarse a Tarantula.

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

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

La configuración contiene una directiva de escucha, que abre un puerto para comunicaciones externas. Este puerto se utiliza con el protocolo binario y allí se habilita la autenticación.

Para esta conexión, se utiliza tarantoolctl connect al número de puerto. Al usarlo, puede conectarse a servidores remotos, utilizar la autenticación y otorgar varios derechos de acceso.

Módulo de caja y grabación de datos

Dado que Tarantool es a la vez una base de datos y un servidor de aplicaciones, tiene varios módulos. Nos interesa el módulo box: implementa el trabajo con datos. Cuando escribes algo en el cuadro, Tarantool escribe los datos en el disco, los almacena en la memoria o hace algo más con ellos.

Registro

Por ejemplo, entramos en el módulo box y llamamos a la función box.once. Esto obligará a Tarantool a ejecutar 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 esto, creamos un índice primario, primario, mediante el cual podemos buscar datos. De forma predeterminada, si no especifica ningún parámetro, el primer campo de cada registro se utilizará para el índice principal.

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

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

En Tarantool, puede combinar una base de datos súper rápida y una aplicación para trabajar con ellos. Esto es lo fácil que es hacerlo

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

Podemos ver 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 al respecto.

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 descargan en el 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 que nos resulta más familiar, es decir, puede almacenar más datos de los que tenemos en la memoria y Tarantula los leerá del disco.

Por ahora usaremos Memoria.

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:

Se debe crear un índice primario para cualquier espacio, porque sin él nada funcionará. Como en cualquier base de datos, creamos el primer campo: ID del registro.

Partes:

Aquí indicamos en qué consiste nuestro índice. Consta de una parte: el primer campo que usaremos es de tipo sin signo, un número entero positivo. Por lo que recuerdo de la documentación, el número máximo que puede ser es 18 quintillones. Eso es mucho.

Luego 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 allí tantos datos como queramos. Se especifican en el formato MessagePack, que describí anteriormente.

Salida de datos

Luego podemos mostrar los datos usando el comando de selección.

Box.example.select con la tecla {1} mostrará la entrada deseada. Si bajamos la tecla veremos todos los registros que tenemos. Todos difieren en el número de columnas, pero aquí, en principio, no existe el concepto de columnas: hay números de campo.

Puede haber absolutamente cualquier cantidad de datos. Y por ejemplo, necesitamos 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.
Llamémoslo Secundaria.

Después de esto necesitas especificar los parámetros. El tipo de índice es ÁRBOL. Puede que no sea único, así que ingrese Único = falso.

Luego indicamos en qué partes consta nuestro índice. El 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 crea puntos de control y guarda los datos en el disco, pero si dejamos de trabajar hasta el próximo guardado, perderemos todas las operaciones, porque nos recuperaremos del último punto de control, que fue, por ejemplo, hace dos horas.

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

Para ello, se inventó e implementó el concepto de registro de escritura anticipada. Con su ayuda, por cada cambio en los datos, se crea una entrada en un pequeño archivo de registro de escritura anticipada.

Cada entrada hasta el punto de control se almacena en ellos. Para estos archivos configuramos el tamaño, por ejemplo, 64 MB. Cuando está lleno, la grabación comienza a pasar al segundo archivo. Y después del reinicio, Tarantool se restaura desde el último punto de control y luego reinvierte todas las transacciones posteriores hasta que se detiene.

En Tarantool, puede combinar una base de datos súper rápida y una aplicación para trabajar con ellos. Esto es lo fácil que es hacerlo

Para realizar dicha grabación, debe especificar la opción en la configuración de box.cfg (en el archivo ejemplo.lua):

wal_mode = “write”;

Uso de datos

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

Escribir una solicitud

Por ejemplo, escribamos la siguiente aplicación 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 tabla en lua que define los caracteres. Esta placa 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 eso, declaramos la 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 esto, 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 la ruta, de modo que si llega una solicitud con el método GET al puerto 8080 /count, llamemos a la función desde una línea. Devuelve el estado: 200, 404, 403 o cualquier otro 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 indicamos count y getcount, que se llama y muestra la cantidad de registros en nuestra base de datos.

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 fila enrutador:ruta({método = 'OBTENER', ruta = '/token'}, función() llamamos a la función y generamos un token.

Cadena token local = cadena aleatoria (32) es una cadena aleatoria de 32 caracteres.
En línea local último = box.space.ejemplo:len() sacamos el último elemento.
y en la linea box.space.example:insertar{ último + 1, token } escribimos los datos en nuestra base de datos, es decir, simplemente aumentamos el ID en 1. Por cierto, esto se puede hacer no sólo de esta forma tan torpe. Hay secuencias para esto en Tarantula.

Escribimos la ficha allí.

Por lo tanto, escribimos la aplicación en un archivo. Puede manipular directamente los datos allí y el módulo de caja hará todo el trabajo sucio por usted.

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

Para comenzar instalamos el módulo http:

Cómo hacemos esto, 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 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:/#

También necesitamos que Prometheus se ejecute:

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

Lanzamos 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 lo escribe en la base de datos.

Probando la velocidad

Ejecutemos una prueba comparativa para 50 solicitudes. Habrá 000 solicitudes en competencia.

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 fichas. Y estamos constantemente registrando datos. El 99% de las solicitudes se procesaron en 42 milisegundos. En consecuencia, tenemos alrededor de 3500 solicitudes por segundo en una máquina pequeña con 2 núcleos y 4 gigabytes de memoria.

También puedes seleccionar unos 50000 tokens y ver su valor.

Puede utilizar no sólo http, sino también ejecutar funciones en segundo plano que procesan sus datos. Además, existen varios desencadenantes. Por ejemplo, puede llamar a funciones sobre actualizaciones, verificar algo y corregir conflictos.

Puede escribir aplicaciones de script directamente en el servidor de la base de datos y no estar limitado por nada, conectar ningún módulo e implementar cualquier lógica.

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

Tarantula lo hará por sí misma y no tendrás que escribir una aplicación por separado.

en conclusión

Esta es sólo la primera parte de un gran trabajo. El segundo se publicará muy pronto en el blog del grupo Mail.ru y definitivamente agregaremos un enlace en este material.

Si está interesado en asistir a eventos en los que creamos estas cosas en línea y hacemos preguntas en tiempo real, sintonice canal DevOps por REBRAIN.

Si necesita migrar a la nube o tiene preguntas sobre su infraestructura, no dudes en dejar una solicitud.

PD: Tenemos 2 auditorías gratuitas al mes, quizás tu proyecto sea uno de ellos.

Fuente: habr.com

Añadir un comentario