《大型网站技术架构》读书笔记
2017-04-03 / modified at 2023-12-10 / 2.4k words / 8 mins

最近有一个月没有写文,主要是9106加班与看书比较多。今天写下最近买的一本书的读书笔记。

本书在Amazon仅售4.99,相对于它的内容价值,买到就是赚到。本书介绍了微博、淘宝、WIKIPedia、DDS等业务从最开始的PHP网页到最后分布式系统的整个流程。并能够从前端优化、CDN、反代到最后后台业务、MQ、DB等端到端的业务流程进行技术关键分析。最后章节甚至专门介绍了作为架构师如何做好非技术方向的改进建议,实在是国内难得的一本好书。

本文主要是介绍书中出现的各种技术关键点的名词进行资料搜索与总结,从而提炼出码农需要掌握的技能。

概念对比

首先要明白下面这两个概率,知道了它们才知道分布式架构中为何能够弹性伸缩

有状态与无状态

“状态”这个概念在线程安全与函数式编程的书中均有介绍。

我个人对无状态的总结是

它既不包含任何域,也不包含任何对其他类中域的引用(这里的域本质就是一个私有的全局变量),所有临时状态只在“栈”上执行。更严格的无状态下,如果你给它同样的输入,它不会受到其它业务组件的影响,返回值总是可控的。

什么是有状态的: 返回值受到全局变量干扰

  • C语言中的随机数(Seed是外部变量)
  • Session服务
  • BPM流程(比如各种复杂的订单业务)
  • 二次认证

什么是无状态的: 返回值不受全局变量影响

  • InflateStateMachine: 比如Zookeeper, DNS等NamingService, 以及 RuleEngine 等各种Router,它们都实现了根据入参实现状态转移
  • MessageQueue(比如DubboMQ,ActiveMQ,Kafka)
  • Cache(比如Redis,CDN)

其实上面这三个可以近似对应Java中的Tree,Queue,Map进行实现,你可以打开这些数据结构源码的内部,看下它是否引入了其它组件的全局变量。

无状态的业务一般是低耦合,线程安全,“纯函数”的业务。在扩展性上更好,可以通过水平扩展堆机器提高性能。

抽象语法与传输语法

此概念来源于通信专业,它由下面两种语法构成:抽象语法与传输语法。抽象语法负责数据类型、结构的描述,一般可以轻易的映射为编程语言中的结构体,传输语法用于报文序列化与反序列化,一般对用户透明。在互联网与IT架构组件中实际上都实现了这两个规范。

传输语法(如何序列号与反序列化)抽象语法(如何描述业务)
WebSerivceHTTP1.1(基于Socket, 来自 RFC 2616规范)WSDL(用XML描述)
Redis自有协议(基于Socket, 详见Redis源码分析等书)见各种命令
Zookeeper自有协议(基于Socket, 通过 Apache Jute定义DSL)见各种命令
MQJSR 343(基于Socket实现JMS接口)用户实现
EurekaHTTP1.1XML

技术组件

本书于2013年完成,当初下面的组件还是各个公司搭建环境各搞各的,在现在所有组件已经全面云化。

分布式文件系统(DFS)

DFS实际上就是常见的云硬盘,通过硬盘集群实现文件的上传下载的API提供。真正企业使用必然还是需要购买存储设备,比如Netapp或者FusionStorage,然后再封装为POSIX等服务。

分布式缓存系统 (DCS)

DCS就是一个远程的HashMap。以Redis为例,目前阿里云已经有了云Redis以及华为云的DCS,看起来应该都是对原有的Redis进行加固包装,并添加了Zk与运维管理功能。作为一个开发者,你还需要了解

  • Redis集群的源码实现(主从同步,心跳检测)
  • Redis单机的前台网络路由与ReHash实现
  • JedisPool的使用,连接池如何使用CommomPool维护Socket
  • 一致性Hash等路由方法的实现

分布式数据库系统(DDS)

DDS是一个远程的数据库,它可以

  1. 对内将各种厂商,各种业务的DB进行统一管理
  2. 对外暴露SQL92等标准语法的连接,用户不知道内部的表用户,也不知道DB密码
  3. 实现读写分离与最终一致性
  4. 实现SQL热点查询命令的预编译优化、缓存查询结果、统计缓慢SQL等。

目前各大厂商都有实现,比如阿里/华为云的云数据库,这个玩意还是很难搞的,需要很多专家团队去对业务进行优化。作为一个开发者,还是把单机版数据库搞清楚吧,比如

  • 数据库中的B+树、LSM树
  • 开源的 Cobar 可以学习一下

CDN加速

CDN的本质都是缓存,可以看作是正向代理的一种。这个以前文章也介绍过,而且已经竞争白热化,就不细讲了

  1. CDN指标主要是缓存命中率、缓存的节点分布速度、延迟。
  2. 目前(截至2017年4月1日),阿里已经宣称实现了0.17/G的流量费率,网宿、七牛/右拍/UCloud等厂商将会有很高的成本压力。

负载均衡

负载均衡是反向代理的一种,用于分配任务。比如阿里的SLB以及华为的LSS,按照带宽与机器收费。作为开发者,你需要了解

  • 规则引擎的实现,比如Nginx,Drools(使用这个前,我居然用正则表达式与for循环去折腾)等实现
  • 精通正则表达式
  • 维护Session的方法,比如直接扔到Redis或者插入数据库

消息队列(MQ)

目前主流的MQ有非常多开源与闭源的实现,比如IBM MQ、RabbitMQ、ActiveMQ、月饼厂的DubboMQ等。它们大部分都是对JSR 343规范的实现,实现异步与削峰作用。入门介绍可以看阿里的ONS云服务,帮助文档写的比书上更加通俗易懂。你需要

  • 了解至少一个开源产品从发送到接收的流程
  • 事件驱动模型
  • 最好也学下Netty库,很多使用它作为Socket底层实现

如何发布业务

发布业务就涉及到持续集成了,主要从源码、测试到最后发布实现。本部分结合书本与菊花厂的过程

源码管理

在代码开发上,主要有如下3个重点,当然流程上看起来是这个,实际上可能偷懒只做两步

  1. 版本管理
  2. VCS门禁(比如FindBugs)
  3. 代码Review

自动构建

自动构建就是传说中的云编译,一般使用单核性能强的“计算云”。在服务器上配置好编译脚本,就可以让后台进行定时自动构建。作为开发者,需要

  • Ant、maven、gradle 要最起码看得懂脚本,能够照猫画虎地进行修改
  • 熟练使用Linux Shell 与 jenkins

测试

现在测试在互联网公司已经很少了,在菊花厂内部也在推广开发测试一体化。但是这个并不能代表测试不重要,菊花厂作为交付厂商,内部按照瀑布流程,从SIT1~SIT5都要测试一次,每次转测试大家都很痛苦。当然这样不够“敏捷”,这个也是菊花厂与互联网厂商的不同之处,惯性太大难掉头。作为开发者,需要至少掌握 JUnit、TestNG 工具的使用

发布

经过测试后,终于可以发布了

  • 合理配置后台的Log等级、JVM参数
  • 为发布包进行签名,对Git库打上Tag

SUM

相比于前台、Android等开发,后台的确门槛更高一些。后台开发的深入不是靠源码分析就可以做到的,个人提升有很大的代价,只不过这些成本是公司帮你承担了(比如开发调测环境至少要上万元一年,你写的代码出错对你来说是经验,对公司来说是损失)。

  1. 后台各种技术组件基本上都全面云化/无状态化,只要花钱就可以买到服务,降低了维护成本

  2. 在写业务(BusinessObject)时,尽可能写无状态的代码,实在不行的话,要保证业务的原子性,写完了记得用线程安全工具再扫一遍。写有状态的代码时,要精通系统框架,否则一个电话把你叫过去通宵定位。

最近去麦当劳吃饭,发现从开始用触摸屏选择商品到最后拿着“挂号”到座位等餐,不用接触任何人,这是何等的变化。如果麦当劳全面推广,有多少人将会失业可想而知。在IT行业中,全面云化趋势已成,上面各种中间件既便宜又稳定,初级Java程序员/运维注定也像麦当劳的营业员一样失业,并将作为寡头的利润,为了不被淘汰,还是加紧看书吧。

REFFERENCE