看到本有趣的书 准备过年的时候读一读 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
rayeaster
V2EX    阅读

看到本有趣的书 准备过年的时候读一读

  •  
  •   rayeaster 2 天前 773 次点击
    12 条回复    2026-02-13 02:20:39 +08:00
    evansun
        1
    evansun  
       2 天前
    你这个帖子就很有趣,你是不是忘记挂书名了。
    yingqiuQAQ
        2
    yingqiuQAQ  
       2 天前
    看到个有意思的帖子,准备等会再过来看下
    zhq566
        3
    zhq566  
       2 天前
    过年在想要不要看彭昱畅新剧年少有为的小说。
    hellomsg
        4
    hellomsg  
       2 天前
    有趣的分享
    abu
        5
    abu  
       2 天前
    好好奇啊,多有趣,踢我一下
    sillydaddy
        6
    sillydaddy  
       2 天前
    答案就在 OP 的头像里 :doge
    justd
        7
    justd  
       2 天前
    有点意思
    panda188
        8
    panda188  
       2 天前 via Android
    带回家,然后再带回公司
    rayeaster
        9
    rayeaster  
    OP
       2 天前
    翻译自 Subhash Choudhary 的 Accidental CTO 一书
    rayeaster
        10
    rayeaster  
    OP
       2 天前
    第 1 章 凌晨 3 点响起的手机

    第一节: 服务器崩了


    我的手机突然响了起来,但不是那种普通的来电铃声,而是一种类似尖叫的声音。

    那声音伴随着一种特定的手机振动(通常被手机厂商用于提示最高等级的恐慌情绪)。振动的手机在我床边廉价的木桌上发出了剧烈而仿佛暴怒的嗡嗡声。那是一种不光能让你从睡梦中惊醒并且能够让你立马进入高度戒备状态的声音。此刻,时钟上的时间微微透着令人不安的红光:凌晨 3 点 14 分。

    其实甚至在我睁开眼之前,我的心就已经开始砰砰直跳。因为一般来说,在这样的午夜时分收到来电只有两个原因:要么是家里人有急事,要么就是公司业务出大事了。手机显示的来电号码确认了后一种情形。一个再熟悉不过的名字闪入我的视线:苏米特( Suumit )。

    苏米特.萨( Suumit Shah )是我的至交和公司合伙人,他敏锐的商业头脑对于我这样的码农而言非常重要。他在凌晨 3 点打电话给我那只会有一个原因。公司出大事了。


    我迅速在手机上滑动接听,虽然我的声音听上去有些沙哑和疲惫:“咋啦,兄弟?”


    “苏巴什( Subhash )! 网站全挂了!” 透过手机麦克风,苏米特的声音听上去就像是一声令人肾上腺素飙升和无比紧张的枪响:“快起来!网站全都不能用了!”


    他不用再多说什么。我已经翻身下了床,光脚踩在冰凉的地板上,全身就像被电击一样。我摸索着找到了我的笔记本电脑, 熟悉的苹果标志泛着白光就像黑暗的房间里的一座灯塔。 我此刻思绪万千,一大堆可能出现的服务灾难场景在脑海中无序地飘过:


    是被黑客攻击了嘛? DDoS 攻击?难道是哪个外国写脚本的小屁孩闲着无聊来搞垮我们的网站用以取乐?

    或者是我们自己的程序员上传了一段有问题的代码?难道是某个多余的分号导致网站完全崩了?

    是不是我们的云服务商挂了?如果是这种情况,那我们还能做啥?

    “网站页面显示不出来。手机端应用也在报错。全都挂了。完完全全的彻底崩了。”苏米特用紧张并且焦虑的声音继续说着。我甚至能听到他在电话那头来回踱步。

    “好的好的,我已经在处理了。哥们淡定。” 我尽量让自己听上去比真实的内心更稳定一点。 一定要保持冷静。 救火第一条原则就是不要火上浇油去添乱。

    略带睡意,我用笨拙的手指开始在键盘敲击。我打开终端( terminal )准备登录。这个黑底绿字的界面是通往我们所有线上服务的指令中枢。

    ssh [email protected]


    我敲下了回车键。光标开始闪烁,继续闪烁,仍在闪烁。

    正常来说,登录提示符应该很快就出现。但现在这个情况。。。感觉不妙。非常不妙。这意味着服务器不只是出现问题了,而是像一个已经进入生命倒计时的垂危病人甚至无法从病床下来应门。在等待了很长很长一段时间之后(长到我甚至觉得仿佛比一辈子还要久),登录提示符终于出现了。还好,至少服务器还没有完全挂,但也差不远了。

    我开始思考原因:如果服务器响应如此缓慢,那应该不是简单的应用代码问题( bug )。应该是有更深层的问题。可能出在系统层面。就像是服务器本身在苟延残喘。

    我输入了我的第一个诊断命令。这是用来检查服务器基本体征的一个简单工具:


    htop


    屏幕上显示的检查指令输出结果令我脊背发凉。满屏的红色。

    每一个进程( process )似乎都处于异常状态。CPU 使用率已经飙升到 100%。结果显示服务器几乎所有内存都已经被占用。甚至连服务器临时救急的 SWAP 存储空间都已经满了。

    看上去服务器并不是在苟延残喘。 它其实已经凉透了,而我们只不过目睹了它超负荷状态下的最后几次抽搐(登录和检查指令响应)。


    紧接着我马上知道了我们网站彻底歇菜的原因。简单得甚至有些尴尬:显示屏上方清楚地展示着服务器的总内存容量是 512MB 。

    五百壹拾贰兆字节。

    我的智能手机拥有 8GB 的内存,比这台承载了我们公司所有业务的服务器要大 16 倍。数千家电商客户以及他们数以百万记的商品名录,Dukaan (我们的公司)全部的希望和梦想都运行在这台比我口袋里的手机还要弱的服务器上。

    这不是一次复杂的黑客行为或者代码错误。原因很简单:就是服务器不够用了。 就好像我们在一个小小的电话亭举办一场大型的摇滚演唱会,最终电话亭被挤爆了。

    盯着屏幕,手机仍响在耳侧,我突然瞬间清醒。像我这样一个不是计算机专业科班出身,没有正儿八经大规模系统扩容经验的人,到底是如何承担起这一切的?

    要弄明白这个问题,先得弄懂我们正尝试驯服的这头野兽。也就是需要如庖丁解牛一样深入理解此刻正在作妖的家伙:服务器。
    rayeaster
        11
    rayeaster  
    OP
       2 天前
    第 1 章第 2 节 庖丁解服务器(一个厨师的厨房)

    让我们先把这场半夜 3 点的惊慌无措搁在一边。在我们解决问题之前,得先理解问题。所以问题来了:“服务器”到底是啥?


    请暂时忽略过于技术的解释。忘记在冰冷机房闪烁的指示灯。在本书剩余部分,我建议你用一个更简单浅显的概念来看待“服务器”:它就是只有一个厨师的餐厅后厨,所以很明显那个厨师会非常忙碌。

    这个类比将会是有关服务器架构的最重要基础,其它东西都将在这个类比的基础上构建。

    CPU: 厨师的速度

    中央处理器 (Central Processing Unit) 就是掌勺的大厨。它是所有处理逻辑的核心大脑。这位厨师把原料 (数据)按照菜谱(代码)制作成一道可口的菜肴(一张网页,一个搜索结果,一笔完成的订单)。


    ● 更快的 CPU (用千兆赫作为单位, 即 GHz) 意味着你拥有手脚更麻利的厨师。 它可以用更快的速度进行切菜,炒菜和装盘。


    ● 多核 CPU 就像厨师多了几个机械臂。 比如 4 核 CPU 就像一位能够同时操作切菜,炒菜,煎炸和调味的厨师。它可以在同一时间处理多项任务。

    我们那 512MB 的服务器只有一个单核 CPU 。按照这个厨师的类比,就如同我们只有一位独臂大厨但我们却要求他为 1 万人做一顿大餐。




    RAM: 厨房的操作台面空间

    内存( Random Access Memory )就是厨房的操作台面。这是理解服务器最关键的一步。内存就是厨师可以利用的工作空间。厨师( CPU )会使用内存来保存当前正在被制作的菜肴所需的所有原料以及锅碗瓢盆。

    从厨房台面拿取所需非常快速。厨师甚至不需要思考, 想要什么直接伸手去拿就可以了。 更多的内存意味着更大的操作台面。如果拥有很大的操作台面,那厨师可以立马处理很多不同的点餐需求因为所有食材都在它面前的台面上摆放着可供随时取用。

    但是如果台面放不下了,那厨师就会有棘手的麻烦。他得放下手头正在处理的活儿, 一头钻进后面的储藏室,从中花时间找到并拿回他所需的食材,还需要从台面上挪走一些东西以便腾出空间。这样一个操作明显会让所有事情都变得更慢。




    这就是之前发生在我们服务器上的事情。我们仅有 512MB 的服务器就好比一个只有砧板大小的厨房台面。而我们自己的应用( Dukkan ),我们的数据库以及服务器上的操作系统本身 全都在争夺这一块小小的砧板空间。所以当台面放不下的时候,服务器开始使用 "SWAP"空间可以看成是储藏室中一个特殊的区域,在临时救急时也可用作台面空间。这肯定是效率极低的方案。厨师不得不花时间来回奔走于储藏室与台面之间,必然耽误了它真正用于烹饪的功夫。


    磁盘: 厨房的储藏室

    磁盘,无论是传统机械硬盘或者是固态硬盘,都可以看做厨房的储藏室和冰箱,是用来长期存储菜谱(代码),食材(数据)以及厨房用具(操作系统)的地方。

    储藏室比操作台面( RAM )显然要大很多,但存取耗时也要慢很多很多. 你肯定不希望你的厨师即使为了拿一点点食盐也得跑去储藏室一趟。 最理想当然是食盐就摆在它的操作台面上。


    资源竞争: 厨房里的无序


    现在请设想一下我们面对的场景。在一个迷你的厨房里,我们的独臂厨师只有一个砧板大小的操作台面, 然后我们苛求它完成:

    ● 运行应用程序: 厨师需要看明白菜谱(我们的 Python 代码) 并完成菜肴的烹制。

    ● 管理数据库: 大厨还得兼任储藏室管理员,不停地把食材(我们的用户数据)分门别类记录好 ,保存好并按食谱准确地取用。

    ● 处理网络流量: 除了以上, 大厨还需要完成服务生的工作:跑到餐厅前台以最快速度为数千用户点单。

    这就是资源竞争。每一项任务都在同一时刻高呼大厨希望优先得到处理。应用程序需要 CPU 来处理运算逻辑,数据库需要把数据写入磁盘,还有刚接收到的用户请求需要内存来暂时记录。所有这些都在竞争同一个有限的资源,所以结果就是完全的死局,无法动弹。

    如果想看到厨房里发生的这些无序竞争,你可能需要安装一个监控摄像头。在服务器的世界里,我们的摄像头只是一个简单的命令:htop. 它是命令行工具 top 的优化版本,可以让你犹如现场直播般看到大厨正在忙啥。

    虽然可能看上去挺复杂,但你只需要了解以下几点:

    ● 顶部的 CPU 柱: 如果它显示红色的 100%,那你的大厨就是过载了。


    ● 内存柱: 如果这个数字满了,说明你的操作台面已经放不下了。


    ● SWAP 柱: 如果这个数字开始增加,这不是好的信号。说明你的大厨正在尝试使用储藏室作为额外的操作台面。


    ● 进程列表: 这里展示了大厨正在处理的每一个任务并且能让你看到哪一个占用了最多的资源。

    学会读懂这个 htop 的输出只是成为 CTO (要么像我这样误打误撞,要么按部就班)的第一步。从这里开始,我们将进行科学的诊断而不是盲目的瞎猜。对于我个人而言, 那晚半夜 3 点的服务器屏幕尖锐地喊出了一个无可辩驳的事实: 我们的厨房对于我们的抱负而言,实在是太小了,小到足以致命。
    rayeaster
        12
    rayeaster  
    OP
       2 天前
    第 1 章第 3 节: 我们伟大而危险的大单体应用

    如果说服务器就像厨房, 那如何描述我们大厨( CPU )正在使用的菜谱(代码)呢? 在软件行业的术语里,我们称之为服务架构。我们采用的架构非常经典, 是那种几乎每一个初创公司早期都会采用的架构。
    是的,我们用的是一个巨大的单体应用( Monolith )。

    这个名字听上去像某种远古巨石阵一般巨大,有点唬人。但事实上,它非常简单。单体应用是指你所有的代码逻辑都在一处一起运行。比如我们的用户注册,商品名录,订单管理,商户仪表盘,支付,所有功能都同处在一个 Django ( Python 流行的 web 框架)项目里面。

    可以把它想象成一本巨大的百科全书般的食谱。它包含从开胃小食,主食,甜品,以及饮品在内的所有菜谱,很显然这本书会超级厚。

    为什么我们要选择从大单体应用起步(为什么它是正确的上手选择!)
    我想直截了当地明确这一点:从大单体应用开始构建没有问题。对于初创企业而言,它大部分时候都是最优可行方案。在创业初期,你唯一的目标就是尽快构建并推出产品,越快越好。因为你需要知道你打算推出的产品的确有人愿意买单。
    大单体应用天然就是为速度而生:
    1. 易于代码开发: 所有逻辑都在一处。无需操心复杂的服务间通信问题。只需要编写一个函数然后调用它就行了。
    2. 易于测试: 可以在笔记本电脑上运行整个应用并轻松地联调测试所有功能。
    3. 易于部署: 只需把所有代码打包放到服务器上就完工了。
    我们构建的大单体应用允许仅靠苏米特和我两个人在 48 小时内就上线了一个可以正常运行的电商平台。如果我们采用更复杂的“微服务”架构(本书后面的章节会详述), 我们现在可能还在为系统设计的细节争论不休。
    所以大单体应用就是我们的超能力,给予我们极速试错的机会。但就像所有超能力一样,它也有一个不易察觉的危险副作用。
    大单体应用的隐型危险
    随着我们的菜谱增加,问题逐步开始显露。

    ● 变得愈发沉重以致难以使用。 查找某个食谱可能耗时更长。搞清楚为什么甜品部分的一个改动可能影响到开胃餐部分变得几乎不可能。在软件行业的术语里,我们称之为紧耦合。
    ● 一个小错误可能会毁了整本食谱书。 一个菜谱里面的一个小小的笔误理论上可能导致整本书都难以理解. 类似的,一个小小的代码错误可能会让整个网站都崩掉。
    ● 雇佣一个各司其职的专业团队变得毫无意义。比如即使你聘请了一个专业的糕点大厨, 它可能仍然需要理解一整本巨无霸食谱书才能开始工作。类似的,大单体应用会让新加入的开发者很难迅速融入以致降低效率。

    最重要的是(也是那天晚上导致我们网站崩溃的原因), 大单体应用让你别无选择:如果你仅仅想为食谱书中某一部分(对应软件应用的某个功能)扩容( Scale ),那你只能先把整本书都扩容。


    比如我们电商客户的商铺主页面访问量很高 (好比是食谱上的主食部分很受欢迎)。但另一方面我们的销售仪表盘(好比是食谱上的开胃餐部分) 被访问的次数就要少得多。可是由于他们同处于一个大单体应用中,我们的服务器资源得同时提供给所有功能。 处理主食的巨大消耗(厨师/CPU )让其它厨房任务处于资源嗷嗷待哺的状态,最终导致整个系统的崩盘。


    我们那运行在小得可怜的服务器上的大单体应用成了一个潜在的完美毁灭风暴:一个软件层面的单点( Single Point of failure )运行在一个硬件层面的单点。 这简直就是一枚时间炸弹,最终在周二凌晨 3 点 14 分被引爆了。


    第 1 章的关键知识点总结

    ● 你创业历程中第一台服务器肯定会有崩溃的一天。这不是一个会不会崩溃的问题,而是何时崩溃的问题。所以我们的目标应该是如何从崩溃中迅速恢复并从中总结经验, 而不是绞尽脑汁试图去避免崩溃。
    ● 深入理解架构基础。 在学习复杂架构之前, 彻底搞明白有关服务器运行的原理。 思考这些概念:CPU (大厨的手速), 内存 (操作台面空间), 以及磁盘 (储藏室).
    ● 掌握基本诊断工具库。如果看不到问题,那也没办法修复问题。学会使用 ssh 和 htop(或 top) 这些命令行工具。这些就是系统管理员的听诊器。
    ● 从大单体应用开始构建是一个实用选择( feature ),不是错误( bug )。创业初期,速度就是王道。尝试打造完美的早期产品属于用力过度。
    ● 认识到你的初期技术选择存在保质期。 为你赢得头 1 万个用户的架构很可能没办法帮你拿下接下来的 10 万个用户。为迭代进化做好准备。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2008 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 22ms UTC 03:34 PVG 11:34 LAX 19:34 JFK 22:34
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86