本文 首发于 🌱 煎茶转载 请注明 来源

大型网站技术架构 李智慧 95个笔记

◆ 第1篇 概述

网站访问特点和现实世界的财富分配一样遵循二八定律:80%的业务访问集中在20%的数据上。

网站使用的缓存可以分为两种:缓存在应用服务器上的本地缓存和缓存在专门的分布式缓存服务器上的远程缓存。

当一台服务器的处理能力、存储空间不足时,不要企图去换更强大的服务器,对大型网站而言,不管多么强大的服务器,都满足不了网站持续增长的业务需求

恰当的做法是增加一台服务器分担原有服务器的访问及存储压力。

数据库经过读写分离后,从一台服务器拆分成两台服务器,但是随着网站业务的发展依然不能满足需求,这时需要使用分布式数据库

文件系统也是一样,需要使用分布式文件系统

分布式数据库是网站数据库拆分的最后手段,只有在单表数据规模非常庞大的时候才使用

不到不得已时,网站更常用的数据库拆分手段是业务分库,将不同业务的数据库部署在不同的物理服务器上

NoSQL和搜索引擎都是源自互联网的技术手段,对可伸缩的分布式特性具有更好的支持

应用服务器则通过一个统一数据访问模块访问各种数据,减轻应用程序管理诸多数据源的麻烦。

大型网站架构技术的核心价值不是从无到有搭建一个大型网站,而是能够伴随小型网站业务的逐步发展,慢慢地演化成一个大型网站。

网站技术是为业务而存在的,除此毫无意义

如果能控制住并发访问的量,很多棘手的技术问题也就不是什么问题了

能亲身经历一个网站从小到大的架构演化过程的网站架构师越来越少,虽然过去有这种经历的架构师也很少(从小型网站发展成大型网站的机会本来就极少),但是将来可能真就没有了

模式的关键在于模式的可重复性,问题与场景的可重复性带来解决方案的可重复使用。

在大型网站架构中也采用分层结构,将网站软件系统分为应用层、服务层、数据层

计算机软件发展的一个重要目标和驱动力是降低软件耦合性。

系统分为三个层次,最下层是基础服务层,提供数据库、缓存、存储、搜索等数据服务,以及其他一些基础技术服务

中间层是平台服务和应用服务层

最上层是API和新浪微博的业务层

性能、可用性、伸缩性、扩展性和安全性是网站架构最核心的几个要素,这几个问题解决了,大型网站架构设计的大部分挑战也就克服了

◆ 第2篇 架构

性能测试是一个总称,具体可细分为性能测试、负载测试、压力测试、稳定性测试

为了保证数据的高可用,网站通常会牺牲另一个也很重要的指标:数据一致性

CAP原理认为,一个提供数据服务的存储系统无法同时满足数据一致性(Consistency)、数据可用性(Availibility)、分区耐受性(Patition Tolerance,系统具有跨网络分区的伸缩性)这三个条件

失效转移操作由三部分组成:失效确认、访问转移、数据恢复。

在网站应用中强调的一个处理错误的理念是快速失败(fast failed),即如果系统在启动时发现问题就立刻抛出异常,停止启动让工程师介入排查错误,而不是启动后执行错误的操作。

很多网站选择周四作为发布日,这样一周前面有三天时间可以准备发布,后面还有一天时间可以挽回错误。如果选择周五发布,发现问题就必须要周末加班了。

计算机领域有句话:计算机的任何问题都可以通过增加一个虚拟层来解决

NoSQL,主要指非关系的、分布式的数据库设计模式

全球大约70%的Web应用攻击都来自XSS攻击和SQL注入攻击

常用的Web应用还包括CSRF、Session劫持等手段

XSS攻击即跨站点脚本攻击(Cross Site Script),指黑客通过篡改网页,注入恶意HTML脚本,在用户浏览网页时,控制用户浏览器进行恶意操作的一种攻击方式

注入攻击主要有两种形式,SQL注入攻击和OS注入攻击

HTTP请求头的Referer域中记录着请求来源,可通过检查请求来源,验证其是否合法。

如果上传的是可执行的程序,并通过该程序获得服务器端命令执行能力,那么攻击者几乎可以在服务器上为所欲为,并以此为跳板攻击集群环境的其他机器

攻击者在请求的URL中使用相对路径,遍历系统未开放的目录和文件

信息加密技术可分为三类:单项散列加密、对称加密和非对称加密

单向散列加密是指通过对不同输入长度的信息进行散列计算,得到固定长度的输出,这个散列计算过程是单向的

为了加强单向散列计算的安全性,还会给散列算法加点盐(salt),salt相当于加密的密钥,增加破解的难度。

常用的单向散列算法有MD5、SHA等

输入的任何微小变化都会导致输出的完全不同

所谓对称加密是指加密和解密使用的密钥是同一个密钥(或者可以互相推算)

对称加密的优点是算法简单,加解密效率高,系统开销小,适合对大量数据加密

缺点是加解密使用同一个密钥,远程通信的情况下如何安全的交换密钥是个难题

常用的对称加密算法有DES算发、RC算法等

不同于对称加密,非对称加密和解密使用的密钥不是同一密钥,其中一个对外界公开,被称作公钥,另一个只有所有者知道,被称作私钥

用公钥加密的信息必须用私钥才能解开,反之,用私钥加密的信息只有用公钥才能解开

非对称加密技术通常用在信息安全传输,数字签名等场合。

由于私钥只有签名者拥有,因此该信息是不可抵赖的,具有签名的性质。

非对称加密的常用算法有RSA算法等。HTTPS传输中浏览器使用的数字证书实质上是经过权威机构认证的非对称加密的公钥。

Trie算法的本质是确定一个有限状态自动机,根据输入数据进行状态转移

另一种更简单的实现是通过构造多级Hash表进行文本匹配

◆ 第3篇 案例

合适的场景下使用合适的产品,而不是最好的产品,所谓小脚穿大鞋,不但跑不快,还可能会摔跤

所谓网站前端是指应用服务器(也就是PHP服务器)之前的部分,包括DNS服务、CDN服务、反向代理服务、静态资源服务等

在反向代理Squid之前,则是被Wikipedia技术团队称为“圣杯”的CDN服务

每个内容页面有唯一的REST风格的URL,以便CDN快速查找并避免重复缓存。

他的意思大概是在互联网公司一年遇到的问题比传统软件公司三年遇到的问题还多

遇到问题,解决问题,经历了这个过程,技术才能升华,人和技术才能融为一体,才知道什么技术是真正有用的,什么技术是花拳绣腿。

所以培养一个网站架构师的成本不单要看付了他多少薪水,给了他多少股票,还要看为他引起的故障买了多少次单。

网站还有很多类似的场景,都需要后台服务准备好,前台应用才能启动,否则就会导致故障。这种情况被内部人戏称作“姑娘们还没穿好衣服,老鸨就开门迎客了”

在应用程序中加入一个特定的动态页面(比如只返回OK两个字母),启动脚本先启动JBoss,然后在脚本中不断用curl命令访问这个特定页面,直到收到OK,才启动Apache。

存储的使用需要根据不同文件类型和用途进行管理,图片都是小文件,应该使用专用的存储服务器,不能和大文件共用存储。批处理用的大文件可以使用其他类型的分布式文件系统。

程序在处理一个输入的对象时,如果不能明确该对象是否为空,必须做空指针判断

程序在调用其他方法时,输入的对象尽量保证不是null,必要时构造空对象(使用空对象模式)。

有位软件技术前辈曾经说过“软件设计有两种风格,一种是将软件设计得很复杂,以使其缺陷没那么明显;一种是将软件设计得很简单,以使其没有明显的缺陷”。

吃一次亏,学一次乖,以后设计软件时就会设计得简单些,如果问题能够很快被发现,要解决也相对容易。

◆ 第4篇 架构师

处理好人的关系对架构和项目的成功至关重要。

一定要坚信:一群优秀的人做一件他们热爱的事,一定能取得成功

最好的软件项目管理不是制订计划,组织资源,跟踪修正项目进展,对成员进行激励和惩罚,而是发掘项目组每个成员的优秀潜能,让大家理解并热爱软件产品最终的蓝图和愿景。

一旦做到这一点,项目组每个成员都会自我驱动,自觉合作,寻找达成目标的最优路径并坚韧不拔地持续前进

领导的真谛:寻找一个值得共同奋斗的目标,营造一个让大家都能最大限度发挥自我价值的工作氛围

所有强迫员工加班的管理者都应该为自己的无能而羞愧。

是事情成就了人,而不是人成就了事。

指望优秀的人来帮自己成事,不如做成一件事让自己和参与的人都变得优秀。

发掘人的优秀远比发掘优秀的人更有意义。

蓝图应该是表述清楚的:产品要做什么、不做什么、要达到什么业务目标,都需要描述清楚。

蓝图应该是简单的:不管内部还是外部沟通,都能一句话说明白:我们在做什么。

蓝图应该写在软件架构设计文档的扉页、写在邮件的签名档、写在内部即时通信群的公告上

不要企图去证明自己了不起,永远也别干这种浪费时间、伤害感情的事。

提醒自己是来做软件的,来实现客户价值的,不是来证明谁对谁错的,不是来给黑熊XX的。

新员工首先要做的事情是融入团队,跟大家打成一片,只要能和团队一起共进退,你就不是一个人在战斗。等熟悉了情况,知道了水的深浅后,再寻找突破口,择机而动。

新员工最不需要做的事情就是证明自己的能力

软件开发出来,如果没有投入使用,就一点价值也没有,不管架构设计和代码实现多优美都没用。

做出软件不等于解决问题,事实上很多问题确实也不需要用软件来解决。

如果你需要他的支持,就要想办法把你的问题变成他的问题,是他遇到了问题,而你来帮他解决

给上司提封闭式问题,给下属提开放式问题

如果在合作中出现问题,告诉他问题的存在和紧迫性,而不是责问他为什么出现问题

人在听到批评信息的时候,本能地想要去针对批评进行反驳或者辩解,于是谈话就变成关于批评是否合理的争论,离解决问题越来越远

在解决我的问题之前,先解决你的问题

◆ 附录B Web开发技术发展历程

随着CGI(Common Gateway Interface,通用网关接口)技术的出现,Web服务端可以根据不同用户请求产生动态页面内容

早期主要的CGI编程语言是Perl

CGI程序擅长处理请求信息,而服务器页面擅长构造响应页面,那么能不能将两者结合起来呢?答案就是MVC(模型-视图-控制器)模式

Web开发中通常将服务端划分为三层:表现层、业务逻辑层和数据源层

表现层完成视图展现和用户交互;业务逻辑层实现系统的核心逻辑;数据源层负责数据存储、交换和通信

◆ 后记

不要企图去设计一个大型网站