Por curiosidade, resolvi voltar a 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 testar o desempenho, e você verá como tudo é fácil e legal.
O que é Tarantool
Tarantool se posiciona como um banco de dados super rápido. Lá você pode enfiar quaisquer dados que desejar. Além disso, replique-os, shard - ou seja, divida uma grande quantidade de dados em vários servidores e combine os resultados deles - para criar pacotes "mestre-mestre" tolerantes a falhas.
Em segundo lugar, é um servidor de aplicativos. Você pode escrever seus aplicativos nele, trabalhar com dados, por exemplo, deletar registros antigos em segundo plano de acordo com certas regras. Você pode escrever um servidor Http diretamente no Tarantula, que irá trabalhar com os dados: emita sua quantidade, escreva novos dados lá e reduza tudo para o mestre.
Eu li um artigo sobre como os caras criaram uma fila de mensagens de 300 linhas que apenas rasga e voa - eles têm um desempenho mínimo de 20.000 mensagens por segundo. Aqui você pode realmente expandir e escrever um aplicativo muito grande, e ele não será armazenado como no PostgreS.
Sobre tal servidor, simplesmente simples, tentarei descrever neste artigo.
Instalação
Para o teste, comecei 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.
Nós instalamos o Tarantool - execute o script bash ou adicione um repositório e instale o Tarantool. O link para o script é (curl -L https://tarantool.io/installer.sh | VER = 2.4 sudo -E bash). Temos comandos como:
tarantoolctl - o principal comando para gerenciar instâncias de Tarantula.
/ etc / tarantool - todas as configurações estão aqui.
var / log / tarantool - aqui é onde os logs estão localizados.
var / lib / tarantool - é onde os dados são armazenados e, em seguida, são divididos em instâncias.
Existem pastas instance-available e instance-enable - contém o que será lançado - um arquivo de configuração de instância com código lua, que descreve em quais portas ele escuta, qual memória está disponível para ele, configurações do mecanismo de vinil, código que é acionado na inicialização servidores, fragmentação, 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 portas diferentes. Acontece que várias instâncias de banco de dados são iniciadas no mesmo servidor, que ficam suspensas 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 permite gerenciar suas instâncias do Tarantula. Por exemplo, tarantoolctl check example verificará o arquivo de configuração e dirá - 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.
Quando a instância está em execução, existem duas maneiras de se conectar a ela.
1. Console Administrativo
Por padrão, Tarantool abre um soquete, onde transmite texto ASCII simples para controlar o Tarantula. A conexão com o console é sempre feita sob o usuário administrador, não há autenticação, então você não precisa mover a porta do console para gerenciar o Tarantula.
Para conectar dessa forma, insira Tarantoolctl insira o nome da instância. O comando iniciará o console e se conectará como usuário administrador. Nunca exponha a porta do console ao exterior - é melhor deixá-la como um soquete de unidade. Então, apenas aqueles que têm acesso de escrita 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 um protocolo binário e a autenticação é ativada lá.
Para esta conexão, tarantoolctl connect to port number é usado. Usando-o, você pode se conectar a servidores remotos, usar autenticação e conceder vários direitos de acesso.
Registrador de dados e módulo de caixa
Como Tarantool é um banco de dados e um servidor de aplicativos, ele possui vários módulos. Estamos interessados no módulo box - ele implementa trabalho com dados. Quando você grava algo na caixa, o Tarantool grava os dados no disco, armazena-os na memória ou faz outra coisa com eles.
Gravação
Por exemplo, vamos para o módulo box e chamamos a função box.once. Isso fará com que o Tarantool execute nosso código quando o servidor for inicializado. Criamos um espaço no qual 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 os dados. Por padrão, se você não especificar nenhum parâmetro, o primeiro campo em cada entrada para o índice do primer será usado.
Em seguida, fazemos uma concessão ao usuário convidado, sob a qual nos conectamos por meio de um protocolo binário. Permitindo leitura, gravação e execução em toda a instância.
Em comparação com bancos de dados convencionais, tudo é bastante simples aqui. Temos um espaço - uma área que simplesmente armazena nossos dados. Cada entrada é chamada de tupla. Ele é empacotado em um MessagePack. Este é um formato muito legal - é binário e ocupa menos espaço - 18 bytes versus 27.
É bastante conveniente de trabalhar. Quase todas as linhas, todos os registros de dados podem ter colunas completamente diferentes.
Podemos ver todos os espaços usando o comando Box.space. Para selecionar uma instância específica - escreva box.space example e obtenha informações completas sobre ele.
Tarantool possui dois motores integrados: 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 registro de gravação antecipada, portanto, não perderemos nada se o servidor travar.
O Vinyl armazena dados no disco de uma forma mais familiar - ou seja, você pode armazenar mais dados do que temos na memória, e o Tarantula irá lê-los 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:
O índice primário deve ser criado para qualquer espaço, pois sem ele nada funcionará. Como acontece com qualquer banco de dados, criamos o primeiro campo - o ID do registro.
Partes:
aqui indicamos em que consiste o nosso índice. Ele consiste em uma parte - o primeiro campo que usaremos não tem sinal, um número inteiro positivo. Pelo que me lembro da documentação, o número máximo que pode ser é 18 quintilhões. Muito incrível.
Então, podemos 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 exclusivo. Não estamos limitados pelo número de colunas, então podemos inserir quantos dados quisermos. 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á o registro necessário. 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 muitos dados. E, por exemplo, precisamos procurá-los pelo segundo campo. Para 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. Campo é o número do campo ao qual vinculamos o índice e especificamos a string de tipo. 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 em 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, há duas horas.
Salvar a cada segundo também não funcionará - porque despejar constantemente 20 GB no disco não funciona.
Para isso, o conceito de log write-ahead foi inventado e implementado. Ele cria uma entrada em um pequeno arquivo de log write-ahead para cada alteração nos dados.
Cada entrada antes do ponto de verificação é salva neles. Para esses arquivos, definimos o tamanho - por exemplo, 64 MB. Quando fica cheio, a gravação começa indo para o segundo arquivo. E depois de reiniciar, o Tarantool restaura do último ponto de verificação e, em seguida, rola todas as transações posteriores até parar.
Para fazer essa gravação, você precisa especificar a 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 Tarantula para armazenar dados e funcionará muito rapidamente como um banco de dados. E agora a cereja no topo do bolo - o que você pode fazer com tudo.
Escrevendo um aplicativo
Por exemplo, vamos escrever um aplicativo para Tarantula
Veja o aplicativo sob o 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 algum rótulo em lua que define símbolos. Esta placa é necessária para gerar uma linha 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 parênteses.
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 enviaremos ao cliente.
local http_router = require('http.router')
local http_server = require('http.server')
local json = require('json')
Depois disso, iniciamos na porta 8080 em todas as interfaces do servidor http, que irá 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 a rota que se uma solicitação com o método GET chega à porta 8080 / contagem, então chamamos a função de uma linha. Ele retorna o 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, nele especificamos count e getcount, que é chamado e mostra o número de registros em nosso banco de dados.
Método dois
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.
Bar local token = randomString (32) - é uma string Randomnaya de 32 caracteres.
Linha local last = box.space.example: len () retiramos o último elemento
e na linha box.space.example: insert {last + 1, token} escrevemos em nosso banco de dados, ou seja, apenas aumentamos o ID em 1. Isso pode ser feito aliás, não só dessa forma desajeitada. No Tarantula existem sequências para esse negócio.
Escrevemos um token lá.
Assim, escrevemos um aplicativo em um arquivo. Nele, você pode lidar imediatamente com os dados, 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 com rapidez suficiente.
Para executar, instalamos o módulo http:
Como fazemos isso, olhe por baixo 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:/#
Começamos 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 fazer um benchmark com 50.000 consultas. Haverá 500 solicitações 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:/#
Os tokens são emitidos. E estamos constantemente registrando dados. 99% das solicitações foram concluídas em 42 milissegundos. Assim, temos cerca de 3.500 solicitações por segundo em uma máquina pequena, onde há 2 núcleos e 4 gigabytes de memória.
Você também pode selecionar cerca de 50.000 tokens e ver seu valor.
Você pode usar não apenas http, você pode 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 scripts de aplicativos diretamente no próprio servidor de banco de dados e ser ilimitado, conectar quaisquer módulos e implementar qualquer lógica.
Um servidor de aplicativos pode acessar servidores externos, coletar dados e armazená-los em seu banco de dados. Os dados deste banco de dados serão usados por outros aplicativos.
Isso será feito pelo próprio Tarantula, e não há necessidade de escrever um aplicativo separado.
Finalmente
Esta é apenas a primeira parte de muito trabalho. O segundo será publicado em breve no blog do Grupo Mail.ru e, com certeza, adicionaremos um link para ele neste artigo.
Se você está interessado em participar de eventos onde criamos tais coisas online e fazer perguntas em tempo real, entre no canal DevOps by REBRAIN .
Se você precisar mudar para a nuvem ou tiver dúvidas sobre sua infraestrutura, fique à vontade para deixar uma solicitação .
PS Temos 2 auditorias gratuitas por mês, talvez o seu projeto esteja entre elas.