整车SOA组网与服务发现管理

目录

前言

注册中心 - Service Registry

FDBus的分层服务发现策略

服务发现各级描述

节点(子系统)内服务发现 – Name Server

服务地址解析

服务地址分配

内部服务地址分发

内部服务地址上报

外部服务地址转发

访问授权控制

域内服务发现 - Domain Host Server

整车内服务发现 - Vehicle Host Server

车云一体服务发现 - Cloud Host Server

服务发现的范围控制


前言

随着整车E/E架构从面向信号到面向服务转变,SOA有(Service Oriented Architecture)逐步取代SOA(Signal Oriented Architecture)的趋势(后面提到的SOA指的是前者)。SOA的一大特点是服务的分布式,但分布式导致模块之间的联系变得松散,因而需要跟踪和管理服务状态,引入服务的发现过程,把一个松散的分布式系统融合成一个整体,使得服务动态部署,动态配置,动态扩展,动态加载成为可能。可以说,没有完善的服务发现配合,部署SOA反而会“弄巧成拙”,不但SOA的优势无法体现,还会让分布式带来的副作用变得十分突出。本文以FDBus为例,介绍服务发现中遇到的问题和实现方案,以期为正在向SOA转型的E/E架构提供一种参考设计。

注册中心 - Service Registry

服务发现的实现方式有两种:基于组播和基于注册中心。基于组播比较简单,建立并加入组播组就可以实现一对多的广播,但可靠性,安全性和扩展性都存在不足,跨网络,跨平台方面也有限制。另外没有服务器做地址分发也意味着缺少集中的服务管理和权限管控,无法控制服务可被发现的范围,构筑分级、分区域的网络。

服务发现的另一种方案是基于注册中心的方式,把服务地址和状态收集在一起并发布给订阅者。通常的实现方式是:在系统里运行一个叫做service registry的服务,所有服务端启动后都要向它注册登记;所有客户端启动后向它订阅服务,获取已上线服务的状态和地址。原理上这样做是对的,但要落实到现实中的整车网络,需要考虑的因素很多,并非一个简单的service registry可以完成的:

首先,整车由许多域控制器组成,每个域控制器包含许多服务。域控制器之间通过局域网相连。对于比较复杂的域控制器,内部包含多个子系统(节点),子系统之间由另一个内部网络相连,如下图所示。在这样的网络环境下,service registry应该部署在哪个设备上?

 理想的方案是部署在所有系统都能访问到的节点或设备上,例如网关或TBox。但实际情况是:

  1. 对于复杂的域控制器内部的子系统,有的可能只挂在内部局域网上,未与整车网络相通,故无法访问位于网关或TBox里的service registry。
  2. 有的子系统甚至没有挂在任何局域网上,只在内部组成封闭的SOA环境,这种情况下更加无法访问service registry,但也采用了SOA,同样存在服务发现的需求。

其次,从功能和安全性考虑,即便节点可以访问service registry,也不能或没必要把服务全部暴露给其它域控制器,有的服务特别是内部服务只希望在一定范围内可以访问。例如告警服务只希望在仪表子系统内部使用,多媒体服务只希望在信息娱乐域内部使用等等。如果只部署单一service registry,很难控制服务发现的范围。

再次,如果service registry位于外部,服务的注册和订阅要从局域网绕一圈,导致服务发现成为瓶颈,尤其在启动阶段会拖慢整个系统的启动时间。

然后,service registry这么重要的服务一旦出问题或不可访问,会导致整车所有的服务都无法解析,所有域无论内部服务还是外部服务都不能访问。这样脆弱的架构在车上是无法接受的。

最后,单一的service registry不利于多方合作开发。通常各个域是由不同的供应商开发的,假如service registry位于网关里,那么在网关开发完成之前,其它各域自身的开发都要受影响,因为缺少网关里的service registry这个重要的服务。

FDBus的分层服务发现策略

考虑到上述问题,FDBus既基于中心化的service registry,又采用分层级的服务发现策略,在不同的范围内和层次上管理服务发现,满足未来E/E架构的需求。下面是FDBus在车内典型的组网图:

上图不但包含车内组网,也把位于云端的后台服务囊括进来,组成一个统一的SOA系统,无论服务部署在云端,还是车内,都能通过服务发现建立起端到端的连接。图中服务发现分成四个层次,从下往上分别是:

  • 节点
  • 整车
  • 车云一体

例如QNX/Android等操作系统代表一个节点,它们隶属于域infotainment domain controller,该域又隶属于整车,整车隶属于车云一体。下图表示这些层次的包含关系:

以上层次划分是一个例子,FDBus支持灵活的组网方式,可以根据实际情况部署各种拓扑结构的网络。

FDBus的服务发现由两个模块负责:name serverhost server。Name server部署在每个节点(操作系统)上,负责节点内服务管理;多个节点上的name server可以连接到同一个host server上,组成一个域,Host server相当于一座桥梁,使得域内的各节点上的服务可以互相发现。但不同域之间的服务是隔离的,为此多个域的host server又可以利用更高一级的host server作为桥梁,从而打通这些域之间的服务发现,让服务可以在更广的范围暴露并被发现。

上图中,host server A联通了两个域:B和C,以及两个节点:D和E。如果没有host server A,那么host B和C是两个独立域,name server D和E是两个独立节点,B,C,D,E下面的服务只能在各自内部被发现,而不能被其它域或节点发现。

服务发现各级描述

节点(子系统)内服务发现 – Name Server

节点代表由一个操作系统主宰的子系统,例如Windows,QNX,Linux等。从使用者角度,通信双方不关心对方在节点内还是跨网络,只希望通过服务发现建立起端到端的连接。节点内部的服务发现由name server来承担:每个节点必须部署一个name server,用于管理本节点内部服务的注册和订阅。各节点负责各自内部的服务发现,解决了上述service registry异地部署导致的性能问题和可靠性问题:name server可以在第一时间在节点建立服务发现机制,确保本地服务和客户端快速建立连接。当然若要和其它节点建立连接,还得等到上级host server打通网络连接。

name server是个非常重要的服务,它的职责包括:

服务地址解析

name server维护一张【服务名-服务地址】转换表,包含所有已上线的服务的名字-地址映射。这张表是动态的,服务注册成功会添加相关项到表里,服务下线会从表里删除相关项。Name server将变化广播给前来订阅的客户端,从而实现节点内部的服务发现过程。服务名是一个任意字符串,通常采用分层级,方便记忆的方式,例如com.company.component.service。作为服务的标识,客户端通过该名字查询,订阅,跟踪服务状态。

服务地址分配

从使用者角度并不关心服务的地址,只关心服务名。但名字只是用来标识服务,通信双方建立连接需要的是底层协议栈能识别的地址,例如IP地址+端口号。因此name server还要负责分配用于底层通信的地址,包括两种类型:节点内地址和网络地址。

  1. 节点内地址:在类unix(Linux,QNX等)主机上,节点内通信采用UDS,因此节点内地址就是UDS地址。UDS地址又有两种形式:文件名和抽象名。两种形式FDBus都支持,并且能够确保在同一节点内名字不会发生冲突。对于Windows,由于(10之前的版本)不支持UDS,本地地址采用回环地址,即127.0.0.1,或localhost。
  2. 网络(INET)地址:由于一个节点有多个网卡,因此一个服务可以绑定多个network interface,为来自多个子网的客户端提供服务。例如位于安卓系统的导航可以通过内部网络把信息传给仪表显示,也可以接受来自整车网络上其它节点的导航请求。网络地址分配的目的是在多个子网(或interface或IP地址)上为服务分配唯一的端口号,避免端口冲突。端口号分配有两种策略,一种是主动分配:name server从端口60003开始到65535的范围内寻找空闲的端口分配给各个服务;一种是系统分配:服务端bind地址时如果不指定端口号,操作系统会自动分配一个,然后再把该号返还给name server记录在案,供客户端连接使用。

UDS和网络地址都使用socket,基本用法一致,但细节上略有区别,主要包括:

  1. 节点内采用UDS(Unix Domain Socket),网络上采用INET socket
  2. UDS地址是字符串或文件名,INET地址是IP+Port
  3. UDS不会被窃听,无需施加PKI之类的安全机制;INET则不然
  4. 但UDS也有自己的安全机制,例如可以用PEERCRED作认证,INET socket不支持
  5. Windows直到10后才支持UDS,因此Windows节点内也用INET socket
  6. UDS不支持组播,也无需UDP连接

Name server需要填平这些差异,使其对使用者透明。另外对于IP相同的网络地址,一个服务也可能绑定多个端口:一个端口传输普通的TCP,一个端口传输加密的TCP,一个端口传输普通UDP。

综上,对于每一个服务,name server可能分配以下地址:

地址类型

属性

格式

节点内地址

不加密UDS或TCP回环

/tmp/fdb-ipc1(UDS)或tcp://127.0.0.1:60004

网卡1地址

不加密TCP

tcp://192.168.0.7:60004

加密TCP

tcps://192.168.0.7:60004

不加密UDP

由于一个服务必须绑定TCP地址,不能只绑定UDP地址,因此UDP地址只用端口号表示,其IP地址就是上面TCP地址里的IP部分

网卡2地址

不加密TCP

tcp://192.168.1.7:60004

加密TCP

tcps://192.168.1.7:60004

不加密UDP

端口号

网卡n地址

Name server会把这些地址都发给服务端,服务端同时绑定所有地址,处理来自这些地址的客户端请求。

内部服务分发

内部服务分发是指把节点内部服务地址广播给订阅了该服务的客户端,从而建立到服务端的直连。前面提到,服务端可能会绑定多个地址,但不能把所有地址都发给客户端去连接,既浪费资源也没这个必要,况且不是所有地址在任何地方都能连上,例如其它节点上的内部地址或路由达不到的子网地址。Name server有一套默认策略为不同的客户端挑选合适的地址:如果服务和客户端位于同一节点,毫无疑问分发的是节点内部地址;对于跨网络的访问,分发的是和客户端在同一子网的网络地址(包括普通TCP,加密TCP和UDP地址),确保客户端和服务端不用路由就能直接访问。客户端收到从name server传过来的地址后,会利用这些地址建立和服务端的点对点连接,在随后的数据交换时能够根据不同业务类型选择合适的传输通道。

内部服务上报

内部服务上报是指把节点内服务列表上报给上级host server(如果存在),从而把内部服务暴露给外部,能够被其它节点发现。

外部服务转发

外部服务转发是指把来自host server的外部服务列表在节点内做广播,发送给订阅了相关服务的客户端。这是和上面“内部服务上报”对应的:这里转发的外部服务来自其它节点上报的内部服务。

访问授权控制

访问授权控制类似Adaptive AUTOSAR的IAM(Identity and Access Management),的目的是为某个服务端的不同客户端授予不同的访问权限,避免未授权的客户端访问敏感数据或执行有破坏性的操作。FDBus采用类似Oauth类似的授权方式,name server在其中扮演了authorization server的角色。首先name server为每个前来注册的服务分配若干个token,每个token代表一种权限。name server会把为某个服务分配的token全部发送给服务端。服务端保存这些token,用于随后客户端前来连接时的权限判断。

接下来,当客户端向name server订阅某个服务时,name server会鉴别客户端的身份。支持UDS的操作系统通常也支持PEERCRED选项,能够通过socket连接获得对方的uid/gid,再根据预先定义的配置表查出uid/gid对应的权限。每个服务都有自己的配置表,定义各种uid/gid的客户端所拥有的权限。根据查找出来的权限,从若干个token中取出和该权限对应的token,连同解析出来的服务地址一并发给客户端。

客户端通过地址连接到服务,并把从name server获取的token呈现给服务。服务端用该token和上面收到的若干token做比对,匹配哪个token就说明客户端拥有该token对应的权限。至于如何使用该权限由每个服务端自己来决定,一般发生在如下场合:

  1. 收到客户端的事件订阅请求时,服务端根据客户端的权限以及事件的敏感程度决定是否接受订阅。如果客户端没有权限订阅,该订阅请求将失败,客户端没法获得事件相关的任何数据
  2. 收到客户端方法调用请求时,服务端根据客户端的权限以及方法调用的后果决定是否执行方法调用。如果客户端没有执行该方法的权限,请求将不被执行,客户端的操作不会产生任何效果

对于访问权限控制还有几点说明:

  1. 由于Windows 10之前的版本不支持UDS,故不支持访问权限控制。
  2. 之所以使用token,而非服务端从UDS直接获得客户端的uid/gid,是因为还有连接可能来自INET socket,但它不支持PEERCRED,无法得到对方的uid/gid。token是个字符串,可以在两类socket上面传输。当token足够长,足够随机时,客户端几乎无法猜测和仿冒。
  3. 目前token只在服务注册时动态创建,只要服务不下线就不会更新。将来可以考虑动态更新。
  4. token是敏感数据,通过INET socket传输时不能用明文,需要加密,否则若被恶意截获就可以仿冒高权限的客户端。上面提到,每个server可以绑定一个加密的TCP通道,token可以通过加密通道传输。对于UDS,由于无法被截获,可以不加密。

域内服务发现 - Domain Host Server

Host server能够连通服务发现,从而把多个节点聚合成一个域,或者把多个域聚合成一个大域,或者把多个节点和多个域混合成一个大域。车载系统里,由于Hypervisor的采用,有的domain可能会有多个节点,例如信息娱乐域,SOC上可能会同时运行QNX和Android,虽然位于同一个SOC上,但还是被认为是两个节点。若要服务发现能够跨越这两个域,在启动各自的name server时,可以指定连接到同一个host server上。至于该host server的部署,可以位于域中任意一个节点上,也可以位于域外节点上。但通常会部署在域中启动较快,连通性好,可靠性高的节点上。至于选择把哪些节点组合到一个域里,取决于节点之间的关系。如果节点之间有大量交叉访问,意味着存在大量跨节点的服务发现需求,那么可以考虑把这些节点挂在同一host server下。

节点里的name server会把各自的【服务名-服务地址】转换表发给host server,由host server转发给域里每个节点的name server里,后者接着在节点内做广播。这种方式理论上可以实现全域的服务发现。但对直连的name server,host server采用另外一种策略:host server不转发服务列表表,而是把所有name server的信息收集在一张表里,并把表广播给所有直连的name server。根据表中的地址,各name server之间会两两建立连接,也就是说域里一个name server会和其它所有name server建立直连,组成一个网状结构。

由于name server之间是互通的,任何一个节点内local service table的变化都可以直接广播给域中其它name server,进而广播给节点内服务的订阅者,从而实现服务发现过程。该方案好处是可靠性高,容错性好,一旦网建成,即使host server由于种种原因无法访问,服务发现还是可以在节点之间正常开展。

整车内服务发现 - Vehicle Host Server

域内打通了,接下来再看一下跨域的服务发现如何实现,这就涉及到vehicle host server。类似的,如果把各个域的domain host server连接到同一台vehicle host server上,那么这些域之间的服务发现就打通了:一个服务一旦在name server里注册成功,更新后的服务列表将被通知到domain host server,再通知到vehicle host server,然后下发到所有域的domain host server,再下发给域内的name server,最后发布给订阅者,如下图所示:

图中最左边有服务上线,name server把更新的服务列表上报给上级host server,host server层层上报,层层转发,把服务同步到整个网络,从而实现整车的服务发现。第二个name server没有接收来自host server的广播,是因为上面讲的,同一个域里的name server是两两直连,无需绕行host server。

站在更高的角度,host server相当于服务发现的连通器,把来自一个连接的服务列表转发到所有其它连接上,最后由name server发布给客户端。

车云一体服务发现 - Cloud Host Server

车云一体是FDBus的一大特色:服务和客户只关心端到端的连接,不必考虑对方究竟是部署在节点内部,域内,甚至是云上。FDBus可以将服务发现扩展到云端:假设云端也运行了FDBus服务,为了让所有的车都能发现这些服务,可以采取同样的方式:在云端运行name server和cloud host server,把云端的服务组成一个域。所有车上的vehicle host server都连接到cloud host server上,从而打通车和云的服务发现。一旦云端有服务上线,其地址信息就能通过cloud host server->vehicle host server->domain host server->name server到达车内每个节点,订阅了该服务的客户端就可以直接连接云端服务。整个路径虽然比较长,但是一来云端服务数量不会很多,二来服务状态不会经常变化,所以从数据量和频率都是可控的。

对于车云一体,需要注意的是,首先通常服务发现是单向的,只有车能发现云,云不用发现车,因为车没必要对外暴露服务。其次云服务绑定的地址必须是公网地址,否则无法从车端连接。最后,由于车的数量巨大,车云之间host server的连接数也很多。如果采用长连接将造成资源浪费。为此可以采用优化策略,例如平时vehicle host server和cloud host server之间是断开的,只有当有客户端订阅了服务,且该服务在车内部无法解析(即车上不存在该服务)时,才连接到cloud host server,监控云端的服务变化。一旦所有服务都解析完毕,即可再次断开连接。

服务发现的范围控制

上面介绍了服务发现如何从节点内逐步走向整车直至车云一体,从而构筑起一张巨大的服务发现网络。但正如前述,从安全角度,不是所有服务都适合大范围公开;从组网角度不是所有服务都能被大范围访问到(例如内网服务);从功能角度,不是所有服务都需要被大范围使用。因此对特定服务,需要限制其可被发现的范围,避免带来不必要的麻烦。

由于host server是连接服务发现的枢纽,故可以在其向转发服务列表时实施控制,例如采用黑白名单的方式,限制哪些服务可以向上转发,哪些服务可以向下转发,哪些不能,从而有效管理特定服务的可发现范围。

关于FDBus

FDBus(Fast Distributed Bus),旨在提供高速,分布式,跨进程,跨节点,跨网络,可靠,可伸缩的SOA实现,满足未来物联网,整车E/E架构需要。

FDBus已经迁移到gitee上,原来在github的仓库已不再维护:

https://gitee.com/jeremyczhen/fdbus

截止到FDBus  5.2.0,服务发现的大部分功能已完成,黑白名单尚待实现,期待在不远的将来能进一步完善,把FDBus打造成满足未来整车E/E架构的SOA方案。

  • 14
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
整车SOA架构是指在整车设计和制造领域中,使用面向服务的架构(Service Oriented Architecture,简称SOA)来构建整车系统。 整车SOA架构的核心思想是将整车系统划分为一系列相互独立的服务,每个服务负责一个特定的功能或业务。这些服务通过标准化的接口进行通信和交互,可以在不同的硬件平台和软件环境下进行部署和运行。这样的架构可以提高整车系统的可扩展性、灵活性和可维护性。 整车SOA架构的优势主要体现在以下几个方面: 1. 模块化设计:整车系统被分解为多个相互独立的服务,每个服务专注于一个特定领域的功能。这种模块化的设计使得整车系统更易于开发、测试、部署和维护。 2. 业务分离:不同的服务可以由不同的团队开发和维护,各自独立于彼此。这样可以提高开发效率,同时降低开发过程中的风险。 3. 服务复用:整车系统中的服务可以在不同的应用场景中进行复用,避免了重复开发和维护。这不仅提高了开发效率,还可以降低整车系统的成本。 4. 松耦合:每个服务只暴露必要的接口,对外界的变化具有较高的容忍性。这样可以降低整车系统中不同模块之间的耦合度,提高系统的灵活性和可扩展性。 整车SOA架构虽然有很多优点,但也存在一些挑战和限制。例如,服务之间的同步通信可能会引入较大的延迟,需要进行合理的性能优化。此外,服务接口的设计和管理也是一个关键问题,需要进行规范化和标准化的处理。 总的来说,整车SOA架构在整车设计和制造领域具有重要的应用价值,可以提高整车系统的可扩展性、灵活性和可维护性。随着技术的发展和应用的深入,整车SOA架构有望在未来得到更广泛的应用和推广。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值