No Tarantool, você pode combinar um banco de dados super rápido e um aplicativo para trabalhar com eles. Veja como é fácil fazer

Cinco anos atrás, tentei trabalhar com Tarantool, mas não funcionou para mim. Mas recentemente fiz um webinar onde falei sobre o Hadoop, sobre como o MapReduce funciona. Lá me fizeram a pergunta - “Por que não usar o Tarantool para esta tarefa?”.

Por curiosidade, resolvi voltar a ele, testar a versão mais recente - e desta vez gostei muito do projeto. Agora vou mostrar como escrever um aplicativo simples no Tarantool, carregá-lo e verificar o desempenho, e você verá como tudo é fácil e legal.

No Tarantool, você pode combinar um banco de dados super rápido e um aplicativo para trabalhar com eles. Veja como é fácil fazer

O que é Tarantool

O Tarantool se posiciona como um banco de dados ultrarrápido. Você pode colocar todos os dados que quiser lá. Além disso, replique-os, fragmente - ou seja, divida uma grande quantidade de dados em vários servidores e combine os resultados deles - crie links mestre-mestre tolerantes a falhas.

Em segundo lugar, é um servidor de aplicativos. Você pode escrever seus aplicativos nele, trabalhar com dados, por exemplo, excluir entradas antigas em segundo plano de acordo com certas regras. Você pode escrever um servidor Http diretamente no Tarantula que funcionará com dados: forneça seu número, escreva novos dados lá e reduza tudo a um mestre.

Li um artigo sobre como os caras fizeram uma fila de mensagens de 300 linhas, que só rasga e se debate - eles têm um desempenho mínimo de 20 mensagens por segundo. Aqui você pode realmente virar e escrever um aplicativo muito grande, e estes não serão armazenados, como no PostgreS.

Aproximadamente tal servidor, apenas simples, tentarei descrever neste artigo.

Instalação

Para o teste, iniciei três máquinas virtuais padrão - um disco rígido de 20 gigabytes, Ubuntu 18.04. 2 CPUs virtuais e 4 gigabytes de memória.

Instalamos o Tarantool - executamos um script bash ou adicionamos um repositório e fazemos o apt get install Tarantool. Link para o script - (curl -L https://tarantool.io/installer.sh | VER=2.4 sudo -E bash). Temos comandos como:

taranolctl é o comando principal para gerenciar instâncias do Tarantula.
/etc/tarantool - aqui está toda a configuração.
var/log/tarantool - aqui estão os registros.
var/lib/tarantool - aqui estão os dados e, em seguida, eles são divididos em instâncias.

Existem pastas disponíveis e habilitadas para instâncias - contém o que será iniciado - o arquivo de configuração da instância com o código lua, que descreve em quais portas ele escuta, qual memória está disponível para ele, configurações do mecanismo Vinyl, código que funciona na inicialização servidores, sharding, filas, exclusão de dados obsoletos e assim por diante.

As instâncias funcionam como no PostgreS. Por exemplo, você deseja executar várias cópias de um banco de dados que trava em diferentes portas. Acontece que várias instâncias de banco de dados são iniciadas em um servidor, que ficam em portas diferentes. Eles podem ter configurações completamente diferentes - uma instância implementa uma lógica, a segunda - outra.

Gerenciamento de Instância

Temos o comando tarantoolctl que nos permite gerenciar instâncias do Tarantula. Por exemplo, tarantoolctl check example verificará o arquivo de configuração e informará que o arquivo está ok se não houver erros de sintaxe.

Você pode ver o status da instância - exemplo de status tarantoolctl. Da mesma forma, você pode iniciar, parar e reiniciar.

Depois que uma instância está em execução, há duas maneiras de se conectar a ela.

1. Console administrativo

Por padrão, o Tarantool abre um soquete e envia um texto ASCII simples para controlar o Tarantula. A conexão com o console sempre ocorre sob o usuário admin, não há autenticação, portanto você não precisa tirar a porta do console para controlar o Tarantula fora.

Para se conectar dessa maneira, você precisa digitar Tarantoolctl enter nome da instância. O comando iniciará o console e se conectará como usuário administrador. Nunca exponha a porta do console para fora - é melhor deixá-la como um soquete da unidade. Então, apenas aqueles que têm acesso de gravação ao soquete poderão se conectar ao Tarantula.

Este método é necessário para coisas administrativas. Para trabalhar com dados, use o segundo método - o protocolo binário.

2. Usando um protocolo binário para conectar a uma porta específica

Há uma diretiva de escuta na configuração, que abre a porta para comunicações externas. Esta porta é usada com protocolo binário e a autenticação é habilitada lá.

Para esta conexão, tarantoolctl conectar ao número da porta é usado. Com ele, você pode se conectar a servidores remotos, usar autenticação e conceder vários direitos de acesso.

Módulo de Registro de Dados e Caixa

Como o Tarantool é um banco de dados e um servidor de aplicativos, ele possui vários módulos. Estamos interessados ​​​​no módulo de caixa - ele implementa o trabalho com dados. Quando você escreve algo em uma caixa, o Tarantool grava os dados no disco, armazena-os na memória ou faz outra coisa com eles.

Registro

Por exemplo, entramos no módulo box e chamamos a função box.once. Isso forçará o Tarantool a executar nosso código quando o servidor for inicializado. Criamos um espaço onde os nossos dados serão armazenados.

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

Depois disso, criamos um índice primário - primário - pelo qual podemos pesquisar dados. Por padrão, se nenhum parâmetro for especificado, o primeiro campo em cada entrada para o índice primário será usado.

Em seguida, fazemos uma concessão ao usuário convidado, sob a qual nos conectamos por meio de um protocolo binário. Permitimos a leitura, escrita e execução em toda a instância.

Comparado aos bancos de dados convencionais, tudo é bastante simples aqui. Temos espaço - uma área na qual nossos dados são simplesmente armazenados. Cada entrada é chamada de tupla. Ele é empacotado em um MessagePack. Este é um formato muito legal - é binário e ocupa menos espaço - 18 bytes contra 27.

No Tarantool, você pode combinar um banco de dados super rápido e um aplicativo para trabalhar com eles. Veja como é fácil fazer

É bastante conveniente trabalhar com ele. Quase todas as linhas, todas as entradas de dados podem ter colunas completamente diferentes.

Podemos visualizar todos os espaços usando o comando Box.space. Para selecionar uma instância específica, escrevemos o exemplo box.space e obtemos informações completas sobre ele.

Existem dois tipos de motores embutidos no Tarantool: Memória e Vinil. A memória armazena todos os dados na memória. Portanto, tudo funciona de forma simples e rápida. Os dados são despejados no disco e também há um mecanismo de log de gravação antecipada, para que não percamos nada se o servidor travar.

O vinil armazena dados no disco de uma forma mais familiar - ou seja, você pode armazenar mais dados do que temos memória e o Tarantula os lerá do disco.

Agora vamos usar a Memória.

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:

Um índice primário deve ser criado para qualquer espaço, porque nada funcionará sem ele. Como em qualquer banco de dados, criamos o primeiro campo - o ID do registro.

Peças:

É aqui que especificamos em que consiste nosso índice. Consiste em uma parte - o primeiro campo que usaremos, digite unsigned - um inteiro positivo. Tanto quanto me lembro da documentação, o número máximo que pode ser é 18 quintilhões. Muito incrível.

Podemos então inserir dados usando o 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>

O primeiro campo é usado como chave primária, portanto deve ser único. Não estamos limitados pelo número de colunas, então podemos inserir quantos dados quisermos lá. Eles são especificados no formato MessagePack, que descrevi acima.

saída de dados

Então podemos exibir os dados com o comando select.

Box.example.select com a tecla {1} exibirá a entrada desejada. Se omitirmos a chave, veremos todos os registros que temos. Eles são todos diferentes no número de colunas, mas aqui, em princípio, não há conceito de colunas - existem números de campo.

Pode haver absolutamente tantos dados quanto você quiser. E, por exemplo, precisamos procurá-los no segundo campo. Para fazer isso, criamos um novo índice secundário.


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

Usamos o comando Create_index.
Nós o chamamos de Secundário.

Depois disso, você precisa especificar os parâmetros. O tipo de índice é TREE. Pode não ser exclusivo, então inserimos Unique = false.

Em seguida, indicamos em quais partes nosso índice consiste. Field é o número do campo ao qual vinculamos o índice e especifica o tipo de string. E assim foi criado.

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>

Agora é assim que podemos chamá-lo:

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

Preservação

Se reiniciarmos a instância e tentarmos chamar os dados novamente, veremos que eles não estão lá - tudo está vazio. Isso acontece porque o Tarantool faz checkpoints e salva os dados no disco, mas se pararmos de trabalhar antes do próximo salvamento, perderemos todas as operações - pois nos recuperaremos do último checkpoint, que foi, por exemplo, duas horas atrás.

Salvar cada segundo também não funcionará - porque despejar constantemente 20 GB no disco é uma ideia mais ou menos.

Para isso, o conceito de log write-ahead foi inventado e implementado. Com sua ajuda, para cada alteração nos dados, um registro é criado em um pequeno arquivo de log write-ahead.

Cada entrada até o ponto de verificação é armazenada neles. Para esses arquivos, definimos o tamanho - por exemplo, 64 mb. Quando enche, a gravação começa a ir para o segundo arquivo. E após a reinicialização, o Tarantool se recupera do último ponto de verificação e rola todas as transações posteriores até parar.

No Tarantool, você pode combinar um banco de dados super rápido e um aplicativo para trabalhar com eles. Veja como é fácil fazer

Para realizar tal gravação, você precisa especificar uma opção nas configurações box.cfg (no arquivo example.lua):

wal_mode = “write”;

uso de dados

Com o que escrevemos agora, você pode usar o Tarantula para armazenar dados e funcionará muito rápido como um banco de dados. E agora a cereja do bolo - o que você pode fazer com tudo isso.

Escrevendo um aplicativo

Por exemplo, vamos escrever tal aplicativo para a Tarântula

Veja o aplicativo abaixo do 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 alguma tabela em lua que define símbolos. Esta tabela é necessária para gerar uma string aleatória.

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

Depois disso, declaramos uma função - randomString e fornecemos o valor do comprimento entre colchetes.

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

Em seguida, conectamos o roteador http e o servidor http ao nosso servidor Tarantula, JSON, que daremos ao cliente.

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

Depois disso, começamos na porta 8080 em todas as interfaces do servidor http, que registrará todas as solicitações e erros.

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

Em seguida, declaramos uma rota que, se uma solicitação com o método GET chegar à porta 8080 /count, chamaremos a função de uma linha. Ele retorna um status - 200, 404, 403 ou o que especificarmos.

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

No corpo, retornamos json.encode, especificamos count e getcount nele, que é chamado e mostra o número de registros em nosso banco de dados.

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

Onde na linha router:route({method = 'GET', path = '/token'}, function() chamamos a função e geramos um token.

Linha token local = randomString(32) é uma string aleatória de 32 caracteres.
Em linha local último = box.space.example:len() retiramos o último elemento.
E na fila box.space.example:insert{ último + 1, token } gravamos os dados em nosso banco de dados, ou seja, simplesmente aumentamos o ID em 1. Isso pode ser feito, aliás, não apenas de forma tão desajeitada. Tarantula tem sequências para este caso.

Nós escrevemos o token lá.

Assim, escrevemos um aplicativo em um arquivo. Você pode acessar os dados imediatamente e o módulo de caixa fará todo o trabalho sujo para você.

Ele escuta http e trabalha com dados, tudo em uma única instância - tanto o aplicativo quanto os dados. Portanto, tudo acontece muito rapidamente.

Para executar, instalamos o módulo http:

Como fazemos, veja abaixo do 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:/#

Também precisamos do prometheus para executar:

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

Iniciamos e podemos acessar os 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 dá o status 200.
/token emite um token e grava esse token no banco de dados.

velocidade de teste

Vamos executar um benchmark para 50 solicitações. Os pedidos competitivos serão 000.

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

Os tokens são emitidos. E estamos constantemente registrando dados. 99% das solicitações foram concluídas em 42 milissegundos. Assim, temos cerca de 3500 solicitações por segundo em uma máquina pequena, onde existem 2 núcleos e 4 gigabytes de memória.

Você também pode selecionar algum token de 50000 e ver seu valor.

Você pode usar não apenas http, executar funções em segundo plano que processam seus dados. Além disso, existem vários gatilhos. Por exemplo, você pode chamar funções em atualizações, verificar algo - corrigir conflitos.

Você pode escrever aplicativos de script diretamente no próprio servidor de banco de dados e não ser limitado por nada, conectar quaisquer módulos e implementar qualquer lógica.

O servidor de aplicativos pode acessar servidores externos, coletar dados e adicioná-los ao seu banco de dados. Os dados deste banco de dados serão usados ​​por outros aplicativos.

Isso será feito pela própria Tarântula e não há necessidade de escrever um aplicativo separado.

Em conclusão

Esta é apenas a primeira parte de um grande trabalho. O segundo será publicado muito em breve no blog do Mail.ru Group, e com certeza adicionaremos um link para ele neste material.

Se você estiver interessado em participar de eventos em que criamos essas coisas online e fazendo perguntas em tempo real, conecte-se a DevOps pelo canal REBRAIN.

Se você precisa migrar para a nuvem ou tem dúvidas sobre sua infraestrutura, Sinta-se à vontade para enviar uma solicitação.

PS Temos 2 auditorias gratuitas por mês, talvez o seu projeto seja uma delas.

Fonte: habr.com

Adicionar um comentário