Интеграция open62541 в существующий цикл событий libev
У меня есть приложение, которое широко использует libev для цикла обработки событий. Теперь я хотел бы добавить функциональность сервера OPC UA, но не уверен, как лучше интегрировать цикл событий open62541 в libev.
На ум приходят следующие возможности:
- Вызов
UA_Server_run_iterate
из цикла событий libev сwaitInternal
время 0. Это будет означать, что сервер никогда не может спать (опрос open62541 вev_idle
) или что запросы от клиента OPC UA будут иметь дополнительную задержку до 50 мс (максимальное время ожидания по умолчанию open62541). - Патч open62541, чтобы разрешить поиск файловых дескрипторов, используемых в настоящее время (serverSockets и соединения) сетевым уровнем сервера. Это позволило бы добавить события libev для тех файловых дескрипторов, которые могли бы, в свою очередь, опрашивать
UA_Server_run_iterate
только когда это необходимо. - Реализуйте пользовательский сетевой уровень сервера, который использует libev. Кажется, это подразумевает частичное дублирование кода... Есть ли примеры / учебные пособия для реализации пользовательского сетевого уровня?
- Запустите цикл обработки событий open62541 в отдельном потоке. Я действительно очень хочу этого избежать, поскольку вся цель системы событий, такой как libev, состоит в том, чтобы избежать проблем, связанных с асинхронной работой. Например, все обратные вызовы из open62541 должны были бы синхронизироваться с основным потоком libev.
Какой из вышеперечисленных вариантов вы бы посчитали "лучшим" с точки зрения сложности и производительности?
Можете ли вы вспомнить какие-либо другие варианты, не перечисленные выше?
1 ответ
Я бы порекомендовал либо вариант 1, либо вариант 2. (Отказ от ответственности: я один из разработчиков ядра open62541)
- Вызовите UA_Server_run_iterate из цикла событий libev с временем ожидания InInternal равным 0. Это может означать, что сервер никогда не будет спать (опрос open62541 в ev_idle), или что запросы от клиента OPC UA будут испытывать дополнительную задержку до 50 мс. (максимальное время ожидания по умолчанию open62541).
На данный момент это, вероятно, лучший вариант, который вы могли бы пойти. Вы можете вызывать UA_Server_run_iterate через фиксированный интервал, например каждые 10 мс, в зависимости от требований приложения. Все остальные опции требуют исправления open62541, и в настоящее время во внутреннем API многое происходит, так как многие функции добавляются в настоящее время. Также посмотрите мою заметку в конце!
- Патч open62541, чтобы разрешить поиск файловых дескрипторов, используемых в настоящее время (serverSockets и соединения) сетевым уровнем сервера. Это позволит добавить события libev для этих файловых дескрипторов, которые, в свою очередь, могут опрашивать UA_Server_run_iterate только при необходимости.
Возможно, вам не нужно исправлять open62541, поскольку вы можете получить дескриптор файла сокета через сетевой уровень конфигурации сервера, если сетевой уровень является уровнем TCP: server->config.networkLayers[i].serverSockets[j]
, Это также может привести к большим объемам работ по техническому обслуживанию, поскольку могут быть разные типы сетевых уровней. Например, pubsub использует UDP, где сокеты хранятся внутри config->pubsubTransportLayers
- Реализуйте пользовательский сетевой уровень сервера, который использует libev. Кажется, это подразумевает частичное дублирование кода... Есть ли примеры / учебные пособия для реализации пользовательского сетевого уровня?
Вы можете реализовать свой собственный сетевой уровень, используя интерфейс плагина, то есть написать свой собственный ( https://github.com/open62541/open62541/blob/master/arch/ua_network_tcp.c). Поскольку это использует внутренний API, вы можете ожидать много работы по обслуживанию и исправлению патчей. -> Слишком много работы
- Запустите цикл обработки событий open62541 в отдельном потоке. Я действительно очень хочу этого избежать, поскольку вся цель системы событий, такой как libev, состоит в том, чтобы избежать проблем, связанных с асинхронной работой. Например, все обратные вызовы из open62541 должны были бы синхронизироваться с основным потоком libev.
Я бы сказал, что это не очень хороший вариант, поскольку вы вводите асинхронные обратные вызовы.
Общее примечание:
В настоящее время у нас есть внутренний черновик и эскиз для доработки сетевого интерфейса, особенно один выбор для всех FD сокетов. В настоящее время у нас есть несколько вариантов выбора для нескольких FD.
Также взгляните на следующий PR, где мы уже начали с переделки: https://github.com/open62541/open62541/pull/2271