Основная конфигурация
Основная кoнфигурация системы состоит из набора xml файлов, расположенных в config директории. Каждому xml файлу соответствует свой xsd файл, который служит для проверки валидности конфигурации. xsd файлы расположены с config/.xsd директории. Помимо xml/xsd файлов используется dll.c исходник, который также расположен с config директории и служит для настройки роутинга сообщений в системе. Самым важным файлом конфигурации является init.xml:
<?xml version="1.0"?>
<config>
<node
wait_timeout_ms="1000"
log_level="debug"
/>
<app>
<timesheets>
<timesheet name="holidays">
<off from="00:00:00 06/12/22" till="00:00:00 06/12/22"/>
</timesheet>
</timesheets>
<schedule>
<timesheet include="holidays">
<on from="09:30:00 mon" till="23:50:00 mon"/>
<on from="09:30:00 tue" till="23:50:00 tue"/>
<on from="09:30:00 wed" till="23:50:00 wed"/>
<on from="09:30:00 thu" till="23:50:00 thu"/>
<on from="09:30:00 fri" till="23:50:00 fri"/>
</timesheet>
<nodes>
<node id="4" name="rts_exec_cgate" group="exchange" cmd="${XROAD_ROOT_DIR}/bin/rts_exec_cgate" />
<node id="5" name="moex_exec_fix" group="exchange" cmd="${XROAD_ROOT_DIR}/bin/moex_exec_fix" />
<node id="7" name="cur_exec_fix" group="exchange" cmd="${XROAD_ROOT_DIR}/bin/moex_exec_fix" />
<node id="6" name="rts_exec_fix" group="exchange" cmd="${XROAD_ROOT_DIR}/bin/rts_exec_fix" />
<node id="10" name="rts_mdata_cgate" group="mdata" cmd="${XROAD_ROOT_DIR}/bin/rts_mdata_cgate" />
<node id="18" name="curr_ol_fast" group="mdata" cmd="${XROAD_ROOT_DIR}/bin/mdata_fast" />
<node id="19" name="fond_ol_fast" group="mdata" cmd="${XROAD_ROOT_DIR}/bin/mdata_fast" />
<node id="12" name="perfbot4" group="algo" />
<node id="13" name="elabhft" group="algo" />
<node id="14" name="perfbot5" group="algo" />
<node id="20" name="sitrade" group="algo" />
<node id="21" name="indicator" group="algo" config="py_algo" schema="py_algo" env="PYTHONPATH=/opt/algo/indicator1:${PYTHONPATH}" cmd="${XROAD_ROOT_DIR }/bin/py_algo -a -p /opt/algo/indicator1/basis_ema_ind_new.py"/>
</nodes>
</schedule>
<schedule>
<timesheet>
<on from="00:00:00 mon" till="23:59:59 mon"/>
<on from="00:00:00 tue" till="23:59:59 tue"/>
<on from="00:00:00 wed" till="23:59:59 wed"/>
<on from="00:00:00 thu" till="23:59:59 thu"/>
<on from="00:00:00 fri" till="23:59:59 fri"/>
<on from="09:00:00 sat" till="23:59:59 sat"/>
<on from="09:00:00 sun" till="23:59:59 sun"/>
</timesheet>
<nodes>
<node id="99" name="egate" group="tools" cmd="${XROAD_ROOT_DIR}/bin/egate" />
<node id="100" name="mail_agent" group="tools" cmd="${XROAD_ROOT_DIR}/pbin/mail_agent.py" />
<node id="101" name="ctl" group="tools" />
<node id="102" name="instr_load" group="tools" />
<node id="103" name="stat" group="tools" cmd="${XROAD_ROOT_DIR}/bin/stat" />
</nodes>
</schedule>
</app>
</config>
В этом файле определяется, какие ноды надо запустить и когда. Как видно из примера, в конфигурацию добавлены 2 секции <schedule> (9-30, 32-49). Ноды в этих секциях сгруппированы по расписанию запуска, которое задается тэгом <timesheet> (10-16, 33-41). Правило <on> задает время когда нода должна быть активной. Например,
<on from="09:30:00 mon" till="23:50:00 mon" />
говорит о том, что нода должна быть активной (в состоянии active) с 9:30 понедельника до 23:50:00 понедельника. Остальное время нода должна оставаться в состоянии offline. В тэге <nodes> задаются ноды, которые должны быть запущены. 18-24, 43-44, 47 - эти ноды запускаются при старте системы. Ноды 25-28, 45-46 не запускаются при старте системы, а запускаются вручную по усмотрению и под контролем пользователя. Возможные aтрибуты тэга <node>:
- id - обязательный атрибут. Определяет уникальный id ноды. Используется для общения нод между собой. Id 1 зарезервирован для суперноды xroad_init
- name - обязательный атрибут. Определяет уникальное имя ноды. При старте ноды ищется конфигурационный файл name.xml и name.xsd. Если соответствующий xml/xsd не будет найден, то нода запущена не будет.
- group - oбязательный атрибут. Определяет группу ноды. Ноды могу быть сгруппированы логически по усмотрению пользователя. Например, по функционалу - биржевые коннекторы сгруппированы в группу exchange, коннекторы - провайдеры рыночных данных - mdata и т.д. Никакого особого функционала группировка не несет, но позволяет, например, отравить всем нодам из какой-нибудь группы сообщение
- env - необязательный атрибут. Позволяет указать переменные окружения для запускаемой ноды. Например расширяет PYTHONPATH для ноды inicator.
- cmd - необязательный атрибут. Определяет команду которую выполняет супернода xroad_init для запуска ноды. Если этот атрибут не задан, то нода является stand alone, т.е. не запускается при старте системы, а запускается пользователем самостоятельно
- delay_start_s - необязательный атрибут. Определяет задержку запуска ноды в секундах
- delay_kill_s - необязательный атрибут. Определяет задержку остановки ноды (kill signal) в секундах
- max_restarts - необязательный атрибут. Определяет количество попыток перезапуска ноды супернодой, в случае ее падения. По умолчанию 10 раз
- hidden - необязательный атрибут. Скрытая нода. Не отображается на WebUI
- memory_locked - необязательный атрибут. Если атрибут установлен true, то вся выделяемая память ноды будет блокирована в ОЗУ, для предотвращения свапирования (man mlock)
- offline_primary - необязательный атрибут. Определяет, что в primary системе нода будет оставаться offline даже если она должна активироваться исходя из расписания
- offline_backup - необязательный атрибут. Определяет, что в backup системе нода будет оставаться offline даже если она должна активироваться исходя из расписания
- config - необязательный атрибут. Определяет файл конфигурации для этой ноды. К примеру, для ноды с именем rts_exec_cgate должны быть определен config/rts_exec_cgate.xml. config атрибут, если он определен, задает альтернативное название конфигурации. Т.е. если config="test", для ноды rts_exec_fix будет искаться конфигурация test.xml
- schema - необязательный атрибут. Определяет файл схемы конфигурации для этой ноды. К примеру, для ноды с именем rts_exec_cgate должна быть определена схема config/.xsd/rts_exec_cgate.xsd. schema атрибут, если он определен, задает альтернативное название схемы конфигурации. Т.е. если schema="test", для ноды rts_exec_fix будет искаться схема config/.xsd/test.xsd
- cpus - необязательный атрибут. Задает номера CPU к которым данная нода будет прикреплена. По умолчанию "" т.е. нода будет запускаться любых cpu доступных системе. Можно указать какие-то конкретные CPUID, так и диапазоны CPUID1-CPUIDN
- scheduler - необязательный атрибут. Определяет IO scheduler процесса. По умолчанию берется стандартный scheduler OS. Возможные значения: default, other, fifo, rr, batch, idle, deadline. См. "man sched_setscheduler"
- sched_priority - необязательный атрибут. См. "man 7 sched"
- nice - необязательный атрибут. Приоритет процесса. См. "man nice"
Настройка общих секций расписания
В init.xml можно отдельно указать общие части расписания и подключить их для отдельных групп нод. Для этого нужно перечислить в отдельном теге <timesheets> диапазоны c именами. В дальнейшем по имени можно подключить нужную часть расписания для группы нод через аттрибут include как это сделано для первой группы.
Переменные окружения системы
В конфигурации возможно использование переменных окружения. Переменные окружения определяются как ${variable_name}. Например:
<?xml version="1.0"?>
<config>
<node
log_level="info"
wait_timeout_ms="0"
/>
<fast_engine>
<channel name="OLI" heartbeat="40">
<feed_a address="udp://0.0.0.0;239.195.10.40:44040;91.203.253.233" recv_buf_size="1048576"/>
<feed_b address="udp://0.0.0.0;239.195.138.40:45040;91.203.255.233" recv_buf_size="1048576"/>
<recovery name="OLS" heartbeat="10" cycled_sn="true">
<feed_a address="udp://0.0.0.0;239.195.10.41:44041;91.203.253.233" recv_buf_size="1048576"/>
<feed_b address="udp://0.0.0.0;239.195.138.41:45041;91.203.255.233" recv_buf_size="1048576"/>
</recovery>
</channel>
<channel name="INI" heartbeat="40">
<feed_a address="udp://0.0.0.0;239.195.5.12:36012;91.203.253.232" recv_buf_size="1048576"/>
<feed_b address="udp://0.0.0.0;239.195.133.12:37012;91.203.255.232" recv_buf_size="1048576"/>
<recovery name="INS" heartbeat="10" cycled_sn="true">
<feed_a address="udp://0.0.0.0;239.195.5.11:36011;91.203.253.232" recv_buf_size="1048576"/>
<feed_b address="udp://0.0.0.0;239.195.133.11:37011;91.203.255.232" recv_buf_size="1048576"/>
</recovery>
</channel>
</fast_engine>
<mdata_engine filter_not_subscribed="true">
<server address="${FORTS_MD}" cpu="7"/>
</mdata_engine>
<app fix_crossed_book="false" book_levels="2" trades="true"/>
</config>
здесь используется переменная окружения FORTS_MD. В момент создания ноды производится следующая последовательность действий:
- конфигурация xml считывается из xml файла
- ищутся все переменные окружения ${var}
- если переменна найдена, то сначала ищется ее значение в переменных окружения OS. Если такая переменная не найдена, то она ищется в файле config/env.xml. env.xml - это специальный файл конфигурации, который является общим для всей системы, содержащий какие-то общие значения настроек. Например это могут быть значения host:port для подключения к бирже, логины, и т.д.
- Если значение переменной найдено, то оно подставляется в xml вместо названия переменной
- Если переменная не находится, то процедура чтения xml прерывается с ошибкой
- После того как все переменные были заменены на соответствующие значения выполняется валидация и обогащение xml при помощи xsd схемы
- Если шаг 6 выполнен успешно, то шаги 2-3 повторяются снова и если они завершаются успешно, то прочитанная конфигурация может использоваться дальше нодой
Добавление ноды
Предположим, что нам надо добавить ноду с именем robot в систему. Для этого необходимо выполнить следующие шаги:
- Убедится, что для ноды есть соответствующие xml/xsd файлы в config директории. В нашем случае это robot.xml, robot.xsd Минимальная конфигурация может выглядеть следующим образом
robot.xml: <?xml version="1.0"?>
<config>
<node
log_level="debug"
/>
</config>
robot.xsd: <?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="node.xsd"/>
<xs:element name="config">
<xs:complexType>
<xs:sequence>
<xs:element name="node" type="node_type" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
- Добавить ноду в config/init.xml:
<?xml version="1.0"?>
<config>
<node
wait_timeout_ms="1000"
log_level="debug"
/>
<schedule>
<timesheet>
<on from="09:30:00 mon" till="23:50:00 mon"/>
</timesheet>
<nodes>
<node id="5" name="moex_exec_fix" group="exchange" cmd="${XROAD_ROOT_DIR}/bin/moex_exec_fix" />
<node id="10" name="rts_mdata_cgate" group="mdata" cmd="${XROAD_ROOT_DIR}/bin/rts_mdata_cgate"/>
<node id="11" name="curr_mdata_fast" group="mdata" cmd="${XROAD_ROOT_DIR}/bin/moex_mdata_fast"/>
<node id="15" name="fond_mdata_fast" group="mdata" cmd="${XROAD_ROOT_DIR}/bin/moex_mdata_fast"/>
<node id="20" name="robot" group="algo" cmd="${XROAD_ROOT_DIR}/bin/robot"/>
</nodes>
</schedule>
<schedule>
<timesheet>
<on from="00:00:00 mon" till="23:59:59 mon"/>
</timesheet>
<nodes>
<node id="99" name="egate" group="tools" cmd="${XROAD_ROOT_DIR}/bin/egate" />
<node id="101" name="ctl" group="tools" />
<node id="102" name="instr_load" group="tools" />
</nodes>
</schedule>
</config>
- Обратите внимание на строку 17. Здесь мы добавили новую ноду номер 20 с именем robot в группу algo. При старте ноды должен быть запущен исполняемый файл robot, который расположен в ${XROAD_ROOT_DIR}/bin
- После того как все изменения были сделаны их необходимо проверить. Для это надо запустить в консоли скрипт ./check_cfg.sh:
./check_cfg.sh
✔ build routing libraries
✔ check env config
✔ check cache config
✔ check init config
✔ check config
- Если система уже запущена, в чем можно убедится, запустив скрипт
./view.sh
то ее надо информировать о произошедших изменениях. Это можно сделать 2-мя способами:
- Если система не была запущена, то запускаем ее скриптом start.sh
- После этого надо убедится, что нода была успешно запущена. Для этого запускаем
./view.sh
скрипт и убеждаемся, что
- нода запущена и имеет соответствующее состояние (active, inactive)
- если нет ноды с таким именем или счетчик ошибок init ноды увеличится, это означает, что нода запущена не была
- если нода robot появилась в списке, но статус этой ноды DEAD, это означает, что в процессе запуска ноды произошлa ошибка. Для поиска причины, почему нода не была запущена требуется посмотреть логи:
- /var/log/syslog
- лог ноды init
- лог ноды, запуск которой не удался (в нашем случае data/robot/lots/XXXXXXX.log)
- Если требуется запустить stand alone ноду, т.е. ноду, запускаемую вручную, но при этом которая должна быть частью системы необходимо выполнить шаги 1-6, с той лишь разницей, что при добавлении ноды в config/init.xml не указывается cmd атрибут. В таком случае система только выделяет место для такой ноды в писке нод, не производя при этом запуск. Запуск самой ноды происходит вручную. Для этого надо запустить ноду с флагом -s c указанием имени ноды (в нашем случае нода называется robot)
bin/robot -s robot
Удаление/остановка ноды
Для того, чтобы остановить ноду надо:
- закомментировать запись с добавленной нодой в config/init.xml
- выполнить пункты 4-5 раздела Добавление ноды
- убедится, что нода была остановлена, запустив скрипт
./view.sh.
Нода в списке должна иметь статус DEAD
- Note
- если нода была остановлена во время работы системы, то она не удаляется из списка доступных нод. Она удаляется из списка только после остановки системы и повторного запуска с предварительной очисткой кэша системы