编辑推荐: |
文章主要介绍了软件定义汽车,E/E架构是关键、SOA——解决软件定义汽车中服务间通信的分布式架构等相关内容。
本文来自于微信拖拉机日记,由火龙果软件Anna编辑、推荐。 |
|
从去年开始(可能更早),SOA的概念在汽车软件行业逐渐蔓延开来,很多公众号都发过讲汽车SOA的文章,很多车厂都要开始(或者已经在)搞SOA。但我觉得吧,在开搞新技术之前,是不是先花点时间弄明白这个技术到底是什么,它解决的是什么样的问题,然后再谈架构,再谈开发,很多时候我们连问题是什么都没整明白,就急着去做解决方案,最后的结果只能是一地鸡毛。对个人来说,要搞SOA开发,需要夯实哪些基础知识,看了很多SOA文章,却很少有人梳理这些,这段时间我陆续思考了一些,尽管可能不全面(更偏向SOC开发涉及的技术点),但仍然试图写出来,以期逐步构建出自己的领域知识体系(详见下篇)~
那么,先来理一理关于SOA:
软件定义汽车,E/E架构是关键
汽车电子电气架构(简称E/E架构)是指整车电子电气系统的总布置方案。在智能网联汽车产业大变革背景下,软件定义汽车理念已成为共识。传统汽车采用的分布式E/E架构因计算能力不足、通讯带宽不足、不便于软件升级等瓶颈,已经不能满足现阶段汽车发展的需求,E/E架构的变革已成为智能网联汽车发展的关键,其升级主要体现在硬件架构、软件架构、通信架构三个方面:
硬件架构升级:由分布式ECU向域控制/中央集中架构方向发展,汽车E/E架构的升级路径表现为分布式(模块化→集成化)、域集中(域控制集中→跨域融合)、中央集中式(车载电脑→车-云计算)。好处在于:提升算力利用率,减少算力设计总需求;数据统一交互,实现整车功能协同;缩短线束,降低故障率,减轻质量。
软件架构升级:通过 AutoSAR 等软件架构提供标准的接口定义,模块化设计,促使软硬件解耦分层,实现软硬件设计分离;Classic
AutoSAR架构逐步向Classic AutoSAR+Adaptive AutoSAR混合式架构发展。好处在于:可实现软件/固件
OTA 升级、软件架构的软实时、操作系统可移植;采集数据信息多功能应用,有效减少硬件需求量,真正实现软件定义汽车。
通信架构升级:车载网络骨干由 LIN/CAN 总线向以太网方向发展。好处在于:满足高速传输、高通量、低延迟等性能需求,同时也可减少安装、测试成本。
中央计算单元——E/E架构的核心
中央计算单元是E/E架构中最关键的部分,不管是按区域的架构,还是以后的纯中央计算平台,其硬件构型从根本上决定了软件架构的设计方向。中央计算单元可以分为以下三种形态:
SOC分离式:将多个不同的芯片集成到一个中央计算单元上去,每个运行不同的操作系统,只是在形态上集中到了一起,各单元依然独立的完成各自任务;
硬件隔离式:在统一的计算平台上采用虚拟化方案,同时运行多个操作系统,但是各个系统依然在硬件上进行隔离,每个系统都有自己的专属硬件资源;
软件虚拟式:在统一的计算平台上采用虚拟化方案,同时运行多个操作系统,每个操作系统所使用的硬件资源,由Hypervisor层动态调配,每个系统并没有专属的硬件资源。
硬件隔离式和软件虚拟式,都采用了虚拟化方案,唯一不同点在于硬件资源是否专属,如果是专属的,就意味着资源无法动态调配,容易产生资源浪费。虚拟化方案最大的好处是,硬件上的可拓展性,如果中央计算单元采用刀片式的设计结构,可以很方便地拓展计算单元的算力,而不用替换整个计算单元。
在中央计算单元中,只需要两个操作系统即可,用于自动驾驶、车控、网关的RTOS,以及用于娱乐的普通OS(如Android、Linux)。用于娱乐的OS完全可以通过虚拟机的方式运行,用于自动驾驶、车控、网关的RTOS,可以直接运行在Hypervisor层,既能兼顾实时计算的要求,也能获得丰富的娱乐系统功能。
SOA——解决软件定义汽车中服务间通信的分布式架构
在软件定义汽车中,应用间跨进程或跨核的通信,必然成为软件架构设计中一个需要去解决的问题。SOA在互联网已经应用了很长时间,但在汽车行业中,算是比较新的概念。鉴于汽车的应用场景和通信需求有其特殊性,很多互联网的SOA技术,并不能照搬过来。虽然Adaptive
AutoSAR采用了SOA作为通信架构(ARA::COM架构如下图),但是Adaptive AutoSAR的应用可以说还没有普及,应该说整个行业就没什么标准的SOA中间件解决方案,几乎没有专业做中间件研发的公司,可能在国内这种慢工出细活的东西很难有什么成长的空间和土壤吧。所以,对于汽车SOA,还有很多值得我们去做的研究和尝试~
摘自《Introduction of
ARA:: COM as common communication middleware》April,
2018 by GENIVI
SOA,Service-Oriented Architecture(面向服务的架构),是一种架构思想,实施者可以根据实际情况设计SOA的技术实现。为什么要面向服务?以前用得好好的面向信号或者面向消息的通信架构怎么就不香了?面向服务的通信架构,它的优势到底在哪里,如果不能很好地理解这点,可能很难从过去面向信号的思维转变过来,也就无法体会引入SOA的价值和意义。这有点悖论哈,不去用,无法感受其奥义,但又因为没用过,对它保有质疑,过往的再拧巴,也是千锤百炼了,从零开始,谈何容易。因此,我觉得短时间内不太可能全面铺开做整车SOA,可能会在安全等级不高的域比如智能座舱先尝试SOA。
本质上SOA就是服务的集合。在SOME/IP 协议介绍一文中,我写过对于“服务”的理解。以智能座舱域为例(如下图),可以把“服务”分为两类:基础服务和应用服务,基础服务的功能可能包括:总线消息的解析和路由(如车身数据服务)、直接与硬件相关的逻辑处理(如音频服务)、上层应用有共同需求的一些基础设施(如日志服务);应用服务的功能相对复杂些,可能需要由多个基础服务提供数据支撑,也可能需要应用服务之间相互协同,实现业务逻辑(如导航服务)。
SOA分层架构视图(仅作举例)
这只是一个很简单的例子,想表达的是,每个服务将自己的功能,以接口的方式提供,基于这些服务和接口,便可以设计出应用场景,以满足各种用户需求,提升驾车体验。可以想象,应用场景的需求一定是丰富且变化的,面向信号的话,新增一个需求,可能要等上一年,但如果服务也能够方便地进行开发、扩展和更新,是不是好多了,是不是挺有价值呢~
个人觉得,汽车SOA的设计难点,主要在于以下几点:
服务的定义和划分,要把业务需求分析透彻,从中提炼出服务的功能,数据流向理清,定义服务的边界,把握服务的粒度,怎么做到“低耦合,高内聚”,我以前很讨厌研究需求,觉得那些不过就是些业务,没啥技术含量,后来才慢慢认识到,这种想法很危险啊,脱离需求的软件设计不可能很好地满足需求,如果不能很好地服务于产品功能,那么再牛逼的技术都没有机会实现它应有的价值,事实上,能够把需求文档转化为可实施的软件设计,也是一种能力;
不同系统中,要实现中间件框架或者底层通信基础设施,Adaptive AutoSAR有ARA::COM组件,Android有Framework,但不能跨域,QNX/Linux就不用说了。要实现一个中间件框架,本身并不是件容易的事,需要比较强的技术实力,一旦出了问题一般都是重大问题;
服务接口标准化,接口描述语言化(IDL),能够通过工具自动生成RPC桩的代码(最好能够关联整车通信矩阵,e.g.
ARXML->C++ API),能够跨平台,支持多语言,毕竟UI层可能不是C++写的,时至今日,没几个应用愿意去解析原始消息,远程调用接口不香嘛~;
如何兼容一些没有与时俱进的设备和模块,如何兼容旧的传输通道,如何尽可能复用以前的业务逻辑,理论上任何兼容都是可以实现的,抽象一层不够,那就再来一层,但兼容得越多,系统就越复杂,出问题的概率就越大,维护起来就越费劲,这意味着成本的升高,质量却不见得变好;
评估性能影响,怎么保证安全性,……,如果是基于开源项目,可能还要做二次开发,来满足这些非功能性质的需求~;
所以,汽车SOA真不是SOME/IP,也不是DDS,更不是Adaptive AutoSAR,这些都是汽车SOA技术栈中的一环,并不是全部。
很多时候,纯技术的部分并不是最难的,新的架构方案要达成共识,要真正落地,需要博弈和取舍,需要天时地利人和。作为一名工程师,心态是极为重要的,要分清理想与现实,技术与工作,所以在这里我只想谈技术,本来打算梳理一下做汽车SOA开发的基础知识体系,以后公众号的内容大致也会围绕着这个体系去写,没想到写着写着这么长了,于是分成上下篇了,下面先开个头吧。
SOA是架构,做SOA的设计和开发,其实也是做架构的设计和开发,在这里我想引用陈皓老师为《架构整洁之道》作的推荐序里的一段话,我常想起这段话,挺有鞭策的功效,分享给每个不想成为PPT架构师的工程师,以共勉:
问题:如果你要成为一名架构师,你需要明确地区分几组词语,否则你不可能成为一名合格的工程师或架构师。这几组词语是简单vs.简陋、平衡vs.妥协、迭代vs.半成品。如果你不能很清楚地定义出其中的区别,那么你将很难做出正确的决定,也就不可能成为一名优秀的工程师或架构师。
之前很长一段时间,我经常感到焦虑,一方面不想成为PPT党,开会党,另一方面,除了工作还要生(带)活(娃),留给学习的时间并不多,而想学的知识又如同汪洋大海,今天想好好梳理一下某个技术点,明天搜到某个开源项目蛮感兴趣想写个Demo跑跑看,年轻的时候觉得日子一天天刷刷地过去,也不是什么事儿,现在愈发有种紧迫感。在做了一些架构方面的设计和开发工作以后,更是深刻体会到构建个人的领域知识体系,尤其是一些基础技术,真的非常重要。
今年伊始,关于“如何打好基础”的讲座,核心观点是:“基础≠底层,基础≠源码,基础≠不变”,很是醍醐灌顶~结合个人实际情况,我觉得可以这么去构建我的领域知识体系:首先,定义出哪些是与我工作相关的领域知识(比如现阶段是SOA);其次,进一步细化要学习的知识范围,也就是下篇要梳理的SOA相关知识;最后,分别从广度和深度(根据工作内容去判别学习的深度),有针对性地学习,并在实际工作和项目中把知识和技术串起来,从而系统性地提升技术能力。
就像前面说的,要分清理想与现实,因为这个世界从来都不是我所能想象的,很多PPT党开会党,基础不扎实甚至很水,设计出焦油坑一样的架构,坑自己,坑别人,坑项目,也不耽误他们升职加薪跳槽。但是“世界上只有一种英雄主义,那就是认清生活的真相后依然热爱它”,不是么,于是才有了写公众号的初心和决心。
接下来要做的梳理,没有思维导图,没有PDF,没有表格,是结合了我的实际经历和体会,总结得出的一些基础知识点,这是现阶段的这个我所了解的所认为的,随着时间的流逝,我又会经历更多一些,现在梳理的可能也会跟着改变一些。这种极其个性化的梳理,对我,是梳理(其实,写这篇比想象中艰辛,要不是前面给自己埋下了坑,都想放弃了~),对你,看看便好,就当是听我絮叨絮叨,侃侃大山,轻松愉快,真心不能提供什么参考。以下梳理分为四个维度:编程,架构,网络,工具。
编程:多看,多写,多折腾
目前,智能座舱的生态圈主要包括Android、Linux、QNX等操作系统,因此,我认为做SOA开发,至少需要熟练掌握C++和Java两种编程语言。C++是必须要会的,Linux/QNX主要用C++开发,Android其实也涉及C++开发,尤其是对性能要求较高的模块,通常会下沉到Native或HAL实现。Java也是必须要会的:第一,Android的App和Framework是用Java开发的,需要设计和开发SOA接口,提供给位于这两层的应用和服务使用;第二,设计SOA架构,要对系统各层级之间的接口如何设计和调用有足够的了解,代码都看不明白,怎么设计易用的接口;第三,写Demo是架构设计过程中重要的步骤,总不能你设计的方案等着别人写Demo验证吧,更重要的是,通过写Demo可以发现很多想法上的不足,设计文档写得不严谨的地方。
对于C++编程,要掌握的一些基础知识:
语法基础:构造,继承,虚函数,内联,多态,类型转换,STL容器,…;
C++11新特性:时至今日,应该学会使用至少C++11常用的特性,比如:类型推导(auto,decltype),右值引用,智能指针,泛型/模板,type_taits,函数式编程(lambda),C++11多线程,future,promise,…,用它们使代码更简洁,改进代码质量,提升程序性能,不是为了炫技,而是用到实处;
应用开发:Linux/QNX网络编程、多线程编程、进程间通信等编程手法,常用实现如无锁,消息队列、线程池等,常见开源库的使用,选择感兴趣的如Libevent、Muduo等,深入学习其设计和实现;
项目开发:代码结构,接口封装方式,常用几种设计模式的实现(如单例模式、观察者模式等);
对于Java编程,要掌握的一些基础知识:
语法基础:包,类,接口,反射,泛型,异常,集合,注解,常用类,…;
并发编程:原子操作,Exexutor,线程池,阻塞队列,synchronized,锁,volatile,CompletableFuture,…,常见模型如Thread-Per-Message,CopyOnWrite,生产者-消费者,…;
应用开发:Java中的网络编程(JDK API),Android应用开发基础(四大组件,不研究UI,只要能整出个正常点儿的DemoApp就行~),Android进程间通信机制,AIDL、JNI和HIDL接口的设计和开发;
项目开发:常用代码结构,常用几种设计模式的实现(如工厂模式、代理模式、门面模式、观察者模式、策略模式等),注意,这里和前面C++说的都是实现,期望达到的水平:做到真正的理解,谈到某种设计模式,脑子里能够想到其适用的应用场景是什么,落实到代码上,一个大致思路是怎样的,反之亦然;在阅读一些开源项目时,能够看出用了什么设计模式,这样用的好处什么,不用可能会产生什么问题。
架构:保持好奇心,平常心
架构和编程的不同之处在于,编程是容易看见结果和成效的,你写的代码有没有Bug很快能被证明,你写的模块扩展性和稳定性怎么样,经过一些时日,也能看出个一二。架构不是,有多少人能在短时间内落地几种架构方案的,更不用说评价架构设计得好不好了,就拿通信框架来说,很少听应用说满意当前的通信框架的,为什么扩展个接口这么麻烦,为什么不支持同步调用,为什么没有消息缓存,…,能被吐槽的点太多了。即使如此,我们还是要致力于做出好的架构,也许无法得到所有人的满意,但设计和开发出好的SOA架构,可以让系统中每一个应用和模块在交互通信与数据共享的问题上获得不错收益,反之,糟糕的SOA架构可能就是所有人必须面对的一场灾难。
在架构设计这件事上,我也是刚开始有一点点经历,以下所想完全没有参考价值。
设备:跳出单个模块的视野范围,尝试去了解这个通信系统里的每一个设备(可以是车机,仪表,T-Box,网关等等),他们的软件系统,他们的硬件,硬件之间的连接,他们的功能业务,他们的开发模式,他们的数据需求,他们以往采用过的通信方案,…;
车载以太网:了解相关知识,如:CAN,LIN,诊断,标定,CP,AP,…,重点关注整车以太网与智能座舱的对接,或者说智能座舱未来如何接入中央计算单元。至于最近很火的AP,没有计划作深入研究,从编程角度来说,基础是相通的,CP用的C,AP用的C++,很多东西并不是本身难度有多大,而是学习的资源和工具难以获得,人为形成了所谓的技术壁垒,个人开发者想要学习研究,几乎不可能搭建环境。我觉得开源是时代的进步,一定会是大势所趋,1202了,我们都要拥抱开源呀~;
系统:Linux/QNX系统调用(如输入/输出,存储,文件,网络,线程,进程间),Android系统架构,座舱的整体架构,模块的架构,比如,车机中Android原生模块(如BT,WiFi,Audio,Location,…)的数据源有什么不同,车机中这些基础模块都是怎么适配的,车机中较复杂的APP如导航、语音等的架构是什么样的。不要觉得别人负责的模块我了解了干嘛,说白了,SOA就是模块与模块之间的交互,对每个模块了解一下一定是有益的;
中间件:基于几种通信模型(可参考DDS 介绍)的中间件框架,RPC技术的原理和实现,各种开源RPC框架:grpc,brpc,srpc,…,各种中间件架构方案:GENIVI,ROS2,…,如何技术选型,如何验证可行性,如何做性能评估;
设计原则:SOLID,KISS,迪米特,…,结合具体业务的前提下追求原则,知易行难,没有定式,如何做出正确的决策,需要在实践中不断思考和总结;
沟通表达:面向不同受众的架构视图,SOA是需要传播的,“咱们用TCP通信”和“咱们用SOMEIP通信”,对于不熟悉SOMEIP的小伙伴来说,是两码事。正确地传达架构的设计,高效地沟通和解决过程中的冲突,清晰地表述技术实现的细节,画的UML要能指导开发,尽可能说经过验证的结论,即便是预估的,也要有一些数据作为依据,不要说出诸如“应该没问题”这样的结论;
项目+产品:做架构设计,可以是一个人的事,但架构的落地,是需要一群人一起完成的,能否保质保量完成不是项目经理该去操心的事吗?我觉得并不是,能否落地也是架构设计中可以考虑的一个视角,适当了解一些项目管理和产品思维的知识,会使你能更好地理解这个世界,理解一个项目的运作,理解一个产品从无到有所要经历的过程,理解架构不止是一个技术问题,这些都会帮助你设计一个好的架构。
网络:实践出真知,重视细节
如果说架构是宏观,那么网络通信的设计和开发,是件要扣细节的事儿。不要想当然,不要把网络状况想得过于理想,不要把服务端想得过于强大,不要对任何错误掉以轻心,试图找到每个错误背后的根源,解决的过程就是一次收获。
网络基础:OSI,TCP/IP,五层协议,各层作用和常见协议;
开发基础:TCP和UDP建立连接的流程,阻塞与非阻塞Socket API,同步与异步,IO多路复用,epoll的水平触发与边缘触发;
通信协议:SOME/IP,DDS,HTTP/RESTful,SSL/TLS,MQTT,对于SOME/IP和DDS,准备死磕:协议标准,开源项目的应用,源码剖析,二次开发,封装接口;多媒体传输:AVB,RTP/RTCP/RTSP/RTMP;
序列化:JSON,Protobuf,Franca IDL,MsgPack,…,各自优缺点、性能效率、适用场景、开源库选型;
细节:私有通信协议如何设计,如何解决粘包和分片;心跳机制如何设计;收发缓冲区如何设计;如何优雅地关闭连接;断线重连机制如何设计;流量控制如何设计;…;
实践:分析当前网络连接状态;定位通信链路中出错位置,分析其出错原因;抓包,分析数据包;如何设计Benchmark,测试和分析通信架构的各项指标如传输时延、CPU占用、内存消耗、负载压力等;
工具:发现,尝试,积累
写工具,会让人觉得很Low吧,实际上,很多人低估了学会使用工具的重要性。为什么别人花一小时搭建实验环境,而你要一天?为什么别人花半小时定位问题改好代码,而你要一周?为什么别人花半天完成了某个第三方库的平台移植,而你要花几天,甚至搞不定?…?其实不是别人有多厉害,而是你不善于运用各种工具去解决问题,也没有注重积累,举个栗子:一次重装Ubuntu系统时遇到某个问题,查了好几篇CSDN文章,总算给搞定了,可什么都没记下,下次再重装时,又遇到同样的问题,这个问题我好像碰到过!然后,就没有然后了,如果那篇之前帮到你的文章还找不到了,…,总在这样又那样的事情上,浪费了太多的精力和时间,这些时间原本可以用来做更多有价值的事情啊~
开发:VSCode,IDEA,Android Studio;
构建:Shell,CMake,Gradle,Maven;
调试(测试):GDB,UT框架,静态代码检测,内存泄漏检测,tcpdump,Wireshark,MQTT
X,JMeter,Docker;
文档:Markdown,PPT,Excel,笔记,Visio,EA,draw.io,录屏,…,;
自动化:一直觉得SOA开发工具是值得研究的,比如API文档自动生成工具、API代码自动生成工具、回环测试工具等(在互联网领域已经有一些类似的工具,看过几个开源的,比如ShowDoc,感觉都不太能用到汽车领域,有好用的欢迎推荐啊~);
终于,写完了,好多没有写进来,比如算法与数据结构、JVM、Linux内核、数据库等,当然不是说它们不重要。但对现阶段的我来说,上面列的这些已经很够我学的了,能把这些搞透彻,我已经非常非常满足了。术业有专攻,先把能做好的事做到最好,不是每个人都能成为技术大牛,也不是每个人的目标都是要成为技术大牛吧,人生的路长着呢,以后的事以后再想好了。有句话不是很扎心么,“以大部分人的努力程度,根本还轮不上拼天赋”,有时候只是态度就足够拉开差距了。
|