一、服务提供方的处理模式概述
文档主要讨论了服务提供方在ara::com
框架下的事件驱动和轮询两种处理模式,以及它们的特点和应用场景。
二、事件驱动处理模式
-
工作原理:
- 在纯事件驱动的设置中,通信管理会生成相应的调用事件,并将这些事件转换为对服务实现提供的服务方法的具体方法调用。
- 服务消费者的服务调用到来时,
ara::com
实现将异步将事件分派给服务方法实现。
-
优缺点:
- 优点:对服务方法调用的一般反应可能会很快,因为延迟仅受一般机器负载和内在 IPC 机制延迟的限制。
- 缺点:包含服务实例的操作系统进程的上下文切换率可能会很高且不确定,从而降低整体吞吐量。
三、轮询处理模式
-
设置与调用方法:
- 如果将处理模式设置为
kPoll
,ara::com
实现将不会异步调用任何提供的服务方法。 - 要处理下一个挂起的服务调用,必须在服务实例上调用
ara::core::Future<bool> ProcessNextMethodCall();
方法。
- 如果将处理模式设置为
-
返回值作用:
- 返回的
ara::core::Future<bool>
允许在 “下一个请求” 被处理时得到通知,有助于将服务方法调用一个接一个地连接起来。 - 如果队列中存在未完成的请求并且已被分派,返回的
bool
值为true
,否则为false
。
- 返回的
-
对 AP 产品的影响及队列位置:
- 对于基于典型操作系统的 AP 产品,轮询模式会排除由通信管理事件导致的进程上下文切换。
- 队列必须在服务提供应用程序的地址空间之外实现,或者位于共享内存之类的位置,以便发送方能够直接写入队列。
- 典型的队列位置解决方案包括内核空间(如果绑定实现使用套接字或管道机制,目标内核缓冲区类似队列,但调整缓冲区大小可能需要重新编译内核)和不同绑定 / 通信管理守护应用程序的用户地址空间(在用户空间内分配队列的缓冲区空间更灵活)。
四、代码示例
- 服务实现方的请求处理模式枚举:
/*** 服务实现方(骨架)的请求处理模式。* * \note 平台供应商应完全按照此方式提供。*/
enum class MethodCallProcessingMode { kPoll, kEvent, kEventSingleThread };
- 轮询模式下获取下一个调用并执行的方法:
/*** 从通信管理中获取下一个调用并执行它。* * 仅在轮询模式下可用。*/
ara::core::Future<bool> ProcessNextMethodCall();
五、kEvent
和kEventSingleThread
的区别
-
kEvent
:意味着ara::com
实现可以同时调用服务方法实现。例如,来自不同服务消费者的多个调用可以同时被执行,ara::com
实现允许从其内部线程池中获取多个线程同时为多个服务方法执行调用。 -
kEventSingleThread
:确保在服务实例上,ara::com
实现每次只调用一个服务方法。ara::com
实现必须为同一服务实例的传入服务方法调用事件排队,并一个接一个地分派它们。
六、提供两个变体的原因
从功能角度看,只有kEvent
似乎就足够了,但对于某些由于共享数据 / 一致性需求而无法同时运行服务方法的服务实现,可以简单地自己进行同步(如通过std::mutex
)。提供两个变体的原因是 “效率”。如果服务实例实现具有广泛的同步需求,几乎会同步所有服务方法调用,那么如果通信管理从其线程池资源中 “花费”N
个线程,而这些线程在直接获得硬同步后,将N - 1
个线程发送到睡眠状态,这将是一种资源浪费。