如果说服务器就像厨房, 那如何描述我们大厨(CPU)正在使用的菜谱(代码)呢? 在软件行业的术语里,我们称之为服务架构。我们采用的架构非常经典, 是那种几乎每一个初创公司早期都会采用的架构。
是的,我们用的是一个巨大的单体应用(Monolith)。
这个名字听上去像某种远古巨石阵一般巨大,有点唬人。但事实上,它非常简单。单体应用是指你所有的代码逻辑都在一处一起运行。比如我们的用户注册,商品名录,订单管理,商户仪表盘,支付,所有功能都同处在一个Django(Python流行的web框架)项目里面。
可以把它想象成一本巨大的百科全书般的食谱。它包含从开胃小食,主食,甜品,以及饮品在内的所有菜谱,很显然这本书会超级厚。
为什么我们要选择从大单体应用起步(为什么它是正确的上手选择!)
我想直截了当地明确这一点:从大单体应用开始构建没有问题。对于初创企业而言,它大部分时候都是最优可行方案。在创业初期,你唯一的目标就是尽快构建并推出产品,越快越好。因为你需要知道你打算推出的产品的确有人愿意买单。
大单体应用天然就是为速度而生:
-
易于代码开发 : ****所有逻辑都在一处。无需操心复杂的服务间通信问题。只需要编写一个函数然后调用它就行了。
-
易于测试 : 可以在笔记本电脑上运行整个应用并轻松地联调测试所有功能。
-
易于部署 : 只需把所有代码打包放到服务器上就完工了。
我们构建的大单体应用允许仅靠苏米特和我两个人在48小时内就上线了一个可以正常运行的电商平台。如果我们采用更复杂的“微服务”架构(本书后面的章节会详述), 我们现在可能还在为系统设计的细节争论不休。
所以大单体应用就是我们的超能力,给予我们极速试错的机会。但就像所有超能力一样,它也有一个不易察觉的危险副作用。
大单体应用的隐型危险
随着我们的菜谱增加,问题逐步开始显露。
● 变得愈发沉重以致难以使用。 查找某个食谱可能耗时更长。搞清楚为什么甜品部分的一个改动可能影响到开胃餐部分变得几乎不可能。在软件行业的术语里,我们称之为紧耦合。
● 一个小错误可能会毁了整本食谱书。 一个菜谱里面的一个小小的笔误理论上可能导致整本书都难以理解. 类似的,一个小小的代码错误可能会让整个网站都崩掉。
● 雇佣一个各司其职的专业团队变得毫无意义。 比如即使你聘请了一个专业的糕点大厨, 它可能仍然需要理解一整本巨无霸食谱书才能开始工作。类似的,大单体应用会让新加入的开发者很难迅速融入以致降低效率。
最重要的是(也是那天晚上导致我们网站崩溃的原因), 大单体应用让你别无选择:如果你仅仅想为食谱书中某一部分(对应软件应用的某个功能)扩容(Scale),那你只能先把整本书都扩容。
比如我们电商客户的商铺主页面访问量很高 (好比是食谱上的主食部分很受欢迎)。但另一方面我们的销售仪表盘(好比是食谱上的开胃餐部分) 被访问的次数就要少得多。可是由于他们同处于一个大单体应用中,我们的服务器资源得同时提供给所有功能。 处理主食的巨大消耗(厨师/CPU)让其它厨房任务处于资源嗷嗷待哺的状态,最终导致整个系统的崩盘。
我们那运行在小得可怜的服务器上的大单体应用成了一个潜在的完美毁灭风暴:一个软件层面的单点(Single Point of failure)运行在一个硬件层面的单点。 这简直就是一枚时间炸弹,最终在周二凌晨3点14分被引爆了。
第1章的关键知识点总结
● 你创业历程中第一台服务器肯定会有崩溃的一天。 这不是一个会不会崩溃的问题,而是何时崩溃的问题。所以我们的目标应该是如何从崩溃中迅速恢复并从中总结经验, 而不是绞尽脑汁试图去避免崩溃。
● 深入理解架构基础。 在学习复杂架构之前, 彻底搞明白有关服务器运行的原理。 思考这些概念: CPU (大厨的手速) , 内存 (操作台面空间) , 以及磁盘 (储藏室) .
● 掌握基本诊断工具库。 如果看不到问题,那也没办法修复问题。学会使用ssh和htop(或top) 这些命令行工具。这些就是系统管理员的听诊器。
● 从大单体应用开始构建是一个实用选择(feature),不是错误(bug) 。 创业初期,速度就是王道。尝试打造完美的早期产品属于用力过度。
● 认识到你的初期技术选择存在保质期。 为你赢得头1万个用户的架构很可能没办法帮你拿下接下来的10万个用户。为迭代进化做好准备。