Потоки приложения
Потоки приложения позволяют коду приложения использовать дополнительные потоки для выноса части работы из основного потока.
Как и основной поток, каждый поток приложения выполняет независимый цикл событий и интерпретатор Lua, и для него доступно большинство встроенных модулей Tarantool.
Чтобы включить потоки приложения, добавьте в файл конфигурации раздел
верхнего уровня threads с подразделом groups. Например, чтобы
создать две группы потоков приложения — http с одним потоком и app
с четырьмя потоками, используйте следующую конфигурацию:
threads:groups:- name: httpsize: 1- name: appsize: 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: secretprivileges:- permissions: [execute]lua_call: [test_func]threads:groups:- name: appsize: 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 doprint(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.