隨著行業(yè)的 SOA 理念大火,帶著一系列的解讀和思考觀點(diǎn)橫行于世,筆者大多仔細(xì)研讀過(guò),雖然增加了很多碎片化知識(shí)和曾經(jīng)的盲點(diǎn),但也同樣帶來(lái)了更多的疑惑,本文撰寫(xiě)初衷是基于車(chē)廠的角度思考,如何在現(xiàn)有整車(chē)架構(gòu)和軟件資產(chǎn)下,進(jìn)行 SOA 的設(shè)計(jì)開(kāi)發(fā),并從工具鏈和操作方法上給出案例。
1. 分布式 ECU-基于信號(hào)的架構(gòu)設(shè)計(jì)
現(xiàn)在我們來(lái)看,在域控制器開(kāi)發(fā)階段,針對(duì)傳統(tǒng)車(chē)廠,在分布式 ECU,或區(qū)域控制器集成,已經(jīng)有了深厚的架構(gòu)開(kāi)發(fā)和經(jīng)驗(yàn)積累的前提條件下,如何轉(zhuǎn)型并進(jìn)行中央域控的服務(wù)設(shè)計(jì)。
本章節(jié)描述現(xiàn)階段,面對(duì)分布式 ECU,如何進(jìn)行基于信號(hào)的整車(chē)電子電器架構(gòu)開(kāi)發(fā)。如下為介紹 MBSE 理論的較為經(jīng)典文章。 服務(wù)設(shè)計(jì)相對(duì)軟件架構(gòu)設(shè)計(jì)影響較大,接下來(lái)著重分析 SOA 服務(wù)設(shè)計(jì)。
2. 中央域控架構(gòu)-基于 SOA 服務(wù)設(shè)計(jì)
為了后續(xù)方便理解,我們大致把國(guó)內(nèi)的整車(chē)電子電器架構(gòu)分為三個(gè)階段:
1.0 架構(gòu): 以逆向分析為主,整合現(xiàn)階段市面上供應(yīng)商的零部件,實(shí)現(xiàn)整車(chē)功能(典型代表 比亞迪 F3)
2.0 架構(gòu): 以正向開(kāi)發(fā)為主,融合國(guó)內(nèi)外先進(jìn)經(jīng)驗(yàn)技術(shù),進(jìn)行整車(chē)多車(chē)型的架構(gòu)開(kāi)發(fā)(典型代表 吉利 CMA 架構(gòu))
3.0 架構(gòu):硬件上從分布式 ECU 變?yōu)檎?chē)域控架構(gòu),軟件上由基于 signal 變?yōu)?SOA ,能夠大幅降低車(chē)輛上 ECU 數(shù)量,軟件迭代速度也由質(zhì)的飛躍(典型代表 特斯拉)
2.1. 服務(wù)設(shè)計(jì)依據(jù)
總體采用自上而下與自下而上想結(jié)合的形式進(jìn)行服務(wù)定義。
針對(duì)網(wǎng)絡(luò)上全拓補(bǔ)硬件,進(jìn)行自下而上設(shè)計(jì),將其分為傳感器,執(zhí)行器,與單功能 ECU 三類(lèi),分別針對(duì)硬件進(jìn)行設(shè)備抽象 api 設(shè)定,與原子服務(wù)抽象。
針對(duì)整車(chē)功能定義 FR 與 FDR ,進(jìn)行自上而下設(shè)計(jì),首先使用面向?qū)ο蟮乃季S進(jìn)行整車(chē)的類(lèi)抽象,然后設(shè)計(jì)類(lèi)的方法與屬性,其中屬性盡量與 原子服務(wù)進(jìn)行映射,方法需要使用一個(gè)或多個(gè)原子服務(wù)進(jìn)行實(shí)現(xiàn)
最終進(jìn)行原子服務(wù),與整車(chē)類(lèi)的屬性與方法進(jìn)行映射,找出無(wú)法實(shí)現(xiàn)的類(lèi),以及沒(méi)有使用到的原子服務(wù),此部分進(jìn)行服務(wù)代理設(shè)計(jì),及使用傳統(tǒng) SWC 軟件模塊實(shí)現(xiàn)部分功能,然后代理成組合服務(wù)形式,參與整車(chē)架構(gòu)設(shè)計(jì)。
?
2.2. SOA 設(shè)計(jì)區(qū)別
3.0 架構(gòu)全面采用 SOA(service-oriented Architecture)設(shè)計(jì)思想進(jìn)行構(gòu)建,上一代 2.0 架構(gòu)采用的是 POP(procedure oriented programming)面向過(guò)程的設(shè)計(jì)思想,需要注意的是,在 SOA 設(shè)計(jì)中,自上而下的設(shè)計(jì)方法中引入了 OOP(object oriented programming)面向?qū)ο蟮某橄笈c封裝概念,這是為了在 2.0 現(xiàn)有架構(gòu)基礎(chǔ)上,能夠繼承原有 FR,FDR,LC,然后進(jìn)行迭代開(kāi)發(fā)。
也就是說(shuō)通過(guò) Class 的抽象,在原有 LC 一層新添加了類(lèi)圖的設(shè)計(jì),通過(guò)抽象的類(lèi)進(jìn)行用例設(shè)計(jì)進(jìn)行功能鏈路實(shí)現(xiàn)。后續(xù)進(jìn)行服務(wù)化設(shè)計(jì),只要滿(mǎn)足類(lèi)中的屬性和方法能夠?qū)崿F(xiàn)即可,而不必去關(guān)心設(shè)計(jì)的服務(wù)如何支撐整個(gè)子系統(tǒng)及功能鏈路的實(shí)現(xiàn)。
POP 面向過(guò)程設(shè)計(jì)
在 2.0 架構(gòu)中,首先要進(jìn)行 Composition 功能組合的劃分,然后在進(jìn)行 Component 功能組件的劃分,每個(gè)組件都有相應(yīng)的輸入和輸出信號(hào),依據(jù)這些來(lái)實(shí)現(xiàn)高內(nèi)聚,低耦合的功能點(diǎn)實(shí)現(xiàn),設(shè)計(jì)好組件/組合之后,然后進(jìn)行模塊間接口信號(hào)的設(shè)計(jì),每個(gè)模塊平均有 20 個(gè)左后的輸入和輸出信號(hào)
SOA 面向服務(wù)設(shè)計(jì)
在 3.0 架構(gòu)中,首先要進(jìn)行服務(wù)的劃分和設(shè)計(jì),每個(gè)服務(wù)是松耦合的,也就是分治的設(shè)計(jì)理念,及服務(wù)里包含的方法、event、field 具備高扇入,合理的扇出,而服務(wù)所抽象的數(shù)據(jù)要與處理的業(yè)務(wù)邏輯、流程、功能實(shí)現(xiàn)三方解耦,所設(shè)計(jì)的基礎(chǔ)服務(wù)也要與操作系統(tǒng)解耦。
對(duì)比 2.0 中的設(shè)計(jì),可以類(lèi)似的理解為 2.0 先設(shè)計(jì)軟件模塊,然后設(shè)計(jì)信號(hào)接口,而 3.0 soa 后先設(shè)計(jì)服務(wù)接口(此接口不僅包含類(lèi)似信號(hào)的 event,還包含類(lèi)似函數(shù)的 method 方法),有了服務(wù)之后,在設(shè)計(jì)哪些模塊提供這些服務(wù),哪些模塊訂閱服務(wù)。
需要注意,SOA 后里的軟件模塊需要嚴(yán)格的區(qū)分 server 與 client,也就是一個(gè)模塊要不就是提供某個(gè)或多個(gè)服務(wù),要不就是訂閱了一個(gè)或多個(gè)服務(wù),不存在既訂閱了一些服務(wù)又提供了一些服務(wù)的情況,這與 2.0 架構(gòu)中的 swc 軟件模塊既有輸入又有輸出完全不一樣。
OOP 面向?qū)ο笤O(shè)計(jì)
在 3.0 架構(gòu)中,需要借助面向?qū)ο蟮脑O(shè)計(jì)方法來(lái)輔助支撐,也就是依托現(xiàn)有 2.0 架構(gòu),不進(jìn)行大范圍重構(gòu)的前提條件下,使用類(lèi)抽象出所有 LC 模塊,并且通過(guò)設(shè)計(jì)不同類(lèi)的用例圖來(lái)實(shí)現(xiàn)原 LC 處理的功能。
?
2.0 架構(gòu)上 MBSE 設(shè)計(jì)圖上 LC 映射實(shí)現(xiàn) ?
3.0 架構(gòu)上 MBSE 設(shè)計(jì)圖上 LC 映射實(shí)現(xiàn)
2.3. 接口命名規(guī)范
在進(jìn)行 SOA 服務(wù)設(shè)計(jì)時(shí),需要遵循如下命名規(guī)范
2.3.1. 基礎(chǔ)規(guī)范
盡量采用單詞全稱(chēng),名稱(chēng)過(guò)長(zhǎng)后才使用縮寫(xiě)
名稱(chēng)不包含特殊字符?,./~
名稱(chēng)如果過(guò)長(zhǎng),需要參考常用單詞縮寫(xiě)表中內(nèi)容進(jìn)行縮寫(xiě)
考慮服務(wù)和參數(shù)的復(fù)用性,各類(lèi)命名中不應(yīng)帶有拓補(bǔ)節(jié)點(diǎn)信息
不同層級(jí)的各類(lèi)名稱(chēng)不能重復(fù)
命名中不能使用如下系統(tǒng)關(guān)鍵字:
skeleton
proxy
internal
resources
method
event
field
input/output
amsr
ara
com
someip
base
vac
std
serialization
2.3.2. Service Instance 服務(wù)實(shí)例
服務(wù)實(shí)例及指代定義的服務(wù)實(shí)現(xiàn),后文若單獨(dú)寫(xiě)服務(wù),則意為服務(wù)實(shí)例
服務(wù)名采用首字母大寫(xiě),全英文名稱(chēng)
服務(wù)名不能有下劃線(xiàn)
服務(wù)名后綴需要以?Srv?結(jié)尾
eg. LedControlSrv
2.3.3. Service Interface 服務(wù)接口
SOA 平臺(tái)上服務(wù)之間通信接口有 Event、Method 和 Field 三種形式, ServiceInterface 用于定義 Event/Method/Field 消息類(lèi)型和具體的命名空間,與具體的通信協(xié)議無(wú)關(guān)。
服務(wù)接口名采用首字母大寫(xiě),全英文名稱(chēng)
服務(wù)接口名不能有下劃線(xiàn)
服務(wù)接口名需要以?SrvIf?結(jié)尾
eg. LedControlSrvIf
2.3.4. Event
Event 接口表示實(shí)際傳輸?shù)臄?shù)據(jù),以數(shù)據(jù)為操作對(duì)象,只要能夠清晰的表達(dá)數(shù)據(jù)的含義即可,命名規(guī)范遵循基礎(chǔ)規(guī)范,后綴要以?Evt?結(jié)尾。 eg. CurrentVleEvt : 電流值 Event 消息傳遞方式如下圖所示,為服務(wù)端主動(dòng)向客戶(hù)端發(fā)送,并且會(huì)觸發(fā)客戶(hù)端的 callback 函數(shù)進(jìn)行數(shù)據(jù)處理。 ?
2.3.5. Method
Mehtod 接口表示某種控制,通訊方式采用 RPC 遠(yuǎn)程調(diào)用,通常有動(dòng)詞行為,比如控制,狀態(tài)查詢(xún),傳輸,注冊(cè),設(shè)置等。其中 Method 又分為 F&F,與 R&R 兩類(lèi),F(xiàn)F 為單次調(diào)用,不需要反饋,RR 為 request resoponse,需要反饋。
請(qǐng)求-響應(yīng)(request/response): R&R
請(qǐng)求-響應(yīng)流(request/stream)
發(fā)后不管(fire-and-forget) : F&F
通道模式(channel)
整體設(shè)計(jì)依據(jù)遵循?CURD/REST?這類(lèi)成熟的互聯(lián)網(wǎng)通用接口概念 CURD
REST
接口名稱(chēng)需要表達(dá)清楚該方法的含義,推薦使用動(dòng)名詞進(jìn)行命名,采用駝峰命名規(guī)范,基于如上 CURD/REST 參考,命名要以后綴?Mtd?作為結(jié)束,設(shè)計(jì)如下基礎(chǔ)命名范式:
get 獲取狀態(tài)
set 設(shè)置狀態(tài)
report 傳遞信息
judge 判斷事件,返回 boolean
create 創(chuàng)建線(xiàn)程/進(jìn)程/動(dòng)態(tài)服務(wù)/文件/事件 等
delete 刪除線(xiàn)程/進(jìn)程/文件 等
eg. setSoundOnMtd : 鳴響喇叭
judgeVehMovingMtd : 判斷車(chē)輛是否移動(dòng)
getCarCfgMtd : 獲取 car config 值
reportComponentStsMtd : 上報(bào) component 狀態(tài)信息
createXTaskUsrLightShowSrvMtd : 創(chuàng)建用戶(hù)自定義的燈光 show 服務(wù)
deleteDebugClass0MsgMtd : 刪除 debug 等級(jí)為 0 的所有 msg 調(diào)試文件 Method 消息傳遞方式如下圖所示,為客戶(hù)端主動(dòng)向服務(wù)端請(qǐng)求,可以設(shè)定是否有服務(wù)端的返回值。
2.3.6. Field
Field 表示一種屬性,通常指狀態(tài)值或某種信息,名稱(chēng)應(yīng)該清楚的表達(dá)該屬性的含義。 Field 包含如下三類(lèi)信息:
getter : 只讀接口,原型為 method,獲取服務(wù)端信息
notifier : 只讀接口,原型為 event,接收服務(wù)端的數(shù)據(jù)
setter : 寫(xiě)入接口,原型為 method,設(shè)置/修改服務(wù)端相關(guān)信息
eg. VehMoveFld : 車(chē)輛移動(dòng)控制 Field 消息傳遞方式如下圖所示
3. 服務(wù)設(shè)計(jì)方法
針對(duì)大部分 OEM,需要在現(xiàn)有整車(chē)架構(gòu)上進(jìn)行服務(wù)設(shè)計(jì)升級(jí),也就是已有 base 的 LC 需求,和工程級(jí)的軟件 swc,需要依據(jù)這兩類(lèi)已有資產(chǎn),使用 OOP 面向?qū)ο蟮某橄笈c封裝手段,進(jìn)行 SOA 服務(wù)化重構(gòu)。 本章節(jié)以車(chē)身控制器中?危險(xiǎn)報(bào)警?軟件模塊為例,說(shuō)明如何在已有 LC 需求和軟件模塊前提下,使用 gitee,進(jìn)行 SOA 設(shè)計(jì)。
需要注意的是,在設(shè)計(jì)服務(wù)接口時(shí),要清楚的知道不同接口的實(shí)際特性和性能消耗。Event 為 服務(wù)端主動(dòng)向客戶(hù)端 發(fā)送請(qǐng)求,而 Method 恰好相反,為 客戶(hù)端主動(dòng)向服務(wù)端 進(jìn)行請(qǐng)求調(diào)用。根據(jù)如上接口描述,整體服務(wù)設(shè)計(jì)遵循如下方案要點(diǎn)。
原 2.0 平臺(tái)中信號(hào)盡量保留,作為 Event 接口類(lèi)型進(jìn)行預(yù)留
服務(wù)設(shè)計(jì)包括 類(lèi)抽象-服務(wù)接口設(shè)計(jì)-服務(wù)實(shí)例設(shè)計(jì)-設(shè)計(jì)具體的進(jìn)程/線(xiàn)程 運(yùn)行此服務(wù)實(shí)例
每個(gè)抽象好的類(lèi),對(duì)應(yīng)一個(gè)服務(wù)接口 : XX_Class -> XX_SrvIf
類(lèi)中的屬性對(duì)應(yīng) Event 接口類(lèi)型 XX_Class::value -> XX_SrvIf-valueEvt
類(lèi)中的方法對(duì)應(yīng) Method 接口類(lèi)型 XX_Class::fuction -> XX_SrvIf-valueMtd
盡量不要設(shè)計(jì) Field 接口
每個(gè)服務(wù)接口由一個(gè)具體的服務(wù)進(jìn)行實(shí)例化 : XX_SrvIf -> XX_Srv
每個(gè)實(shí)例化的服務(wù),都要設(shè)計(jì)哪個(gè)進(jìn)程/線(xiàn)程/軟件模塊/ECU 來(lái)提供,哪些 App 會(huì)訂閱
App 使用/設(shè)定服務(wù)里的數(shù)據(jù)/功能,需要通過(guò) CM 通訊管理進(jìn)行服務(wù)的訂閱
實(shí)例化的服務(wù)之間,數(shù)據(jù)/功能 傳遞,則直接調(diào)用相互暴露的 api,可以不用 CM 參與(即組合服務(wù)和原子服務(wù)的關(guān)系)
App 之間不能直接進(jìn)行數(shù)據(jù)傳輸,需要調(diào)用專(zhuān)有的服務(wù)進(jìn)行數(shù)據(jù)傳遞(即服務(wù)代理模塊)
3.1. 需求分析
示例軟件模塊主要實(shí)現(xiàn)危險(xiǎn)警報(bào)功能,在整車(chē)條件允許的情況下,如果按下手機(jī) app 上的警報(bào)按鈕,則會(huì)觸發(fā)車(chē)輛進(jìn)行聲光報(bào)警。
需要注意?針對(duì) VFC/PNC 相關(guān)軟件邏輯,雖然在 3.0 架構(gòu)上已經(jīng)不復(fù)存在,但是需要保留功能分區(qū)劃域的思想,也就是針對(duì)不同場(chǎng)景需要觸發(fā)不同的軟件組件來(lái)執(zhí)行完成,針對(duì)不同的 PNC,在 3.0 架構(gòu)上可以作為 VLAN 劃分的設(shè)計(jì)參考。 使用 gitee 進(jìn)行需求編寫(xiě),與原 LC 中需求進(jìn)行追溯
3.2. 類(lèi)的抽象和封裝
使用 OOP 手段,根據(jù)需求和已有的軟件模塊,進(jìn)行類(lèi)的抽象,并將有可能被多次調(diào)用的軟件邏輯進(jìn)行類(lèi)方法的封裝,后續(xù)多次執(zhí)行的代碼邏輯,僅在實(shí)例化的類(lèi)中執(zhí)行一次即可。
類(lèi)抽象,將整車(chē)從多個(gè)角度抽象成不同的類(lèi),每個(gè)類(lèi)都可以映射成一個(gè) service 的實(shí)體,不同的軟件模塊調(diào)用相同邏輯時(shí),可以直接訂閱此 service,使用 service 中的 method、event、field。
類(lèi)方法封裝,將接口進(jìn)行泛化,封裝成通用類(lèi)的方法,達(dá)到松耦合的效果
類(lèi)圖:
? ?
時(shí)序圖:
?
3.3. 服務(wù)設(shè)計(jì)
上一章推導(dǎo)出,所設(shè)計(jì)的類(lèi)就是一個(gè)需要實(shí)現(xiàn)服務(wù),根據(jù)此原則,在 gitee 中進(jìn)行服務(wù)設(shè)計(jì)。 服務(wù)設(shè)計(jì)包含如下步驟和要素:
服務(wù)接口設(shè)計(jì)(method/event/field)
接口變量設(shè)計(jì)(method 的入?yún)⒊鰠⒓皵?shù)據(jù)類(lèi)型,event 變量名及數(shù)據(jù)類(lèi)型)
服務(wù)實(shí)例設(shè)計(jì)(發(fā)布者,服務(wù) ID 等信息)
3.3.1. 數(shù)據(jù)類(lèi)型設(shè)計(jì)
在?Gitee-數(shù)據(jù)類(lèi)型?中進(jìn)行數(shù)據(jù)類(lèi)型設(shè)計(jì) ?
3.3.2. 服務(wù)接口設(shè)計(jì)
在?Gitee-Service 接口?中進(jìn)行 service 接口設(shè)計(jì) ?
3.3.3. 服務(wù)實(shí)例設(shè)計(jì)
在?Gitee-Service 實(shí)例?中進(jìn)行服務(wù)實(shí)例設(shè)計(jì) ?
3.3.4. 配置文件導(dǎo)出以及代碼框架生成
通過(guò) gitee 能夠?qū)С鏊蟹?wù) list 的 csv 文件,基于此開(kāi)發(fā)工具進(jìn)行 arxml 文件和代碼框架的轉(zhuǎn)換生成,最終進(jìn)行基于 SOA 服務(wù)化的軟件開(kāi)發(fā)。 代碼框架可以參考筆者之前的回答。
4. 小結(jié)
針對(duì)已有歷史軟件資產(chǎn)的廠商,進(jìn)行 SOA 架構(gòu)升級(jí)的方法大致如上,此處借用了 gitee 企業(yè)版輔助進(jìn)行架構(gòu)設(shè)計(jì),也希望大家意識(shí)到,軟件定義汽車(chē),不僅僅是軟件產(chǎn)品,甚至整車(chē)研發(fā)的工具鏈和開(kāi)發(fā)流程也都會(huì)慢慢靠向軟件開(kāi)發(fā)的生態(tài)工具鏈,抱殘守缺,是注定要被時(shí)代淘汰的,此處諾基亞和柯達(dá)會(huì)深有感觸。?
審核編輯:劉清
評(píng)論