Tarantool CE/EE Documentation portal logo
Помощь
Обновлена 2 ноября 2026 г. в 15:35

Потоки приложения

Потоки приложения позволяют коду приложения использовать дополнительные потоки для выноса части работы из основного потока.

Как и основной поток, каждый поток приложения выполняет независимый цикл событий и интерпретатор Lua, и для него доступно большинство встроенных модулей Tarantool.

Включение потоков приложения

Чтобы включить потоки приложения, добавьте в файл конфигурации раздел верхнего уровня threads с подразделом groups. Например, чтобы создать две группы потоков приложения — http с одним потоком и app с четырьмя потоками, используйте следующую конфигурацию:

threads:  groups:    - name: http      size: 1    - name: app      size: 4

Группа потоков tx с одним потоком создается неявно всегда. Ее можно использовать для вызова основного потока из других потоков, как описано ниже.

Использование потоков приложения

Для взаимодействия с потоками приложения был разработан встроенный Lua-модуль threads. Он предоставляет следующие функции:

  • threads.call() вызывает функцию в группе потоков.
  • threads.export() экспортирует локальную Lua-функцию, чтобы ее можно было вызвать с помощью threads.call() из других потоков.
  • threads.eval() выполняет выражение Lua в группе потоков.
  • threads.info() возвращает информацию о настроенных группах потоков и текущем потоке.

Модуль threads доступен во всех потоках. Его можно использовать в основном потоке еще до того, как Tarantool будет сконфигурирован, но в этом случае единственной доступной целью будет группа потоков tx, поскольку группы потоков приложения создаются в процессе конфигурирования.

Как и основной поток, потоки приложения могут предоставлять функции через IPROTO с помощью вызова box.iproto.export. Если функция предоставлена в одном или нескольких потоках, IPROTO перенаправляет запросы CALL для этой функции в один из потоков, где она предоставлена. Чтобы вызвать функцию в потоке приложения, у пользователя должна быть привилегия lua_call для этой функции, либо он должен быть администратором.

Пример

Ниже приведен пример предоставления функции через IPROTO в потоках приложения.

iproto:  listen:    - uri: localhost:3301credentials:  users:    client:      password: secret      privileges:        - permissions: [execute]          lua_call: [test_func]threads:  groups:    - name: app      size: 4app:  module: test_maingroups:  group-001:    replicasets:      replicaset-001:        instances:          instance-001: {}
-- test_main.lualocal threads = require('threads')threads.eval('app', [[require('test_thread')]])
-- test_thread.lualocal threads = require('threads')box.iproto.export('test_func', function()    local info = threads.info()    return string.format('Hello from thread %s/%d',                         info.group_name, info.thread_id)end)
-- test_client.lualocal net = require('net.box')local conn = net.connect(3301, {user = 'client', password = 'secret'})for i = 1, 10 do    print(conn:call('test_func'))endos.exit()

Чтобы запустить пример, выполните следующую команду:

tarantool -c config.yaml -n instance-001

Затем запустите клиент в другом терминале:

tarantool test_client.lua

Будет выведено что-то вроде следующего:

Hello from thread app/4Hello from thread app/2Hello from thread app/1Hello from thread app/2Hello from thread app/4Hello from thread app/4Hello from thread app/4Hello from thread app/3Hello from thread app/2Hello from thread app/2

Представления для чтения в потоках приложения

Представление для чтения, открытое в основном потоке, можно использовать совместно с потоком приложения, запущенным через box.cfg{app_threads = ...}. Для этого передайте id представления для чтения в поток приложения и откройте его там по этому id:

box.cfg{app_threads = 1}box.schema.space.create('test')box.space.test:create_index('primary')box.space.test:replace({1, 'x'})local rv = box.read_view.open({name = 'shared_read_view'})local threads = require('threads')threads.eval('app', [[  local rv = box.read_view.open({id = ...})  return rv.space.test:select()]], {rv.id})

Новое представление для чтения по-прежнему можно создать только в основном потоке: вызов box.read_view.open() без id в потоке приложения приводит к ошибке. Аналогично, box.read_view.list() можно вызвать только в основном потоке.

Если представление для чтения, используемое потоком приложения, закрывается в основном потоке, оно не удаляется сразу — его статус меняется на close_pending. Представление для чтения в этом статусе нельзя использовать в основном потоке или повторно открыть в другом потоке, но потоки, которые уже открыли его, могут продолжать использовать его вплоть до своей остановки. После того как последний пользователь перестает его использовать, представление для чтения удаляется глобально — явно либо через сборку мусора Lua.