最近沉迷于一款游戏 《城市:天际线》,发现了一些和软件架构的相似性。
玩家扮演市长这个角色,通过规划建造出村庄、城镇直至大城市。
城市规模的变大使得 “面多了加水,水多了加面”的摊大饼式发展难以为继,“道路拥堵、负债累累”往往成为了游戏后期的大城市病。这一点和大型互联网业务的网站架构如出一辙。
城市入口与网关
游戏一开始,从高速公路切出两条路作为城市的出入口和外界的交流便产生了。
通上水、电、路之后,划分居民区、商业区、工业区后,便陆续有市民搬进来。
在城市发展初期,秉着“有多少钱,办多少事“的原则,只是简单地铺了两条单行道。好比一个单体应用,拉了一根网线申请了一个公网 IP 就开始对外提供服务了。不必过度优化,差不多够用就行。网关也不需要复杂的路由规则。简简单单,省心省力。
城市发展到一定规模后,流量规模、类型也会发生改变。公路、铁路、飞机、渡口等形成交通枢纽。
网站的网关也会演化为能够流量治理、容灾、可扩展的集群。
区域管理与领域驱动 DDD
城市的生活区、工业区和商业区是生产、消费者关系循环。居民去工厂上班,商店去工厂进货,居民去商店消费。在一段发展期内是个简单的”水多了加面、面多了加水“的游戏。
区域聚集往往会形成规模效应,比如美食街、电脑城、菜市场.. 每个区域都有其对应的职能。
软件研发也往往会从全栈工程师演化为前端、后端、中间件、数据库、基础架构等职能。而业务后端逻辑也会进一步拆分,如电商业务分化为商品管理、订单管理、广告竞价排名…
工业区也会演变成林业、木材加工、家具制造的产业链。
这时候城市变成了一个复杂的生态系统,大型互联网业务的软件架构也是如此。
道路交通与微服务调用链
城市的生态系统通过道路得以进行货物与货币的循环。
大型互联网的业务通过分布式的微服务调用最终对外提供产品服务,流量的治理从”南北向“ 转化为 ”东西向“。
同一条路上既有步行上班的市民,也有货车、公交车、私家车、城市服务车辆(救护车、警车、垃圾清运),随着流量的增大,拥堵必不可免。治理道路拥堵两大法宝:
1、流量分离
2、增加吞吐
通过将客运、货运分离(私家车在早高峰走市内高架、货车走环城高速),建立公共交通地铁,极大提高人流量的吞吐。还有道路限行、车道分离等治理策略。
大型互联网业务的微服务调用也面临拥堵难题。通过将业务通过多个维度的划分进行分而治之,常见的维度可能有:
1、在线业务或离线业务
2、核心业务或外围业务
3、资源类型:CPU 密集型或 IO 密集型
4、To B 或者 To C
5、服务类型(API、中间件、数据库)
通过多个维度管理形成服务画像,合理分配资源,做好离线混布、周期性资源调度预算。
道路红绿灯矩阵与服务网格
城市道路的无数个红绿灯,是城市交通的矩阵。目前的红绿灯都是单个控制的,并没有形成协调作用。倘若道路能够成为可编程,像 FPGA 芯片一般,那么很有可能做到资源的使用均匀。避免有的道路堵到天际,有的道路门前冷落的道路资源使用不均。这应该可以被成为软件定义交通了!
微服务的流量治理目前最流行的概念是 Service Mesh(服务网格)。流量治理一旦可编程,就可以成为软件定义流量治理(Software Define MicroService )了。这个概念很令人着迷,是基础架构程序员向复杂业务系统的一次挑战。不过 IT 业没有银弹。
城市的边界与单元化
城市规模的边界约等于城市交通工具一小时的路程。城市规模受限于交通工具的速度。
软件的规模受限于光速在 100 ms 内移动的距离。(为什么是 100 毫秒?分布式系统的经验值而已,笑)
一般的业务搞双活,就是把数据复制到另外一个机房。一个机房写,一个机房只读的伪双活。
而随着业务数据量的增长,数据复制的延迟与成本使得这种双活再也无能为力。
这时候,阿里提出了 Set 化(单元化)架构。也就是将用户切分,然后某一个用户的流量闭环至一个机房。将用户按照某种维度(如地理位置或 ID )进行切分为多个 Set,单元化的 Set 数据复制到中心化 Set。
这就好比大城市的卫星城规划,每个卫星城的人口闭环至子城区内。从出生到死亡。
大洪水与故障演练
即便我们做了单元化架构,到了大洪水(机房断电、光纤被挖掘机挖断、数据中心爆炸)的那一刻,哪个资深运维敢信心十足地按下那个切流量的红色按钮呢?
有的城市每年都声称遇到了百年不遇的降雨量,内涝年年有。
微博每年都会因为明星不可访问那么一两回。
孙子曰,”胜可知,不可为也。“
有时候,我们做了各种软件架构改进,推演了各种灾难发生的概率分布,我们以为一切无碍时,现实又给了我们一巴掌。
软件有两种,有 Bug 的和没人用的。