Tarantool 允许您将超快的数据库和应用程序结合起来使用它们。 这就是多么容易做到的事

五年前,我尝试使用 Tarantool,但后来它对我不起作用。 但最近我举办了一次网络研讨会,讨论了 Hadoop 以及 MapReduce 的工作原理。 他们问我一个问题:“为什么不使用 Tarantool 来完成这项任务?”

出于好奇,我决定返回它,测试最新版本 - 这次我真的很喜欢这个项目。 现在我将向您展示如何在 Tarantool 中编写一个简单的应用程序,加载它并检查其性能,您将看到一切是多么简单和酷。

Tarantool 允许您将超快的数据库和应用程序结合起来使用它们。 这就是多么容易做到的事

什么是塔兰图尔

Tarantool 将自己定位为超快数据库。 您可以在那里放置任何您想要的数据。 另外,复制它们、分片——即将大量数据分割到多个服务器上并合并它们的结果——建立容错的主主连接。

其次,这是一个应用程序服务器。 您可以在其上编写应用程序,处理数据,例如,根据一定的规则在后台删除旧记录。 您可以直接在 Tarantula 中编写一个处理数据的 Http 服务器:给出它们的数量,在那里写入新数据并将其全部减少到主服务器。

我读过一篇文章,讲的是这些家伙如何制作一个 300 行的消息队列,这简直就是爆裂和奔涌——他们的性能最低是每秒 20 条消息。 这里你真的可以转身写一个非常大的应用程序,而且它不会像PostgreS那样是存储。

我将在本文中尝试简单地描述类似此服务器的内容。

安装

为了进行测试,我启动了三个标准虚拟机 - 一个 20 GB 硬盘、Ubuntu 18.04。 2 个虚拟 CPU 和 4 GB 内存。

我们安装 Tarantool - 运行 bash 脚本或添加存储库并执行 apt get install Tarantool。 链接到脚本 - (curl -L https://tarantool.io/installer.sh | VER=2.4 sudo -E bash)。 我们有这样的命令:

塔兰图尔克特尔 — 管理 Tarantula 实例的主要命令。
/etc/tarantool - 这是完整的配置。
var/log/tarantool - 这是日志。
var/lib/tarantool ——数据就在这里,然后被分成实例。

有文件夹instance-available和instance-enable - 它包含将要启动的内容 - 带有lua代码的实例配置文件,它描述了它侦听的端口,可用的内存,Vinyl引擎设置,启动时运行的代码服务器、分片、队列、删除过时数据等。

实例的工作方式与 PostgreS 中类似。 例如,您想要运行挂在不同端口上的数据库的多个副本。 事实证明,在一台服务器上启动了多个数据库实例,这些实例挂在不同的端口上。 它们可能具有完全不同的设置 - 一个实例实现一种逻辑,第二个实例实现另一种逻辑。

实例管理

我们有 tarantoolctl 命令,它允许您管理 Tarantula 实例。 例如, tarantoolctl check example 将检查配置文件并说 - 如果那里没有语法错误,则文件没问题。

您可以查看实例的状态 - tarantoolctl status example。 以同样的方式,您可以启动、停止、重新启动。

实例运行后,您可以通过两种方式连接到它。

1. 管理控制台

默认情况下,Tarantool 打开一个套接字,并将普通 ASCII 文本发送到那里来控制 Tarantool。 与控制台的连接始终在 admin 用户下进行,没有身份验证,因此无需外部化控制台端口来管理 Tarantula。

要使用此方法进行连接,您需要输入 Tarantoolctl 输入实例名称。 该命令将启动控制台并以管理员用户身份进行连接。 切勿将控制台端口暴露在外 - 最好将其保留为单元插座。 然后,只有那些有权写入套接字的人才能连接到 Tarantula。

行政事务需要此方法。 要处理数据,请使用第二种方法 - 二进制协议。

2. 使用二进制协议连接到特定端口

该配置包含一个监听指令,它打开一个用于外部通信的端口。 该端口与二进制协议一起使用,并在此处启用身份验证。

对于此连接,使用 tarantoolctl 连接到端口号。 使用它,您可以连接到远程服务器,使用身份验证并授予各种访问权限。

数据记录和盒子模块

由于Tarantool既是数据库又是应用服务器,因此它具有各种模块。 我们对盒子模块感兴趣 - 它实现了数据处理。 当您向 box 写入内容时,Tarantool 会将数据写入磁盘、将其存储在内存中或对其执行其他操作。

记录

例如,我们进入 box 模块并调用 box.once 函数。 这将强制 Tarantool 在服务器初始化时运行我们的代码。 我们创建一个存储数据的空间。

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

之后,我们创建一个主索引 - 主索引 - 我们可以通过它搜索数据。 默认情况下,如果不指定任何参数,则每条记录的第一个字段将用作主索引。

然后我们向来宾用户授予权限,在该权限下我们通过二进制协议进行连接。 我们允许在整个实例上读取、写入和执行。

与传统数据库相比,这里的一切都非常简单。 我们有空间——一个简单存储数据的区域。 每条记录称为一个元组。 它被封装在MessagePack中。 这是一种非常酷的格式 - 它是二进制的,占用的空间更少 - 18 字节与 27 字节相比。

Tarantool 允许您将超快的数据库和应用程序结合起来使用它们。 这就是多么容易做到的事

和他一起工作很方便。 几乎每一行、每条数据记录都可以有完全不同的列。

我们可以使用 Box.space 命令查看所有空间。 要选择特定实例,请编写 box.space example 并获取有关它的完整信息。

Tarantool 有两个内置引擎:Memory 和 Vinyl。 内存将所有数据存储在内存中。 因此,一切都简单而快速地进行。 数据转储到磁盘,并且还有预写日志机制,因此如果服务器崩溃我们不会丢失任何内容。

Vinyl 以我们更熟悉的形式在磁盘上存储数据 - 也就是说,您可以存储比我们内存更多的数据,而 Tarantula 将从磁盘读取它。

现在我们将使用内存。

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>

指数:

必须为任何空间创建主索引,因为没有它什么都无法工作。 与在任何数据库中一样,我们创建第一个字段 - 记录 ID。

部分:

在这里我们指出我们的索引由什么组成。 它由一个部分组成 - 我们将使用的第一个字段是无符号类型 - 一个正整数。 据我所记得的文档,最大数量是 18 quintillion。 好多啊。

然后我们就可以使用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>

第一个字段用作主键,因此它必须是唯一的。 我们不受列数的限制,因此我们可以在其中插入任意数量的数据。 它们以 MessagePack 格式指定,正如我上面所描述的。

数据输出

然后我们可以使用 select 命令显示数据。

Box.example.select 使用 {1} 键将显示所需的条目。 如果我们按下键,我们将看到我们拥有的所有记录。 它们的列数都不同,但原则上,这里没有列的概念 - 有字段编号。

绝对可以有任意数量的数据。 例如,我们需要通过第二个字段搜索它们。 为此,我们创建一个新的二级索引。


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

我们使用 Create_index 命令。
我们称之为次要的。

之后您需要指定参数。 索引类型是TREE。 它可能不是唯一的,因此输入 Unique = false。

然后我们指出我们的索引由哪些部分组成。 Field是我们绑定索引的字段号,并指定字符串类型。 它就这样被创建了。

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>

现在我们可以这样称呼它:

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

保存

如果我们重新启动实例并尝试再次调用数据,我们将看到它不存在 - 一切都是空的。 发生这种情况是因为 Tarantool 会创建检查点并将数据保存到磁盘,但如果我们停止工作直到下一次保存,我们将丢失所有操作 - 因为我们将从最后一个检查点(例如,两个小时前)恢复。

它也无法节省每一秒,因为不断地将 20 GB 数据转储到磁盘上并不是一个好主意。

为此,发明并实现了预写日志的概念。 在它的帮助下,对于数据的每次更改,都会在小型预写日志文件中创建一个条目。

直到检查点的每个条目都存储在其中。 对于这些文件,我们设置大小 - 例如 64 MB。 当它已满时,开始录制到第二个文件。 重启后,Tarantool 将从上一个检查点恢复,然后滚动所有后续事务,直至停止。

Tarantool 允许您将超快的数据库和应用程序结合起来使用它们。 这就是多么容易做到的事

要进行此类记录,您需要在 box.cfg 设置中指定选项(在 example.lua 文件中):

wal_mode = “write”;

数据使用

根据我们现在编写的内容,您可以使用 Tarantula 来存储数据,并且它将作为数据库快速运行。 现在,您可以用这一切来做锦上添花的事情。

编写应用程序

例如,我们为狼蛛编写以下应用程序

请参阅剧透下方的应用程序

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

我们在 lua 中声明一些定义字符的表。 需要该板来生成随机字符串。

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

之后,我们声明函数 - randomString 并在括号中给出长度值。

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

然后我们将 http 路由器和 http 服务器连接到我们的 Tarantula 服务器 JSON,我们将其发送到客户端。

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

之后,我们从所有 http 服务器接口上的端口 8080 启动,这将记录所有请求和错误。

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

接下来,我们声明路由,以便如果使用 GET 方法的请求到达端口 8080 /count,则我们从一行调用该函数。 它返回状态 - 200、404、403 或我们指定的任何其他状态。

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

在正文中,我们返回 json.encode,其中我们指示 count 和 getcount,调用它并显示数据库中的记录数。

第二种方法

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)

在哪里排队 路由器:路由({方法='GET',路径='/令牌'},函数() 我们调用该函数并生成一个令牌。

本地令牌 = randomString(32) 是一个 32 个字符的随机字符串。
排队 本地最后 = box.space.example:len() 我们取出最后一个元素。
并在行中 box.space.example:insert{ 最后 + 1, 标记 } 我们将数据写入数据库,也就是说,我们只需将 ID 加 1。顺便说一句,这不仅可以通过这种笨拙的方式完成。 塔兰图拉毒蛛中有这样的序列。

我们在那里写令牌。

因此,我们将应用程序编写在一个文件中。 您可以在那里直接操作数据,盒子模块将为您完成所有脏活。

它监听 http 并处理数据,一切都在一个实例中 - 应用程序和数据。 因此,一切都发生得很快。

首先我们安装 http 模块:

我们如何做到这一点,请看剧透

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

我们还需要 prometheus 来运行:

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

我们启动并可以访问模块

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 给我们状态 200。
/token 发出一个令牌并将该令牌写入数据库。

测试速度

让我们运行 50 个请求的基准测试。 将有 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:/#

代币已发行。 我们不断记录数据。 99% 的请求在 42 毫秒内得到处理。 因此,在具有 3500 个核心和 2 GB 内存的小型机器上,我们每秒大约有 4 个请求。

您还可以选择一些 50000 个代币并查看其价值。

您不仅可以使用 http,还可以运行处理数据的后台函数。 另外还有各种触发器。 例如,您可以在更新时调用函数,检查某些内容 - 纠正冲突。

您可以直接在数据库服务器本身中编写脚本应用程序,而不受任何限制,连接任何模块并实现任何逻辑。

应用程序服务器可以访问外部服务器、检索数据并将其添加到其数据库中。 该数据库中的数据将被其他应用程序使用。

Tarantula 会自己完成此操作,您无需编写单独的应用程序。

总之

这只是一部伟大作品的第一部分。 第二个将很快发布在 Mail.ru Group 博客上,我们一定会在本材料中添加指向它的链接。

如果您有兴趣参加我们在线构建这些东西并实时提出问题的活动,请收听 REBRAIN 的渠道 DevOps.

如果您需要迁移到云端或对您的基础架构有疑问, 请随时留下请求.

PS 我们每月有 2 次免费审核,也许您的项目就是其中之一。

来源: habr.com

添加评论