赞
踩
王晨纯(沐剑),阿里高级技术专家,从商业和业务视角长期关注云原生、基础架构、中间件对应用架构带来的革新。
我在 2015 年做聚石塔容器平台 EWS 这个产品的时候,云原生 (Cloud Native) 这个概念还不像今天这样为大部分人所知,那时候对于云也好,容器也好,相关的争论比起今天有过之而无不及。前几天看到一篇文章,标题叫《微服务已死,云原生永生》,不禁莞尔,想起 5、6 年前,最流行的恐怕就是「微服务」的概念,当年也有人说「SOA 已死,微服务永生」类似的话,尽管似乎没人讲得清到底所谓的传统 SOA 和 Micro Service 有什么本质区别,SOA 嘛,字面意思就是面向服务的架构,微服务算不算「服务」?再从技术实现来看,服务发现、服务治理、分布式调用,似乎还是这些东西。在漫漫容器路上,也有人质疑,容器不成熟、不安全、不稳定。
基础架构很多时候是伴随着这些技术大神间的争论快速提升的,有时在早期的时间点很难决断到底什么是「正确」的技术,亦或是根本没有所谓正确,只有合适,架构师最擅长的是什么,其实是懂得平衡和妥协。但是,技术趋势的车轮始终会向前推进,一不留神就会产生技术的代际差距,今天业界对集市的信奉远比大教堂要兴盛得多,谈到云原生,还是要回顾一些标志性事件。
想起还是 2013 年的时候,Docker Engine 刚刚被 Release 出来,当时是为了把一个环境打包成镜像,解决本地研发环境和生产环境差异化的问题,说实话我在 13 年也没看出来有什么大的价值,但这个设计改变了今天我们很多软件交付的架构。
2015 年,Docker 方兴未艾,各家争鸣,Docker 的 Swarm 号称自己有最纯正的官方血统,Twitter 的 Mesos 则以 Marathon 占据了当年容器编排的半壁江山,Google 做 Omega 的兄弟们最终没有战胜 Borg,却将自己几年的工作成果用 Kubernetes 的名义散播出来。后来的故事大家都知道了,在这一场战争中,K8S 成为了行业事实标准,Golang 成为了容器乃至云的标准语言,CNCF 成为了云计算界的 Apache,进而将「云原生」这一概念持续定义和发酵。
到了今天,所有人都在提云原生,有点像当年都在谈微服务、区块链一样,但云原生究竟是什么,有点像量子力学,有很多种诠释。
对于云厂商来说,云原生代表了应用架构的未来,只有构建在云上的应用才预备包括弹性计算在内的诸多优点,最初谈上云,是先把架构原封不动地搬到云上,把基于 Xen/KVM 的虚拟机上的软件放到 ECS 上去跑,但实际上并没有充分体现云的价值,比如「免运维」,所以我们会说,在 ECS 上自己搭 MySQL 不是云原生,因为你还得自己做主备、快照、binlog 等等,而从 GAE 开始的 PaaS 则是让大家直接使用各类计算 / 存储服务,到今天,对于数据库来说,选择 RDS 乃至 PolarDB/OceanBase/TiDB 才是云原生,因为数据库的基础运维也好、扩展性也好,可以不用再被用户关心了。开发者当然是很高兴的,没有人愿意每天担惊受怕数据丢失的风险。
而对于用户来说,社区也好,Rancher 这样提供方案的公司也好,对他们来说,云原生是解决 Vendor Lock-in 的良药,也是 CNCF 在讲的故事,中间件和基础服务解耦,对于 GAE 形态的 PaaS 来说,尽管服务对外的 API 是 simple 的,但底层数据结构导致的迁移就没有那么容易了,于是服务的提供方由平台变为开源可独立部署的中间件,多云 (Polycloud) 架构开始盛行。仔细想想,Netflix 自己做那么多中间件,有一部分也是怕万一被 AWS 坑了吧。
但不管基础架构如何变迁,应用架构总是存在,好的应用架构应该是能适应乃至充分利用基础设施的变化,才能保持它的活力和技术竞争力。例如在工程技术领域。很多时候 I/O 的消耗是最大的问题,大部分业务应用本质上都是 I/O 密集型而非 CPU 密集型。为了优化针对机械磁盘的 I/O,过去有非常多的软件做了各种算法把随机读写转成顺序读写,把用户态拷贝转成内核态拷贝,为了性能有时在 Write-Back 和 Write-Through 之间做取舍,包括 Linux 的 I/O Scheduler 也是为了解决这个问题。但当 SSD 出现后,很多事情开始发生变化,Facebook 首先开始用 SSD 做 I/O Cache,后来国内一些互联网公司部分核心数据库用 Fusion IO 存储,紧接着业务数据库也开始转为使用 SSD,但当年我们切 SSD 的时候遇到了问题,最终定位是由于 CFQ 调度器导致的,再例如早期基于 LSM-Tree 的 LevelDB/RocksDB,后来针对 SSD 也都改进了读写算法,最后大家都明白了,对于新的存储介质,很多算法和设计都要演进才能发挥它的威力。
以前写过一篇文章,《面向 GC 的 Java 编程》,其实还有非常多类似的内容值得去讲,比如面向 SSD 低延迟寻道存储的软件设计,软硬一体的架构设计往往能最大化榨干性能,想象一下,如果我们的软件不用 SIMD 去做并行计算,不用局部性原理去加速数据读取,不用 DPDK 去做网络数据流的计算,不用 FPGA 等硬件做辅助虚拟化,很难支撑今天大规模的分布式计算,延伸想一下矿机是如何软硬一体运作的。
对于云原生也是相似的,如果没有利用好云的特性,在今天各行业客户都要拓展更广阔市场的前提下,大家都想要异地多活、全球部署的能力,如果还是用老的 IDC 思路去设计应用架构,很难。
云提供的最核心能力,我的看法还是算力,不在这里展开谈弹性这些老生常谈的问题。有 2 点是我对云的算力架构的一些想法。
首先,云的算力是分布式的,而分布式的算力是需要被「调度」起来的。在操作系统中,是在线程或是进程间通信视角去调度 CPU Core 的算力;在 IDC 中,在机架、机房(可用区)视角去调度不同服务器的算力;而在云上,我们在全球数据中心的基础上,一家小公司,也能在跨大洲、大洋的维度去调度 IDC 级别的算力(当然,从非技术因素来说,GDPR 等规定给算力和数据打上了政治标签)。大公司当年做异地多活,要自建或者租用大的跨省 IDC,但不是每个小公司都能做这么大投入,今天在云上,只要架构合理,完全可以小成本完成。类似的,用户还可以把计算密集型业务放到收费低的偏远 IDC 降低成本。从这个意义上来说,云厂商的重资产基建实现了算力的普惠。而对于这种能做到跨大洲的算力调度得好不好,就要取决于应用架构面向这种维度和视角的算力的设计了。另一方面,在澎湃算力的场景下,面向弹性的设计也很重要。举个例子,单机多线程编程往往不是面向弹性的,而基于 MQ 的设计,消费者算力不够时可以通过水平扩容解决,便是面向弹性的设计。
面向弹性的确是云原生的一个特征,但并不像眼见得那么容易,有钱就能解决访问量问题的方案基本等同于水平扩展友好的方案,但这类扩容和架构的耦合性还是比较高,新浪微博花了几年时间在阿里云上打造了自动化扩容平台,给明星们的绯闻热搜保驾护航,但这个能力今天还不是大部分公司都有的能力。
其次,跨 Region 的网络延迟扩展了计算机体系的延迟数据看板 (Latency Numbers Every Programmer Should Know) (2),对于程序员来说,不同的延迟对应不同的存储用途设计,原来我们都知道从寄存器、L1/L2/L3 Cache、内存、磁盘、网络各自的延迟差了上万倍。今天在中国,跨省的网络延迟在 30~80ms 左右,通过 CN2 到香港大概在 60ms 左右,中国大陆到美国大概是 200+ms。事实上,今天在做的各种容灾架构、异地多活都是基于这些关键数据,这是基于 MapReduce 的核心观点:移动计算比移动数据快,最初同城双机房容灾约 1ms 的延迟,到杭州-上海约 10ms 延迟,再到杭州-张北约 30ms 的延迟。对架构师来说,就要去看在跨 IDC 的维度上,如何基于几十毫秒的延迟去调度算力,原来 for 循环简单搞定的,这时候可能就要命了。过去我做了很多性能优化的项目,大多数时候性能就是在和延迟死磕。
面向云原生的应用架构,从某种意义上说,因为获得了更大算力的可能性,反而需要更被约束在最佳实践的模式里,最简单的例子就是 dockerfile,一个标准化的文件可以让软件瞬间分发到几千台服务器,但写过的人都知道,你必须非常克制和准确地描述你的需求,不能像过去一样,基于中心化的基础设施,配置满天飞。所以业界对于面向云原生的软件交付有了「不可变基础设施」这个核心原则,也是我现在在做政务中台的标准化系统交付时最核心的理念之一。
先谈这些吧,有空再写。
文中链接:
https://hesey.wang/2018/11/gc-oriented-java-programming.html
https://gist.github.com/jboner/2841832
原文链接:
https://hesey.wang/2021/04/thinking-cloud-native-computing.html
参考阅读
技术原创及架构实践文章,欢迎通过公众号菜单「联系我们」进行投稿。
高可用架构
改变互联网的构建方式
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。