高并发、大流量
高可用
海量数据
用户分布广泛、网络情况复杂
安全环境恶劣
需求快速变更、发布频繁
渐进式开发
1. 初始阶段:
应用程序、数据库、文件都在一台服务器,如常用的Linux+PHP+Apache+Mysql
2. 应用服务和数据库分离
原因:性能变差、存储空间不足
三台服务器:应用服务器(运算能力:CPU)、文件服务器(更大的存储)和数据库服务器(更大的存储和内存)
3. 使用缓存改善
原因:数据库访问压力太大; 数据访问遵循2-8定律
将访问多的20%的数据放在缓存上,可分为应用服务器端的本地缓存和分布式的远端缓存
4. 应用服务器集群
原因:单一服务器处理的请求链接成为瓶颈
使用应用服务器集群,使用反向代理实现负载均衡、可用性监测、可伸缩的实现
5. 数据库读写分离
原因:使用缓存后,仍有部分读操作和全部写操作要访问数据库,随着规模的增大,这些操作造成数据库瓶颈
数据库进行主从备份和读写分离
6. 使用反向代理和CDN加速网站响应
原因:加速网站访问速度
CDN: 部署到客户端最近的网络提供商的机房,用户可从自己最近的网络提供商获取数据,多用于静态内容如CSS、图片等
反向代理:一般代理都是在客户的浏览器端,而此处的代理是在网站端。 用户请求先通过反向代理,反向代理如果缓存有用户需要的资源则立刻返回,否则调用相应服务器
7. 使用分布式文件系统
原因:业务需求继续增大
8. 使用分布式数据库
分库:
分表:单表数据规模非常庞大时
9. 使用NoSQL和搜索引擎
特点:数据存储和检索越来越复杂
NoSQL对可伸缩的分布式特性有很好的支持
10. 业务拆分
将网站拆分成多个应用,每个应用独立维护
11. 分布式服务
将共有业务(用户管理、商品管理等)提取出来独立部署,上层业务复用这些业务完成具体操作
将系统分成MVC层,对C进一步分成service层和Dao层
注意:定义好层次边界和接口
作用:便于合作开发和维护;方便分离部署
对业务进行拆分,彼此之间低耦合,然后部署到单独的应用服务器上
分层和分割的主要目的就是为了切分后的模块便于分布式部署
常用方案有:
1. 分布式应用与服务:改善性能和复用
2. 分布式静态资源:如JS,CSS独立部署并有独立的域名
3. 分布式数据和存储:对传统数据库使用分布式、采用NoSQL
4. 分布式计算:MapReduce
在多个机器上部署单一模块,提供扩展性、有效性、负载均衡的处理
条件:某些数据被频繁访问;数据在某个时间段内有效,不会很快过期
有以下方式:
CDN:离用户最近,静态资源
反向代理:网站的前段,静态资源等
本地缓存:应用服务器本机
分布式缓存
使用消息队列实现,单一应用服务器使用多线程之间的消息队列实现异步;分布式环境中使用分布式的消息队列实现异步
好处:降低耦合;加快响应速度;消除并发访问高峰
实现7*24小时服务,提高可用性
服务器集群实现; 数据库的冷、热备份
发布过程:自动化代码管理、自动化测试、自动化部署、自动化安全检测
运行过程:自动化监控、自动化报警、自动化失效转移和回复、自动化降级
身份认证: 密码和手机校验码
加密:登录、交易和存储的敏感数据
验证码:机器人程序攻击网站
编码转换:XSS攻击和Sql注入
过滤:垃圾信息和敏感信息
风险控制: 对交易转账等重要操作根据交易模式和交易信息进行
定义:用户访问的快慢
评价指标:响应时间,TPS,系统性能计数器
手段:
1. 浏览器端:页面压缩、浏览器缓存、合理布局页面、减少cookie传输、CDN、CSS放在上面和js放在最下边
2. 应用服务器端:反向代理服务器、缓存、异步请求、集群
3. 代码层:多线程、改善内存管理
4. 数据库端:索引、缓存、SQL优化、主从备份和读写分离、NoSQL数据库
定义:可以访问的时间
评价指标:几个9,如99.99%
手段:
1. 冗余(应用服务器集群、数据库备份)
2. 软件质量:预发布验证、自动化测试、自动化发布、灰度发布
定义:通过向集群中加入服务器提高并发访问和数据存储需求
评价指标:是否容易添加新的服务器;新的服务器能否提供无差别服务;服务器数量是否有限制
手段:
1. 应用服务器集群:服务器上不保存数据(无状态)+合适的负载均衡设备
2. 缓存集群:改进缓存路由算法:hash环
3. 数据库集群:路由分区将部署有多个数据库的服务器组成一个集群; NoSQL数据库天生比较好
定义:快速响应需求变化
评价指标:增加新业务,是否对现有产品透明无影响
手段:
1. 事件驱动:消息队列实现
2. 分布式服务:业务通过分布式框架调用可复用服务
定义:现存和潜在攻击手段的应对策略
1)用户视角
浏览器和服务器通信时间+处理时间+浏览器解析响应数据的时间
2)开发人员视角
应用程序本身和子系统的性能,有 响应时间、吞吐量、并发处理能力、系统稳定性等指标
3)运维人员视角
关注基础设施性能和资源利用率,如网络带宽利用率和服务器资源利用率等
手段:建设优化骨干网、定制的服务器、使用虚拟化技术优化资源利用率
响应时间:
执行一个操作需要的时间
测量方法:重复请求,如一个请求重复执行1万次,求得单次平均访问时间
并发数:
同时访问的请求数量
测量方法:模拟并发用户,在两次请求之间加入随机等待时间(思考时间)
吞吐量:
单位时间内处理的请求数量,TPS(每秒事务数)
并发小:吞吐量增加、响应时间小幅上升;并发逐渐增加:吞吐量下降、响应时间快速上升;并发达到崩溃点:吞吐量为0,不响应
性能计数器
描述服务器和操作系统性能的数据指标,如System Load(进程数和CPU数)、内存和CPU使用、对象与线程数
性能测试:以系统规划初期的指标测试
负载测试:增加并发请求,直到多项性能指标达到临界值
压力测试:直到系统崩溃
稳定性测试:特定软硬件条件下,给系统加载一定业务压力,使系统运行一段时间
性能分析: 检查各环节日志——》检查监控数据,关注内存、磁盘、网络、CPU——》确定是代码问题、架构设计还是系统资源不足
1. 减少http请求
合并javascript css、图片(如果每张独有不同的超链接,可通过css偏移响应鼠标点击操作,构造不同的URL)。
2. 使用浏览器缓存
设置http头中的Cache-Control和Expires设定浏览器缓存
静态文件变化后:改变js文件名并更新html文件中的引用
更新静态资源时,采用批量更新的方法,比如更新10个图标文件,应一个文件一个文件逐步更新,并有一定时间间隔
3. 启用压缩
可对html css javaScript启动GZip压缩,但会对服务器产生压力
需要在 通信和服务器资源间权衡考虑
4. CSS放在页面最上面,JavaScript放在最下面
浏览器会在下载完全部CSS后才进行页面渲染,最好是把CSS放在页面上边
浏览器在加载Js后立刻执行,有可能阻塞整个页面,因此js放在下面,但如果页面解析时就要用到JavaScript的,放在下面就不太合适了
5. 减少cookie传输
静态资源使用独立域名,避免发送cookie
哪些数据需要写入cookie要慎重考虑
用于对静态资源的代理
部署在应用服务器前边,实现 安全过滤、缓存加速web请求、负载均衡
主要手段有缓存、集群和异步
网站优化第一定律:优先考虑缓存优化
缓存实际是内存的hash表
1. 合理使用缓存:
1)频繁修改的数据:读写比在2:1以上
2)没有热点的访问
3)数据不一致和脏读:设置失效时间、数据更新时立即更新缓存
4)缓存可用性
5)缓存预热:新缓存上没数据
6)缓存穿透:持续高并发地请求某个不存在的数据,会对数据库造成很大压力
2. 分布式缓存架构
使用消息队列:减少响应延迟、平滑并发访问波动;
需要对返回状态做特殊处理,如订单提交(等待消费者处理完后才显示成功)等
1. 多线程
使用原因:IO阻塞会释放CPU; 多CPU每个对应一个
多少线程: 启动线程数=【任务执行时间/(任务执行时间-IO等待时间)】*CPU数
线程安全问题:对象是无状态的;使用threadLocal 方法内对象;并发访问资源时加锁
2. 资源复用
开销很大的资源,如数据库连接、网络连接、线程、复杂对象。有两种模式:单例和对象池
3. 数据结构
字符串Hash散列算法:Time33算法: hash(i)=hash(i-1)*33+str[i]
相似的字符串hash值区别很大: MD5算法
4. 垃圾回收
有助于程序优化和参数调优,分为stack和heap,堆空间分为Young Generation(Eden from to)和Old Generation,新建对象在Eden,当Eden满时,复制到from;Eden又满了,将Eden和from——》to,下次Eden+to——》from,young都满了就放到old,如果都满了就触发Full GC(时间比较长)
合理设置young 和 old大小,尽量减少Full GC
可用性度量: 几个9,如99.99%
可用性考核(对工程师的考核): 故障时间*故障权重
企业级采用昂贵的软硬件,如IOE;互联网更多是PC级服务器、开源的数据库和操作系统
主要手段:数据和服务的冗余备份和失效转移。
1. 无状态应用服务器
采用负载均衡软件,一般都提供:心跳检测可用性;失效转移、负载均衡
2. 有状态的应用服务器
1)session复制:当服务器集群规模下的时候可用。通过开启web容器的session复制功能,让每台服务器上都有用户session信息。 应用在集群规模小的情况下。
2)session绑定:使用负载均衡软件的源地址hash算法,保证同一IP的处理总在一台服务器上。但使用较少,主要是可用性的问题,如果该机器done了,该用户的session会丢失
3)cookie记录session:1)cookie大小限制;2)每次都要传输;3)关闭cookie访问不正常;4)简单易用;5)支持应用服务器的线性伸缩。 大部分网站或多或少使用。
4)session服务器: 可用性高,伸缩性好,性能也不错,信息大小又没限制。 将服务器中session都放到独立的session服务器统一管理,每次读写session时,都通过session服务器。通过对分布式缓存、数据库基础上包装实现。
1. 分级管理: 对不同的功能模块进行分级,对于高优先级使用好的硬件,更快的相应速度;等访问量大时,可关闭低优先级功能
2. 超时设置: 设置调用的超时时间,当服务不可用或超时后,通信框架报出异常,根据调度策略转移到其他服务器
3. 异步调用:消息队列
4. 服务降级:访问高峰期,拒绝低优先级服务
5. 冥等性设计:请求重新发送时,保证统一请求重复调用和一次调用结果相同,比如转账(使用交易编号)
1. 冷备: 廉价; 不能保证数据一致性;可用来定期备份
2. 异步热备:只写成功一份,其他之间复制
3. 同步热备:同时向多个副本中写入
4. 失效转移:失效确认(心跳检测和访问异常)——》访问转移——》数据恢复
5. 库表散列: 不同业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者功能进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。
1. 网站发布
每次关闭服务器集群中的一小部分,发布完后立刻可以访问。
使用发布脚本实现
2. 自动化测试
Selenium 自动化测试技术
3. 预发布验证
4. 代码控制
要求:发布版本和开发版本互不影响
主干开发、分支发布:发布时主干出一个branch,如果该版本有bug,在分支上修改发布,并将修改merge回主干
5. 自动化发布
6. 灰度发布
每天只发布一部分服务器,观察运行稳定没有故障
1. 数据采集
用户行为日志收集:服务器端(web服务器)、客户端(javascript)
性能监控
运行数据报告
统计:基于实时计算框架Storm的日志统计和分析工具
2. 监控管理
系统报警
主动失效转移
自动优雅降级
伸缩性:当访问量增加时,通过增加资源(服务器)可以提高吞吐率
伸缩性设计是复杂的、没有通用的、完美的解决方案
一台服务器——》数据库分离——》缓存分离——》静态资源从应用服务器分离
纵向分离(按层分割):网络具体产品--可复用业务服务--基础技术服务--数据库
横向分离(业务分割):网站前台--买家前台--卖家后台
条件:当随着访问量增大,即使分离到最小粒度的独立部署,单一服务器也不能满足需要
1. 如果是无状态的,可以使用负载均衡(请求分发,服务器可用性监测)
2. 负载均衡实现技术有:
1. http重定向: 使用http request将用户请求重新定向到处理服务器,优点是简单;缺点是两次请求才能完成一次访问,性能较差。重定向服务器可能成为系统瓶颈。 http302会被搜索引擎判定为作弊。 实际使用中不多见
2. dns域名解析:在DNS中实现负载均衡。优点是负载均衡给了DNS实现简单。可以解析到用户最近的服务器地址;缺点是当下线了某台服务器不能立即反应。 实际中大型网站使用DNS作为第一级负载均衡,到同样提供负载均衡的内部服务器
3. 反向代理: 反向代理服务器提供缓存资源、负载均衡的功能,需要部署双网卡和双ip,优点是 和反向代理功能一起部署比较简单。缺点是反向代理服务器是所有请求和响应的中转站,性能可能成为瓶颈
4. IP负载均衡:负载均衡服务器修改数据包中的目的IP地址实现。优点较反向代理有更好的处理性能;缺点是所有请求都经过,数据吞吐量受限于网卡带宽
5. 数据链路层负载均衡:修改mac地址实现。使用最广,linux平台使用LVS(Linux Virtual Server)
3. 负载均衡算法
轮询:请求依次分发
加权轮询:根据服务器的硬件情况加权
随机:好的随机数本身就很均衡,如果硬件配置不同,可使用加权随机
最少链接:记录每个服务器的连接数,新的请求分配到最少的
源地址散列:对IP进行散列,使得该IP的上下文信息存储在这台服务器上,实现会话粘滞
1. 目标: 新加入的缓存使得已缓存的数据尽可能能被访问到
2. memchached 分布式缓存集群,其中路由算法很重要:
1. 余数hash: 缓存数据hashcode/服务器数目。 但添加新的缓存服务器就麻烦了,解决方案是 使用虚拟节点的一致性hash环
1. 目标:相对于缓存,对数据的持久性(能存到硬盘)和可用性(能访问到数据)要求更高
2. 关系型数据库
数据库复制: 主从读写分离; 分库(不同表在不同数据库集群,缺点是不能进行跨库join); 分表(产品有Amoeba和Cobar,Cobar可与mysql集群使用)
伸缩的实现:Corba的服务器使用负载均衡;Mysql(Cobar利用Mysql的数据同步功能进行数据迁移)
无法执行跨库Join和事务
避免事务或利用事务补偿机制(分布式事务)代替数据库事务;分解数据访问逻辑避免JOIN操作
支持JOIN的,如GreenPlum,但延迟比较大
3. NoSql数据库
Apache 的HBase,依赖于可分裂的HRegion(数据块)和HDFS(分布式文件系统)。使用者无需处理
扩展性: 对现有系统影响最小情况下,可以加功能,符合开闭原则
软件架构师最大的价值不是掌握多少先进技术,而在于具有将一个大系统切分成N个低耦合的子模块的能力,这些子模块包括横向模块和纵向模块。这种能力是专业的技术和经验,对业务场景的理解,对人性的把握。
核心思想是模块化,并在此基础上,降低模块间的耦合性
主要手段是分层和分割,模块间通过分布式消息队列和分布式服务聚合
借助事件完成模块间合作,常见的是生产者消费者模式,最常用的分布式消息队列
好处是:更好的响应延迟;平缓高峰压力;
ActiveMQ:除了实现分布式消息队列,在伸缩性(加入队列服务器)和可用性(内存队列满后,写入磁盘)也做了改善。
避免系统当机造成消息丢失,会把发送成功的消息存储在生产者服务器,等消息被消费者处理后才删除消息。
纵向拆分:将一个大应用拆分为多个小应用,部署为单独的web系统
横向拆分:将复用业务拆分后部署为分布式服务,新增业务调用这些服务
纵向比较简单,通过梳理业务将较少相关的业务剥离,使其成为独立的web应用。横向不仅要识别可复用的业务,设计服务接口,规范依赖关系,还需要一个完善的分布式服务管理框架。
可整合异构系统和构件分布式系统
缺点: 臃肿的注册和发现机制;低效的xml序列化;开销相对较高的HTTP远程通信;复杂的部署和维护手段。
服务注册和发现
服务调用
负载均衡:对热门服务如登录或商品服务,需要部署在集群上
失效转移
高效的远程通信
整合异构系统
对应用最少侵入:尽量使框架和业务独立
版本管理:提供者升级接口发布新版本服务,并同时提供旧版本服务,当请求者调用接口升级后才关闭旧版本服务。
开源的阿里的Dubbo
描述:
1. 消费者通过服务接口调用服务,服务接口通过代理加载服务,代理调用服务框架客户端模块,客户端包括服务提供者列表、负载均衡、失效迁移服务
2. 提供者提供服务管理容器注册服务
3. 支持多种通信协议和序列化协议,使用NIO通信框架,具有较高的网络通信性能
无需修改表字段就可以新增字段,使用NoSql数据库
提供更多的增值服务,将API开放被第三方开发者使用
跨站点脚本攻击,有两种,一种是反射性(在url中 ?<script src... >),一种是持久型XSS(将恶意脚本的请求保存到数据库中,常用语论坛和博客)
防范手段: 消毒(对提交的文本进行匹配替换,如<img src= 对<进行转义); HttpOnly(防止xss窃取cookie,即浏览器禁止页面Javascript访问带有HttpOnly的cookie)
需要对数据库有所了解,通过开源(网站使用开源软件搭建);错误回显(从错误信息猜测表结构);盲注(猜测数据库表结构)
防范手段:消毒(可能注入的sql,如drop table delete from等);参数绑定(PrepareStatement, ?而不是链接字符串)
跨站点请求伪造:通过跨站请求,以合法用户身份进行非法操作
关键是识别请求者身份,防范手段:
表单token、
验证码(糟糕的用户体验,只在必要时使用,如支付交易);
Referer check(检查http请求头的referer的请求来源,可用来实现图片防盗链)
Error code:获得异常信息,查找系统漏洞; 防范手段:专门的错误页面
html注释: 发布前自动扫描,去除html注释
文件上传:防范手段:设置上传文件白名单,只允许上传可靠的文件类型;修改文件名;使用专门的存储
路径遍历:在url中使用相对路径;防范手段:动态参数不包括文件路径信息;其他文件不适用静态URL访问
处理网站攻击的产品,开源的Web应用防火墙:ModSecurity
根据内置规则,构造具有攻击性的URL请求模拟黑客攻击行为
1. 单向散列加密
不能逆转得到明文,字符串微小差别输出差别很大,不同长度输入得到固定长度的输出
常用的有MD5 SHA
用于密码加密保存、生成信息摘要
2. 对称加密
算法简单,效率高,系统开销少,适合对大量数据加密;使用同一秘钥,远程通信下如何安全交换秘钥是个难题
常用的有DES RC
用于信息需要安全交换或存储的场合,如Cookie加密、通信加密等
3. 非对称加密
用于信息安全传输、数字签名。
在实际中,常会混合使用对称加密和非对称加密。先使用非对称对秘钥进行安全传输,再使用对称进行信息加密和交换。 有时对一个数据两次使用非对称加密,可同时实现信息安全传输与数字签名的目的。
4. 秘钥安全管理
写到配置文件,线上和线下使用不同的
加密算法放在应用系统中,秘钥放在一个独立的服务器,甚至做成一个专用的硬件设施
秘钥分片后存储在多个服务器
1. 文本匹配
敏感词过滤: 正则表达式(敏感词较少、提交的文本长度较短);Trie树(敏感词较多、提交的文本长,如双数组Trie算法);多级Hash表(Trie中相同父节点的字放在Hash表中, 速度较快,浪费部分内存)
2. 分类算法
数据挖掘:分类算法, 贝叶斯算法
3. 黑名单
hash表,布隆过滤器
1. 风险
2. 风控
规则引擎: 将业务规则和规则处理分开,业务规则可配置
统计模型:数据挖掘分类算法(当规则增加,出现规则冲突、难以维护时)
目标:业务简单,大部分是读操作
GeoDNS:将域名解析到离用户最近的服务器
LVS:Linux的开源负载均衡服务器
Squid:Linux的开源反向代理服务器
Lighttpd: 开源的应用服务器,更快速,更轻量,许多网站作为图片服务器
1. 前端优化
请求先经过GeoDNS到达地理最近的CDN服务器,如果没找到调用LVS到Squid服务器,如果缓存有则返回,否则通过LVS分发到Apache应用服务器集群。
2. 服务端优化
代码和数据结构(非特定)
3. 数据端优化
最主要手段是缓存,策略如下
1. 热点特别集中的数据缓存到应用服务器的本地缓存
2. 缓存数据尽可能是直接可用格式,如HTML格式
3. 使用缓存服务器存储session对象
4. 数据库如下优化
1. 更大内存
2. Master当机,关闭写功能,将应用切换到Slave
1. 对原有业务形成冲击
2. 高并发下数据库、应用负载
3. 突然增大的服务器和网络带宽
4. 防止秒杀前下单
1. 独立部署
和原有业务部署在不同服务器,防止高并发拖垮整个网站
2. 页面静态化
将商品详情、描述静态化到页面
3. 租借秒杀网络带宽
向运营商租借带宽
4. 动态生成随机下单页面URL
无法在秒杀前访问下单页面的URL:加入服务器端生成的随机数作为参数,在秒杀开始前才能得到
1. 控制秒杀购买页面的点亮
秒杀商品页面加入一个javascript引用,该javascript中加入秒杀是否开始的标志和下单页面URL的随机数参数,该javascript使用随机版本号,不可被浏览器缓存
当秒杀开始时,生成一个新的javascript文件并被用户浏览器加载
2. 允许第一个订单提交
控制进入下单页面入口,只有先提交的少数用户可进入,后边的用户直接进入秒杀结束页面
架构设计、软件开发
承担一些管理职能:规划产品路线、估算人力资源和时间资源
安排人员职责分工,确定计划里程碑点、指导工程师工作、过程风险评估与控制
与组内外各种角色沟通
首先要做的是融入团队,和大家打成一片。等熟悉情况后,知道了水的深浅,再寻找突破口,择机而动
新员工最不需要做的就是证明自己的能力
对于问题,找到谁需要对可能发生的问题负责。要解决方案被接受,就必须找到问题负责者并愿意支持他的人
1. 把我的问题表述成我们的问题
2. 给上司提封闭式问题,给下属提开放式问题
给上司提问题是希望得到支持,给下属提问题是为了启发他思考
3. 指出问题而不是批评人
在合作中出现问题,告诉问题存在和紧迫性
4. 用赞同方式提出问题
我非常赞同你的方案,不过我有一个小小的建议
1. 在解决我的问题前,先解决你的问题
在帮别人解决问题的过程中,熟悉了情况,解决自己的问题就得心应手了
2. 适当的逃避问题
对于不怎么靠谱的问题和方案: 这个idea很好,改天组织个会议好好讨论下