☞返回总目录
相关总结:AutoSar AP简单多绑定总结
7.3 多绑定
如在 5.4.3 小节中简要讨论的,某个代理类 / 骨架类的不同实例之间的技术传输是不同的,多绑定描述了这种情况的解决方案。多种技术原因都可能导致这种情况出现:
- 代理类使用不同的传输 / IPC 与不同的骨架进行通信。
- 同样地,对于同一个骨架实例的不同代理实例,也可能使用不同的传输 / IPC 与这个骨架实例进行通信,即骨架实例支持多种传输机制的连接。
7.3.1 简单多绑定的用例
下图描绘了一个简单多绑定的用例。例子中,服务消费者和服务提供者在同一个节点(ECU 内部)中进行通信,服务消费者拥有同一个代理类的两个实例。图中可以看出,服务消费者首先触发了一个 “FindService”,它为搜索到的两个不同服务实例返回了两个句柄。服务消费者为每个句柄实例化了一个代理实例。在这个例子中,服务实例 1 与服务消费者(代理实例 1)位于同一个 AP 应用程序(相同的进程 / 地址空间)中,而服务实例 2 与服务消费者(代理实例 2)位于不同的 AP 应用程序(不同的进程 / 地址空间)中。
图 7.3 中,象征代理和骨架之间传输层的线条颜色不同:代理实例 1 有一个红色的传输层(绑定实现),而代理实例 2 的传输层是蓝色的。颜色不同是因为在代理实现层面上使用的技术不同。如果想努力打造一个性能良好的产品,AP 产品供应商(作为 IPC 绑定实现者的角色)需要这样做!
如图所示,因为代理实例 1 和骨架实例 1 包含在一个进程中,代理实例 1 和服务实例 1 之间的通信(红色)应该优化为一个简单的方法调用。因为代理实例 2 和服务实例 2 之间的通信(蓝色)是真正的 IPC,所以采取的行动成本要高得多,很可能涉及各种系统调用 (涉及到内核上下文切换),以便将调用 / 数据从服务消费者的进程传输到服务提供者的进程(通常使用像管道、套接字或共享内存这样的基本技术,并加上一些用于控制信号)。
从服务消费者开发者角度来看,供应商的 ProxyClass::FindService 实现为两个服务实例获得两个不透明的句柄,从这两个句柄中创建了同一个代理类的两个代理实例。“神奇地” 是,这两个代理实例虽然基于相同的代理类而创建,但是与各自的服务实例连接方式完全不同。所以,句柄中一定以某种方式包含了一些信息,代理类实例从这些信息中知道选择哪种技术传输。虽然乍一看很简单,但再看就不是了…… 问题是:是谁,在什么时候,把这些信息写入句柄中,使得从它创建的代理实例知道应该使用直接方法(函数调用),而不使用更复杂的 IPC 机制,或者反之亦然?
服务实例 1 通过 SkeletonClass::OfferService 在注册表(服务发现)中注册自己的时候吗?这取决于稍后使用它的服务消费者,所以很可能, AP 供应商的 SkeletonClass::OfferService 实现是从骨架的参数中获取所需信息,并通过特定的 IPC 通知 AP 供应商的注册表(服务发现)实现。前面句子中提及许多 “AP 供应商” 是有意的,只是表明,这里讨论的机制都没有标准化,因此可以由 AP 供应商设计和优化。然而,基本步骤将保持不变。所以通常在 SkeletonClass::OfferService 过程中从服务实例传递到注册表(服务发现)的是技术寻址信息,即如何通过本地 IPC 实现连接该服务实例。
通常在一个 AP 节点内部只会使用一种 IPC 机制!如果 AP 供应商在 AP 应用程序之间已经拥有一个优化的本地 IPC 实现,那么 AP 节点内部通常都会使用这个实现。所以 —— 在例子中,假设底层的 IPC 机制是 Unix 域套接字 —— 骨架实例 1 将创建一个套接字连接的文件描述符,并在 OfferService 期间将这个描述符传递给注册表(服务发现)。骨架实例 2 也是如此,只是描述符不同。当服务消费者执行 FindService 时,注册表将把两个服务实例的寻址信息发送给服务消费者(它们作为两个可见的不透明句柄)。
所以在这个例子中,这些句柄看起来完全相同 —— 只有一个小区别,即包含的文件描述符不同,因为它们引用不同的 Unix 域套接字。所以在这种情况下,在代理实例 1 中必须以某种方式检测到直接方法(比如:函数调用)的优化。一种可能的简单技巧是,在骨架实例 1 提供给注册表(服务发现)的寻址信息中,也包含进程的 ID(pid);要么显式地包含,要么将其包含在套接字描述符文件名中。所以服务消费者一侧的代理实例 1 可以简单地检查句柄中的 PID 是否表示与自身相同的进程,然后可以使用优化路径。顺便提一下:检测进程本地优化潜力是一件很平常的事情,几乎每个现有的中间件实现今天都在做 —— 所以无需进一步强调这个话题。
退一步的讲,我们必须认识到,这里的简单例子并没有完全反映多绑定的含义。它确实描述了同一个代理类的两个实例使用不同的传输层来联系服务实例的情况,但正如例子所示,这并没有反映在不同实例的句柄中,而仅仅是一种优化!在我们的具体例子中,使用代理实例 1 与服务实例 1 通信的服务消费者也可以像代理实例 2 一样使用 Unix 域套接字传输,而不会有任何功能损失 —— 只是从非功能性能的角度来看,这显然不好。尽管如此,这个简单的场景还是值得在这里提及,因为它是一个真实的场景,很可能在许多部署中发生,因此必须得到很好的支持!