将 open62541 集成到现有的 libev 事件循环中

Integrating open62541 into an existing libev event loop

我有一个现有的应用程序,它在事件循环中广泛使用了 libev。我现在想添加 OPC UA 服务器功能,但不确定如何最好地将 open62541 事件循环集成到 libev 中。

想到以下可能性:

  1. 从 libev 事件循环中调用 UA_Server_run_iteratewaitInternal 时间为 0。这意味着服务器永远无法休眠(在 ev_idle 中轮询 open62541),或者来自 OPC UA 客户端的请求将经历最多 50 毫秒的额外延迟(open62541 的默认最大等待时间)。
  2. 修补 open62541 以允许服务器网络层检索当前使用的文件描述符(服务器套接字和连接)。这将允许为这些文件描述符添加 libev 事件,这些文件描述符可以轮流轮询 UA_Server_run_iterate 仅在必要时。
  3. 实现一个使用 libev 的自定义服务器网络层。这似乎意味着相当多的代码重复...是否有任何 examples/tutorials 用于实现自定义网络层?
  4. 运行 open62541 事件循环在单独的线程中。我真的真的很想避免这种情况,因为像 libev 这样的事件系统的全部目的是避免与异步操作相关的问题。例如,来自 open62541 的所有回调都必须与主 libev 线程同步。

在复杂性和性能方面,您会考虑以上哪个选项"best"?

你能想到上面没有列出的任何其他选项吗?


Also posted on open62541 mailing list.

我推荐选项 1 或选项 2。(免责声明:我是 open62541 的核心开发人员之一)

  1. Call UA_Server_run_iterate from within the libev event loop with a waitInternal time of 0. This would either mean that the server could never sleep (polling open62541 in an ev_idle), or that requests from an OPC UA client would experience an additional latency of up to 50ms (the default max wait time of open62541).

目前这可能是您可以采用的最佳选择。您可以按固定间隔调用 UA_Server_run_iterate,例如,每 10 毫秒,具体取决于应用程序的要求。所有其他选项都需要对 open62541 进行修补,目前内部 API 正在进行很多工作,因为目前正在添加许多功能。最后也看看我的笔记吧!

  1. Patch open62541 to allow retrieval of the file descriptors currently in use (serverSockets and connections) by the server network layer. This would allow adding libev events for those file descriptors, which could in turn poll UA_Server_run_iterate only when necessary.

您可能不需要修补open62541,因为如果网络层是TCP层,您可以通过服务器配置的网络层获取套接字的文件描述符:server->config.networkLayers[i].serverSockets[j]。 这也可能引入大量维护工作,因为可能有不同种类的网络层。例如。 pubsub 使用 UDP,套接字存储在 config->pubsubTransportLayers

  1. Implement a custom server network layer that makes use of libev. This seems to imply quite a bit of code duplication... Are there any examples/tutorials for implementing a custom network layer?

您可以使用插件接口实现您自己的网络层,即编写您自己的 (https://github.com/open62541/open62541/blob/master/arch/ua_network_tcp.c)。由于这是使用内部 API,您可能需要进行大量维护工作和补丁修复。 -> 工作太多

  1. Run the open62541 event loop in a separate thread. I really really really want to avoid this, since the whole purpose of an event system such as libev is to avoid issues associated with asynchronous operation. For example, all callbacks from open62541 would have to synchronize with the the main libev thread.

我会说这不是一个好的选择,因为你引入了异步回调。


一般注意事项:

我们目前有一份内部草案和草图来重新设计网络接口,特别是有一个 select 用于所有套接字 FD。目前我们有多个 select 用于多个 FD。

另请查看我们已经开始返工的以下 PR: https://github.com/open62541/open62541/pull/2271