All Posts

“互联网造车”的误会:不是让软件工程师去做底盘

前些天有个朋友问我,为什么你们搞互联网的工程师,最近几年,都开始往汽车行业里挤了呢? 虽说之前网上也有过各种说互联网造车不靠谱的文章了,但当这个问题被真实地问到自己的时候我还是蛮惊讶的,当时脑海里第一时间的反应是,一场误会,一场误会。 Tesla是最早被贴上“互联网造车”标签的公司,而国内互联网造车的不靠谱新闻,最早或可追溯至2015年,某汽车startup一场发布会之后,被网友在知乎爆出其demo车是拿Tesla改装的PPT造车事件。此后,互联网背景的老板进入汽车行业便被贴上了“互联网造车”的标签。或许这个标签对于资本市场有着不同的含义,但其实在一个比赛里各个选手无论被外界贴着什么标签,最终的成绩仅与自己和对手的发挥有关。本文尝试从一个技术人员的角度来聊聊开头这个问题。 互联网造车不是让软件工程师去做底盘 专业的事情交给专业的人做,这是一个企业能够壮大发展的一个用人基本原则。汽车行业百年的发展历史,在汽车底盘,动力总成等各个地方已经累计非常丰富的行业经验和人才。被贴着“互联网造车”标签的公司,老板们可都不是傻子呀,自然也不会在这些地方重新发明轮子。一方面,整车架构的团队,往往会聘用拥有多年相关领域从事经验的专家和工程师;另一方面,“互联网造车”公司也会选择与各个零部件供应商合作,共创的方式快速整合行业的优质资源。所以请放心,你花三四十万买到的互联网造车上装的是博世iBooster的制动系统,不是码农纯手工打造的。 整车EE架构的进化产生了大量的软件需求 近几年,汽车EE架构从分散的众多单一功能的ECU,架构逐步集中化,分域控制,跨域融合,最终趋向形成一个或几个中央电脑控制全车IO(传感器和执行器)的架构(参考: 特斯拉智能化路上的左脑与右脑 )。 单一功能的ECU,通常只会包含相对简单的逻辑执行,计算能力和可编程的能力有限。功能ECU各自分离,无法实现多功能协同的智能化,这个阶段的软件人才需求量相对小。而随着域控制器和中央电脑的出现,整车架构算力集中化,传感器数据和执行器被集中连接到若干个电脑,使得大量过去由于单ECU功能限制无法实现的智能化功能得以实现。 举个栗子,当我打开全车窗的时候,可能不再需要空调冷气了,过去空调和车窗各自独立,人们往往需要自行关闭空调,而当有连接着空调和车窗控制器的中央智能模块后,这样一个“打开车窗自动关闭空调”的功能就可以通过编写软件来实现了。这是个简单的协同智能化的例子,而自动驾驶相关的功能可视为更高级的协同智能化。 车上有了电脑之后,谁来在电脑上写软件实现智能化呢?最擅长于做这块事情的无疑是各大院校计算机专业毕业的人才呀,而他们目前就散布在各大互联网高科技企业里。 智能汽车的产业链需要优秀的软件人才 在智能汽车的产业链里,整车厂和零部件供应商的发展是一个相互促进共同创新的过程。整车功能和架构的创新对零部件供应商提出了新的需求,零部件供应商的创新为整车厂带来了新的解决方案。当零部件供应商没跟上整车厂的步伐时,整车厂往往会选择自研。当同一个创新需求有多家整车厂都需要时,满足这样共同需求的创新公司会出现。近几年萌生的自动驾驶和智能网联的startup正是这样的科技公司,区别于传统的零部件供应商,它们也是计算机高科技人才集聚的地方。 曾经有一个同事问我,互联网人进入了汽车行业工作后,是不是将来就业面窄了很多?原本有很多互联网公司可以选择,现在是不是只能在少数几家造车新势力里做选择? 其实不然。一方面,智能汽车行业的发展,对跨界人才的需求只会越来越大,过去我们想去招一个既懂互联网又懂汽车电子的人,只能在美国设研发中心招特斯拉的工程师。而现在,国内蔚来,小鹏等造车新势力经过四五年的实战经验,培养了不少这样的综合型人才。另一方面,计算机原理是相通的(大学课上教的计算机知识可没说只能局限于某个领域),熟悉服务端分布式系统开发的同学,进入车载环境后,会发现车里其实也是一个分布式系统。进入智能汽车行业只是让你的计算机技能应用面更广了,并非换了一个技能。 自主研发不等于什么都自己干 最后,伴随着互联网造车的误会的往往还有自主研发。人们在探讨概念的时候习惯性的会忽略掉一些定语和前置条件。自主研发于整车厂在于研发有竞争力的整车平台架构,以支持更多有竞争力的车型推出。比如通用近期发布的下一代电子架构平台,凯迪拉克CT5将率先搭载。而整车平台上使用的各个零部件是否都需要自研?其实不然,如果市场上有合适的解决方案,车厂往往会选择共赢的合作开发,毕竟这是一个商业社会。 End 新建"

从Google Fuchsia理解“天然无root”

"a dream job is not about dreaming, it's all job all work all reality all blood all sweat no tears. i work a lot and i love it.

特斯拉智能化路上的左脑+右脑

“种一棵树,最好的时间是十年前,其次是现在。” 特斯拉于去年3月份发布了基于Intel Atom(Apollo Lake)芯片的新版本多媒体控制器MCU2(MCU, Media Controller Unit),今年4月份 发布了其自研SOC (System On Chip) 的Autopilot硬件HW3(FSD,Full Self Driving)以支持将来实现全自动驾驶所需要的算力。多媒体控制器MCU与Autopilot ECU共同构成了特斯拉的大脑,最新版本的两个硬件开始在今年4月份下旬生产的Model 3和5月下旬生产的Model S/X中使用。 在Model 3中,特斯拉将MCU与Autopilot ECU两个板子分为两层装进了同一个外壳中(如下图),使得原本娱乐域和自动驾驶域的两个零部件就像左脑和右脑的关系一样,物理上组合在一起形成了一个车载大脑零部件。 如上图,其中上层的板子为媒体控制器,使用Intel Atom E3950的4核2.

从TDengine的开源说起技术选型

如果一艘快艇足够承载下你的所有货物到达彼岸,那么你不需要使用一艘轮船出行。产品设计和技术选型也是一样,我们经常会说:“我需要一个能够处理百万规模并发读写操作的,低延时,高可用的系统。” 如果按照这样的需求去设计系统,你可能得到的是一个设计复杂,代价昂贵的通用方案。但是如果仔细分析一下需求,你可能省略了需求背后的一些前提条件,比如真实的需求可能是这样的:“我需要一个能够处理百万规模的并发(只是理论峰值,平均情况小于10万并发)读写操作(读写比例1:9,只有追加写,没有修改操作)的低延时,高可用的(可以接受一定程度数据不一致性的)系统。” 那么你可能可以为这个特定的需求设计一个简单的,高效又低成本的系统。 做技术选型时,我们不会单纯的说A方案比B方案好,只是在解决特定的问题上,A方案比B方案更合适,选择了A方案的同时也意味着接受A方案里那些不如B方案的地方。在特定领域问题上的优化和定制方案往往能够取胜于解决更多领域问题的通用方案。最近涛思数据开源的TDengine也是这样一个针对专用领域的优化方案,TDengine的官方介绍如下: “TDengine是一个针对物联网,车联网和工业物联网领域优化的开源大数据平台。除了是一个速度快10倍的时序数据库,它还提供了缓存,流式计算,消息队列和其他以减少开发和运维的复杂度和成本的功能。” 在TDengine的官网文档上我们可以了解到这是一个针对IOT领域数据特性优化的强大的大数据计算平台。最近花了一些时间去熟悉这个开源项目的文档和代码,聊聊在做IOT时序数据库这方面的技术选型时使用TDengine或者其他产品一些可能需要考虑的点。 版本的选择 TDengine提供了三个版本的产品:社区版,企业版以及云版本。 其中社区版是本次开源的 单机版本 ,根据官方的介绍社区版拥有TDengine的大部分核心功能,是 处理中小规模数据 的理想平台。 企业版 在社区版的基础上新增了 高可用、横行扩展 等集群功能,内置 异地副本复制 功能,可用性达运营商级服务等级,提供 更强大的运维管理工具 。 而云版本则为运行在AWS/阿里云上托管的企业版,按月付费省掉了你自己部署和系统运维的工作。 类似的,行业里另一个比较流行的开源时序数据库InfluxDB也同样提供了三个版本的选择: 开源的单机版,商业的集群版以及云版本,功能对比如下图。 开源协议的考虑 TDengine的社区版本 基于AGPL 3.

那个上传的通讯录有毒!

近期,一则智联招聘员工倒卖个人简历信息的新闻在网上传播《5元一份!16万份简历被盗卖,“智联招聘”多名员工涉案》,个人隐私保护和网络信息安全的话题又一次被拾起。随着越来越多的个人信息电子化,信息安全的保护愈加重要,信息泄漏背后有人为的因素,也有信息系统建设安全设施不健全的因素。 前段时间看到一个黑产界在抖音进行精准营销的例子:抖音的推荐机制里,会经常请求用户手机的通讯录发现新用户或者把自己发布的视频推荐给通讯录里的新用户。黑产大佬呢,这时候,手握无数用户手机号码,做好手机号码归类,就可以尝试进行营销。举个例子,黑产手上有一批打着家长标签的手机号码,把这些号码导入到手机通讯录,用这个手机注册一个抖音用户,只发布育儿商品视频,那么这些视频会被精准的推荐给通讯录里的抖音用户(那些打着家长标签的号码),转化率也是可想而知。 现如今传说中的黑产界流通着各种不同线上线下渠道收集到的数据。你通过中介卖了一个房子,可能后面几年时不时会有电话打过来跟你说在哪有个新楼盘要不要考虑一下。你在汽车APP上尝试对车辆进行一次二手车估价,可能后面几个月你会不断收到不同地方打来的,询问你是否要卖车的电话。据网上消息报道,2018年年中,华住酒店集团有5亿条用户信息疑似遭到泄露,来自圆通和顺丰的总计十几亿条个人信息在暗网被出售。2019年央视3·15晚会也介绍了个人隐私信息通过手机App泄露的案例。 那么手机号都是怎么被泄漏的呢?除了一部分内部人员利益因素的有意售卖,或者不慎使用了恶意APP之外,有相当一部分数据是因为系统的信息安全建设不到位导致的数据泄漏。有存在系统漏洞被完整拖库的,也有接口保护不完善被恶意利用的,这里面也不乏拥有数亿用户的大平台产品。 举个大家熟悉的微博的例子。很久很久以前,国家刚开始执行社交网络实名制,各大社交网络平台的解决方案是让用户绑定手机号,通过运营商对手机号的实名登记完成。于是乎短时间各个人的微博账号都关联上了手机号。另一方面,为了进一步拓展社交关系网络,微博开始收集用户的通讯录数据,向用户推荐他还没有在微博上建立联系的通讯录里的好友。这个功能出发点挺好,然而刚刚上线那会,接口保护不完善遇到了可能产品设计者也没想到的功能滥用: 简单的,比如你有个陌生的未接来电,你想查一下是谁,利用微博这个功能可以这么查:你把这个手机号在通讯录里存一下,走一遍微博的上传通讯录&推荐通讯录好友功能,如果这个手机号也绑定了微博,微博就会给你找出来对应的微博账号。 再进一步呢,这是个通讯录的上传功能,天生就自带了批量查询属性,加上早期接口防范机制不健全(现已修复),于是乎前几年存着一种批量爬取微博手机号的漏洞: 如下图,我们知道运营商的手机号是分地区分配的,知道一个前缀可以查运营商和归属地,比如1817823这个前缀是中国电信分配给了广西柳州的手机号,符合这个前缀号段的号有1万个(手机号共11位),把这1万个号分成10个通讯录,每个通讯录1000个联系人,做十次通讯录上传&推荐通讯录好友的功能,便可以找出这1万个号码里对应的微博账号。在接口保护机制不健全的情况下,一个每秒只发10个请求的脚本(10 QPS对于微博这个体量的访问量来说是非常不可见的),相当于每秒完成1万个手机号的查询,跑一个小时便是3千多万个手机号,数量非常可观。 老实的微博大哥看着乐观的运营数据以为收集了好多用户通讯录,殊不知自己因为这种有毒的通讯录在一次次的往外吐着自己的用户数据。 系统漏洞并不偏好于产品的核心功能,实际上往往一些不起眼的地方的漏洞也会带来很大的损失,而这些不起眼的地方经常会是开发过程中最容易被忽视的地方。一些新的APP开发有时候为了赶时间上线,容易忽视这些不可见的安全方面加固的工作投入,以至于后期出现严重的问题。 防止接口被滥用的方法主要有几个方面: 通过接口签名和密钥保护(比如,白盒加密)的方法尽可能的防止签名方法和密钥泄漏被脚本实现调用; 加强输入参数的有效性校验,拒绝不符合期望的输入请求; 频次控制,对单个来源IP单个接口在短时间内的访问次数限制; 人机挑战,当检测到异常访问时,可以通过人机挑战的方式(比如输入滑块验证码,做基本算数题等)来要求调用方证明自身不是机器; 接口设计上仅输出必要的信息,避免过多的暴露信息而被利用; 线上无小事,防范于未然。

服务网格(Service Mesh)与Kubernetes的服务发现

伴随着微服务架构, 容器编排技术 和云原生(Cloud Native)应用的发展,William Morgan 两年前一篇《 What's a service mesh? And why do I need one? 》把服务网格(Service Mesh)带入到更多人的视野,近两年服务网格软件Linkerd,Istio等在 越来越多的公司生产环境中有所应用 。 在微服务架构里,服务网格是一个负责专门处理服务到服务之间通讯的基础设施层。 服务网格有两个主要目标,一个是将原先不可见的服务间通讯可视化; 另一个是对服务间的通讯进行一定控制(在路由/跟踪/安全等方面); 实践中, 服务网格通常被设计成轻量的 网络代理 程序,通过无侵入式的方式与应用集成,接管服务所有 入口和出口的网络流量,作为微服务之间网络拓扑中的通讯管道。 Kubernetes提供了服务抽象及服务发现机制,支持微服务之间的相互通讯,为什么我们还需要服务网格呢?我们先来看看Kubernetes的服务发现。 Kubernetes通过抽象出Service对象来支持微服务架构,运行应用的多个Pod实例通过定义Service对象对外提供服务。应用之间通过Service名来相互访问,通过Service名的DNS解析完成服务发现。 具体的,Pod实例运行时会将实例的地址端口等信息注册到kube-apiserver,与相关的Service建立关联(数据存储于背后的etcd存储),同时K8S节点会监听到该Service与Pod实例节点映射关系的变化。对于通常的一个Service名(非Headless Service),它会被DNS服务解析到一个虚拟IP(Virtual IP),而K8S节点上的kube-proxy进程会根据Service的信息建立这个虚拟IP的iptables转发规则:将发送到该虚拟IP的数据均衡的转发到若干个提供该服务的Pod实例所在的节点,以提供L4层的负载均衡功能。 类似于iptables代理模式,Kubernetes也提供了另一种基于哈希表的IPVS代理模式,以解决当服务数量达到上万级别的场景下iptables查找记录性能低下的问题,IPVS模式也提供了基于连接数,期望时延,加权选择等更多的负载均衡算法。 相对于Kubernetes工作在第4层的负载均衡,服务网格通过接管服务的出入口流量,可以提供更多对流量的路由控制,加工和可视化能力: 统一提供安全的双向认证加密通道; 支持7层协议检测,支持HTTP,HTTP/2和gRPC代理; 提供请求重试和超时功能; 自动 熔断机制; 支持基于就近/端到端请求时延的负载均衡; 服务请求的指标监控和可视化; 在应用服务网格之前,我们通常需要在各个服务程序内部实现以上的各个功能:服务的指标监控,请求重试及超时设定,熔断机制处理等跟服务业务逻辑代码混杂在一起存在于多个微服务之中。 以Linkerd为例,如下图,在集成了服务网格后,服务指标如请求成功率,延时及每秒请求数等会被自动记录并可以方便的集成到Prometheus和Grafana报表中展示。 服务网格使得服务运维所需要的代码逻辑与业务逻辑相分离,服务可以专注于业务逻辑的开发。 对于访问在Kubernetes中定义的Service,Linkerd会从K8S中读到Service对应的后台Pod节点信息用做负载均衡而不依赖于服务DNS。基于就近策略的负载均衡使得当Kubernetes在同城多机房部署时,可以优先路由到同机房的服务节点,减少跨机房访问。 服务网格在Kubernetes中有两种常见的部署方式: Sidecar容器的模式及主机共享代理模式。 Sidecar容器模式下linkerd-proxy被部署为每个pod里的一个容器实例,该模式下各个pod的linkerd独立,单个linkerd的故障不会影响其他pod,缺点是服务网格对系统资源的占用随着pod数量增长。 在主机共享代理模式下,同节点上的pod共用一个linkerd代理,这种方式可以减少linkerd的集群资源占用,也能够通过共享连接池的方式一定程度上提高吞吐量,缺点是当linkerd故障时同节点里的所有pod都会被影响到。 最后,服务网格跟API网关有什么联系和区别?API网关的主要职责在于为你的服务提供API接口,而服务网格的主要职责在于从服务实现里解偶出底层网络通讯及其相关的运维需求。两者在路由等部分功能上有一定的重合,但定位不同。微服务之间的内部依赖调用,如果都通过一个中心的内网网关来完成,那么所有服务形成一个中心化的星状网络。服务网格去中心化的架构使得拓扑中不存在一个可能影响所有微服务的中心网关节点存在,另一方面每次内部请求调用也少了网关这一跳的网络节点。 面向外部的API网关和面向内部的服务网格这样的分工通常会是一种推荐的部署方式。