SOA 服务设计-传统车载架构的迭代升级

随着行业的SOA 理念大火,带着一系列的解读和思考观点横行于世,笔者大多仔细研读过,虽然增加了很多碎片化知识和曾经的盲点,但也同样带来了更多的疑惑,本文撰写初衷是基于车厂的角度思考,如何在现有整车架构和软件资产下,进行SOA的设计开发,并从工具链和操作方法上给出案例。

1. 分布式ECU-基于信号的架构设计

之前分析了后续车载网络整体架构的升级迁移路线,

智能网联汽车总线发展趋势将会是怎样?

现在我们来看,在域控制器开发阶段,针对传统车厂,在分布式ECU,或区域控制器集成,已经有了深厚的架构开发和经验积累的前提条件下,如何转型并进行中央域控的服务设计。
本章节描述现阶段,面对分布式ECU,如何进行基于信号的整车电子电器架构开发。如下为介绍MBSE理论的较为经典文章。

窦明佳:面向服务的电子电气架构开发与传统的电子电子电气架构开发的区别

服务设计相对软件架构设计影响较大,接下来着重分析SOA服务设计。

2. 中央域控架构-基于SOA服务设计

1652179227020.png

为了后续方便理解,我们大致把国内的整车电子电器架构分为三个阶段:

  • 1.0 架构: 以逆向分析为主,整合现阶段市面上供应商的零部件,实现整车功能(典型代表 比亚迪F3)
  • 2.0 架构: 以正向开发为主,融合国内外先进经验技术,进行整车多车型的架构开发(典型代表 吉利CMA架构)
  • 3.0 架构:硬件上从分布式ECU变为整车域控架构,软件上由基于signal变为SOA ,能够大幅降低车辆上ECU数量,软件迭代速度也由质的飞跃(典型代表 特斯拉)

2.1. 服务设计依据

  • 总体采用自上而下与自下而上想结合的形式进行服务定义。
  • 针对网络上全拓补硬件,进行自下而上设计,将其分为传感器,执行器,与单功能ECU三类,分别针对硬件进行设备抽象api设定,与原子服务抽象。
  • 针对整车功能定义FR与FDR ,进行自上而下设计,首先使用面向对象的思维进行整车的类抽象,然后设计类的方法与属性,其中属性尽量与 原子服务进行映射,方法需要使用一个或多个原子服务进行实现
  • 最终进行原子服务,与整车类的属性与方法进行映射,找出无法实现的类,以及没有使用到的原子服务,此部分进行服务代理设计,及使用传统SWC软件模块实现部分功能,然后代理成组合服务形式,参与整车架构设计。

1652179294147.png

2.2. SOA 设计区别

3.0架构全面采用SOA(service-oriented Architecture)设计思想进行构建,上一代2.0架构采用的是 POP(procedure oriented programming)面向过程的设计思想,需要注意的是,在SOA设计中,自上而下的设计方法中引入了OOP(object oriented programming)面向对象的抽象与封装概念,这是为了在2.0现有架构基础上,能够继承原有FR,FDR,LC,然后进行迭代开发。

也就是说通过Class的抽象,在原有LC一层新添加了类图的设计,通过抽象的类进行用例设计进行功能链路实现。后续进行服务化设计,只要满足类中的属性和方法能够实现即可,而不必去关心设计的服务如何支撑整个子系统及功能链路的实现。

  • POP 面向过程设计
    在2.0架构中,首先要进行Composition 功能组合的划分,然后在进行Component 功能组件的划分,每个组件都有相应的输入和输出信号,依据这些来实现高内聚,低耦合的功能点实现,设计好组件/组合之后,然后进行模块间接口信号的设计,每个模块平均有20个左后的输入和输出信号
  • SOA 面向服务设计
    在3.0架构中,首先要进行服务的划分和设计,每个服务是松耦合的,也就是分治的设计理念,及服务里包含的方法、event、field具备高扇入,合理的扇出,而服务所抽象的数据要与处理的业务逻辑、流程、功能实现三方解耦,所设计的基础服务也要与操作系统解耦。对比2.0中的设计,可以类似的理解为2.0先设计软件模块,然后设计信号接口,而3.0 soa后先设计服务接口(此接口不仅包含类似信号的event,还包含类似函数的method方法),有了服务之后,在设计哪些模块提供这些服务,哪些模块订阅服务。
    需要注意,SOA后里的软件模块需要严格的区分server 与 client,也就是一个模块要不就是提供某个或多个服务,要不就是订阅了一个或多个服务,不存在既订阅了一些服务又提供了一些服务的情况,这与2.0架构中的swc软件模块既有输入又有输出完全不一样。
  • OOP 面向对象设计
    在3.0架构中,需要借助面向对象的设计方法来辅助支撑,也就是依托现有2.0架构,不进行大范围重构的前提条件下,使用类抽象出所有LC模块,并且通过设计不同类的用例图来实现原LC处理的功能。

2.0架构上MBSE设计图上LC映射实现

1652179343192.png

3.0架构上MBSE设计图上LC映射实现

1652179370084.png

2.3. 接口命名规范

在进行SOA服务设计时,需要遵循如下命名规范

2.3.1. 基础规范

  1. 尽量采用单词全称,名称过长后才使用缩写
  2. 名称不包含特殊字符,./\~
  3. 名称如果过长,需要参考常用单词缩写表中内容进行缩写
  4. 考虑服务和参数的复用性,各类命名中不应带有拓补节点信息
  5. 不同层级的各类名称不能重复
  6. 命名中不能使用如下系统关键字:
  • skeleton
  • proxy
  • internal
  • resources
  • method
  • event
  • field
  • input/output
  • amsr
  • ara
  • com
  • someip
  • base
  • vac
  • std
  • serialization

    2.3.2. Service Instance 服务实例

服务实例及指代定义的服务实现,后文若单独写服务,则意为服务实例

  1. 服务名采用首字母大写,全英文名称
  2. 服务名不能有下划线
  3. 服务名后缀需要以Srv结尾

eg. LedControlSrv

2.3.3. Service Interface 服务接口

SOA平台上服务之间通信接口有Event、Method和Field三种形式, ServiceInterface 用于定义Event/Method/Field消息类型和具体的命名空间,与具体的通信协议无关。

  1. 服务接口名采用首字母大写,全英文名称
  2. 服务接口名不能有下划线
  3. 服务接口名需要以SrvIf结尾

eg. LedControlSrvIf

2.3.4. Event

Event 接口表示实际传输的数据,以数据为操作对象,只要能够清晰的表达数据的含义即可,命名规范遵循基础规范,后缀要以Evt结尾。

eg. CurrentVleEvt : 电流值

Event 消息传递方式如下图所示,为服务端主动向客户端发送,并且会触发客户端的callback函数进行数据处理。

1652179530611.gif

2.3.5. Method

Mehtod 接口表示某种控制,通讯方式采用RPC远程调用,通常有动词行为,比如控制,状态查询,传输,注册,设置等。其中Method又分为 F&F,与R&R 两类,FF为单次调用,不需要反馈,RR 为request resoponse,需要反馈。

  • 请求-响应(request/response): R&R
  • 请求-响应流(request/stream)
  • 发后不管(fire-and-forget) : F&F
  • 通道模式(channel)

整体设计依据遵循 CURD/REST 这类成熟的互联网通用接口概念

  • CURD
NAME DESCRIPTION SQL EQUIVALENT
Create Adds one or more new entries Insert
Read Retrieves entries that match certain criteria (if there are any) Select
Update Changes specific fields in existing entries Update
Delete Entirely removes one or more existing entries Delete
  • REST
CRUD HTTP
CREATE POST/PUT
READ GET
UPDATE PUT/POST/PATCH
DELETE DELETE

接口名称需要表达清楚该方法的含义,推荐使用动名词进行命名,采用驼峰命名规范,基于如上CURD/REST 参考,命名要以后缀Mtd作为结束,设计如下基础命名范式:

  1. get 获取状态
  2. set 设置状态
  3. report 传递信息
  4. judge 判断事件,返回boolean
  5. create 创建线程/进程/动态服务/文件/事件 等
  6. delete 删除线程/进程/文件 等

eg.

setSoundOnMtd : 鸣响喇叭
judgeVehMovingMtd : 判断车辆是否移动
getCarCfgMtd : 获取 car config 值
reportComponentStsMtd : 上报component 状态信息
createXTaskUsrLightShowSrvMtd : 创建用户自定义的灯光show 服务
deleteDebugClass0MsgMtd : 删除 debug 等级为0 的所有msg 调试文件

Method 消息传递方式如下图所示,为客户端主动向服务端请求,可以设定是否有服务端的返回值。

1652180107756.gif

2.3.6. Field

Field 表示一种属性,通常指状态值或某种信息,名称应该清楚的表达该属性的含义。

Field包含如下三类信息:

  • getter : 只读接口,原型为method,获取服务端信息
  • notifier : 只读接口,原型为event,接收服务端的数据
  • setter : 写入接口,原型为method,设置/修改服务端相关信息

eg. VehMoveFld : 车辆移动控制

Field 消息传递方式如下图所示

1652180150859.gif

3. 服务设计方法

针对大部分OEM,需要在现有整车架构上进行服务设计升级,也就是已有base 的LC需求,和工程级的软件swc,需要依据这两类已有资产,使用OOP面向对象的抽象与封装手段,进行SOA服务化重构。

本章节以车身控制器中 危险报警软件模块为例,说明如何在已有LC需求和软件模块前提下,使用gitee,进行SOA设计。

需要注意的是,在设计服务接口时,要清楚的知道不同接口的实际特性和性能消耗。Event为服务端主动向客户端发送请求,而Method恰好相反,为客户端主动向服务端进行请求调用。根据如上接口描述,整体服务设计遵循如下方案要点。

  • 原2.0平台中信号尽量保留,作为Event接口类型进行预留
  • 服务设计包括 类抽象-服务接口设计-服务实例设计-设计具体的进程/线程 运行此服务实例
  • 每个抽象好的类,对应一个服务接口 : XX_Class -> XX_SrvIf
    • 类中的属性对应 Event 接口类型 XX_Class::value -> XX_SrvIf-valueEvt
    • 类中的方法对应 Method 接口类型 XX_Class::fuction -> XX_SrvIf-valueMtd
    • 尽量不要设计 Field 接口
  • 每个服务接口由一个具体的服务进行实例化 : XX_SrvIf -> XX_Srv
  • 每个实例化的服务,都要设计哪个进程/线程/软件模块/ECU 来提供,哪些App 会订阅
  • App 使用/设定服务里的数据/功能,需要通过CM 通讯管理进行服务的订阅
  • 实例化的服务之间,数据/功能 传递,则直接调用相互暴露的api,可以不用CM 参与(即组合服务和原子服务的关系)
  • App 之间不能直接进行数据传输,需要调用专有的服务进行数据传递(即服务代理模块)

3.1. 需求分析

示例软件模块主要实现危险警报功能,在整车条件允许的情况下,如果按下手机app上的警报按钮,则会触发车辆进行声光报警。

1652180510757.png

需要注意 针对VFC/PNC 相关软件逻辑,虽然在3.0架构上已经不复存在,但是需要保留功能分区划域的思想,也就是针对不同场景需要触发不同的软件组件来执行完成,针对不同的PNC,在3.0 架构上可以作为VLAN划分的设计参考。

使用gitee进行需求编写,与原LC中需求进行追溯

1652182880249.png

3.2. 类的抽象和封装

使用OOP手段,根据需求和已有的软件模块,进行类的抽象,并将有可能被多次调用的软件逻辑进行类方法的封装,后续多次执行的代码逻辑,仅在实例化的类中执行一次即可。

  • 类抽象,将整车从多个角度抽象成不同的类,每个类都可以映射成一个service的实体,不同的软件模块调用相同逻辑时,可以直接订阅此service,使用service中的method、event、field。
  • 类方法封装,将接口进行泛化,封装成通用类的方法,达到松耦合的效果

类图:

1652180752244.png

时序图:

1652180831148.png

3.3. 服务设计

上一章推导出,所设计的类就是一个需要实现服务,根据此原则,在gitee中进行服务设计。

服务设计包含如下步骤和要素:

  1. 服务接口设计(method/event/field)
  2. 接口变量设计(method的入参出参及数据类型,event 变量名及数据类型)
  3. 服务实例设计(发布者,服务ID等信息)

3.3.1. 数据类型设计

Gitee-数据类型中进行数据类型设计

1652183130416.png

3.3.2. 服务接口设计

Gitee-Service接口中进行service接口设计

1652183959850.png

3.3.3. 服务实例设计

Gitee-Service实例中进行服务实例设计

1652184092871.png

3.3.4. 配置文件导出以及代码框架生成

通过gitee能够导出所有服务list的csv 文件,基于此开发工具进行arxml文件和代码框架的转换生成,最终进行基于SOA服务化的软件开发。

代码框架可以参考笔者之前的回答。

C++大型项目怎么管理依赖?

4. 小结

针对已有历史软件资产的厂商,进行SOA 架构升级的方法大致如上,此处借用了gitee企业版辅助进行架构设计,也希望大家意识到,软件定义汽车,不仅仅是软件产品,甚至整车研发的工具链和开发流程也都会慢慢靠向软件开发的生态工具链,抱残守缺,是注定要被时代淘汰的,此处诺基亚和柯达会深有感触。

最后附上最新的SDV 工作组,标准服务的定义文档,去年开始,我们国内的汽车行业也有了属于自己的技术标准组织,SDV-软件定义汽车工作组,负责标准化车辆的服务接口名称;AutoSEMO 中国车辆基础软件协会,负责标准化SOA架构下的中间件开发规范。所以,AutoSAR 的生与死在未来是个值得思考的问题。

SDV API Version 2 -第二部分:设备抽象 API 参考.pdf

SDV API Version 2 -第一部分:原子服务 API 参考.pdf

SDV API-第二部分:设备抽象 API 参考-变更说明.pdf

SDV API-第一部分:原子服务 API 参考-变更说明.pdf