Интеграция open62541 в существующий цикл обработки событий libev

У меня есть существующее приложение, которое широко использует libev для своего цикла обработки событий. Теперь я хотел бы добавить функциональность сервера OPC UA, но не уверен, как лучше всего интегрировать цикл событий open62541 в libev.

На ум приходят следующие возможности:

  1. Вызов UA_Server_run_iterate из цикла событий libev со временем waitInternal, равным 0. Это будет означать, что сервер никогда не сможет спать (опрос open62541 в ev_idle), или что запросы от клиента OPC UA будут испытывать дополнительную задержку до 50 мс. (максимальное время ожидания по умолчанию open62541).
  2. Патч open62541, позволяющий извлекать файловые дескрипторы, используемые в данный момент (серверные сокеты и соединения) на сетевом уровне сервера. Это позволит добавлять события libev для этих файловых дескрипторов, которые, в свою очередь, могут опрашивать UA_Server_run_iterate только при необходимости.
  3. Реализуйте собственный сетевой уровень сервера, использующий libev. Похоже, это подразумевает довольно частое дублирование кода ... Есть ли какие-нибудь примеры / учебные пособия для реализации настраиваемого сетевого уровня?
  4. Запустите цикл событий open62541 в отдельном потоке. Я действительно очень хочу избежать этого, поскольку вся цель системы событий, такой как libev, - избежать проблем, связанных с асинхронной работой. Например, все обратные вызовы от open62541 должны будут синхронизироваться с основным потоком libev.

Какой из вышеперечисленных вариантов вы считаете лучшим с точки зрения сложности и производительности?

Можете ли вы придумать какие-либо другие варианты, не перечисленные выше?


Также размещен в списке рассылки open62541.


person Johannes Zeppenfeld    schedule 16.01.2019    source источник
comment
Пожалуйста, избегайте двойных публикаций в разных сообществах. Об этом уже спрашивали здесь groups.google.com/forum/m/# ! topic / open62541 / 7rcE6hYP55s   -  person Stefan Profanter    schedule 16.01.2019
comment
@StefanProfanter Извините, я надеялся передать это и сообществу libev, после того как я уже разместил его в списке рассылки open62541. Что бы вы порекомендовали как способ достижения двух разрозненных сообществ?   -  person Johannes Zeppenfeld    schedule 16.01.2019
comment
Без проблем. Вы должны хотя бы упомянуть кросс-пост, чтобы синхронизировать потоки и сообщить другим, что в другом потоке могут быть дополнительные ответы.   -  person Stefan Profanter    schedule 16.01.2019
comment
Также посмотрите meta.stackexchange.com/questions/64068/   -  person Stefan Profanter    schedule 16.01.2019


Ответы (1)


Я бы рекомендовал либо вариант 1, либо вариант 2. (Отказ от ответственности: я один из основных разработчиков open62541)

  1. Вызов UA_Server_run_iterate из цикла обработки событий libev с временем waitInternal, равным 0. Это либо означает, что сервер никогда не может спать (опрос open62541 в ev_idle), либо запросы от клиента OPC UA будут испытывать дополнительную задержку до 50 мс. (максимальное время ожидания по умолчанию open62541).

На данный момент это, вероятно, лучший вариант, на который вы могли бы пойти. Вы можете вызывать UA_Server_run_iterate через фиксированный интервал, например каждые 10 мс, в зависимости от требований приложения. Все остальные параметры требуют исправления open62541, и в настоящее время во внутреннем API много чего происходит, поскольку в настоящее время добавляются многие функции. Также посмотрите мою заметку в конце!

  1. Патч open62541, позволяющий извлекать файловые дескрипторы, используемые в данный момент (серверные сокеты и соединения) на сетевом уровне сервера. Это позволит добавлять события libev для этих файловых дескрипторов, которые, в свою очередь, могут опрашивать UA_Server_run_iterate только при необходимости.

Вероятно, вам не нужно исправлять open62541, поскольку вы можете получить дескриптор файла сокета через сетевой уровень конфигурации сервера, если сетевой уровень является уровнем TCP: server->config.networkLayers[i].serverSockets[j]. Это также может потребовать большого объема работ по техническому обслуживанию, поскольку могут быть разные типы сетевых уровней. Например. pubsub использует UDP, где сокеты хранятся внутри config->pubsubTransportLayers

  1. Реализуйте собственный сетевой уровень сервера, использующий libev. Похоже, это подразумевает довольно частое дублирование кода ... Есть ли какие-нибудь примеры / учебные пособия для реализации настраиваемого сетевого уровня?

Вы можете реализовать свой собственный сетевой уровень, используя интерфейс плагина, то есть написать свой собственный (https://github.com/open62541/open62541/blob/master/arch/ua_network_tcp.c). Поскольку здесь используется внутренний API, вы можете ожидать много работы по обслуживанию и исправлению исправлений. -> Слишком много работы

  1. Запустите цикл обработки событий open62541 в отдельном потоке. Я действительно очень хочу избежать этого, поскольку вся цель системы событий, такой как libev, - избежать проблем, связанных с асинхронной работой. Например, все обратные вызовы от open62541 должны будут синхронизироваться с основным потоком libev.

Я бы сказал, что это не лучший вариант, поскольку вы вводите асинхронные обратные вызовы.


Общее примечание:

В настоящее время у нас есть внутренний черновик и эскиз для доработки сетевого интерфейса, особенно с одним выбором для всех FD сокетов. В настоящее время у нас есть несколько вариантов выбора для нескольких FD.

Также обратите внимание на следующий PR, где мы уже начали переделку: https://github.com/open62541/open62541/pull/2271

person Stefan Profanter    schedule 16.01.2019