之前很早的时候了解过这本书,但是发现很多都是概念性的东西,没有意向看。
后来在微博上看到一个我比较欣赏的架构师分享这本书,说是基本上涵盖了他过去十来年的一些点,于是打算买回来看了看。发现还是挺不错的,后面的案例有的过于宽泛,但是整体还是挺不错的。
架构一词,比较飘渺,隐藏在代码的背后,似有似无。大家对于架构师这个职位也褒贬不一。大型网站不是设计出来的,而是逐步发展演化过来的。
什么是架构?
最高层次的规划,难以改变的决定,这些规划和决定奠定了事物未来发展的方向和最终的蓝图。
什么是软件架构?
有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。
关于架构师?(发现问题,寻找突破;提出问题,寻求支持;解决问题,达成绩效)
关注人而不是产品,需找一个值得共同奋斗的目标,营造一个让大家都能最大限度发挥自我价值的工作氛围;
发掘人的优秀;
当大家不再讨论架构的时候,表明架构已经融入到项目、系统和开发者中了;
成就他人,做成一个项目不但要给客户创造价值,为公司盈利,还要让项目成员获得成长;
架构师最大的价值不在于掌握了多少先进的技术,而在于将一个大系统切分为N个低耦合的子模块的能力,这些子模块包含横向的业务模块,也包含纵向的基础技术模块,这种能力一部分源自于专业的技术和经验,还有一部分源自架构师对于业务场景的理解,对人性的把握,甚至对世界的认知。
大型网站软件系统的特点
- 高并发、大流量(这个不用说,要不也不叫大型网站了)
- 高可用(用户多,所以基本是要求7*24不间断服务了)
- 海量数据(用户行为中产生的数据必然会很多)
- 用户分布广泛,网络情况复杂(这个全国各地的网络情况确实比较复杂)
- 安全环境恶劣(由于面向的是公众的网络,所以各种安全问题应该都会有)
- 需要快速变更,发布频繁(这个。。。互联网公司的节奏一直比较快)
- 渐进式发展(在做的过程中可能需要多次试错和迭代)
大型网站架构演化过程
- 初始阶段,这个阶段可能应用服务器、文件服务器、数据库所有的资源都在同一台服务器上
- 应用服务器和数据库服务器拆分
- 使用缓存改善网站的性能(貌似互联网架构中,缓存是离不开的话题了)
- 使用应用服务器的集群来改啥网站的并发处理能力(不过一般是同构的集群,伪集群了)
- 数据库读写分离(由专门的机器提供写服务,专门的机器提供读服务,如果读写比例很大,可以多态读服务器)
- 使用反向代理和CDN加速网站响应(这两个原理都是缓存,CDN部署在网络提供商的机房,使用户在请求网站服务时,可以在距离自己最近的机房获得数据,反向代理则部署在网站的中心机房,当用户请求到达中心机房后,首先访问的服务器是反向代理服务器,如果反向代理服务器缓存用户的请求资源,可以直接返回给用户)
- 使用分布式文件系统和分布式数据库系统
- 使用NOSQL和搜索引擎
- 业务拆分(这个更多的是业务层面的规划了)
- 分布式服务(我简单划分可以使消息系统和同步的RPC调用,消息的话是异步的解决方案,RPC的话是同步的调用方案)
大型网站架构演变的价值观
- 随网站所需灵活应对
- 主要力量是网站的业务发展
- 不要一味的追求大公司的解决方案,场景为王
- 不要为了技术而技术,脱离业务场景的技术没有意义
- 不要企图用技术解决所有问题
架构的模式
- 分层,分层是应用系统中最常见的一种架构模式,在计算机世界中无处不在,可以更好的把庞大的软件系统切分成不同的部分,便于分工合作和维护。分层中的挑战就是合理规划层次的边界和接口,严格遵守分层的约束,禁止跨层次的调用以及逆向调用。
- 分割,分割在纵向层面对软件进行切分。比如网购系统,在应用层,分割为交易、物流、优惠、库存等系统。
- 分布式,分割和分层便于切分后的模块能够便于分布式部署。分布式应用和服务、分布式文件系统、分布式数据和存储、分布式计算、分布式配置、分布式锁。
- 集群,多台服务器部署相同的应用构成一个集群,保证负载均衡的同时来提升系统的可用性,互相灾备。
- 缓存,CDN、反向代理、本地缓存、分布式缓存、数据库缓存、浏览器缓存
- 异步,异步架构中最典型的就是生产者和消费者模式,要解耦,就用异步,异步离不开队列,有效的利用异步,能够消除并发访问的高峰。
- 冗余,在集群中机器数量达到一定数量的时候,部分机器宕机会是常态,因此需要数据冗余备份,数据库定期备份称之为冷备份,主从分离实时同步称之为热备份。
- 自动化,发布过程自动化、代码管理自动化、自动化测试、自动化安全扫描、自动化低级bug扫描、自动化监控、自动化报警、自动化失效转移、自动化降级。
- 安全,互联网开放的特性注定了在安全方面提升了很大的挑战。
好的设计绝对不是模仿,不是生搬硬套一个特定的模式,而是对问题深刻理解之上的创造和创新。
架构的要素
- 性能,性能是网站的一个重要指标
- 可用性,几乎所有的网站是要求7*24可用,能够达到四个九等
- 伸缩性,大量用户的高并发和存储海量数据,能否进行灵活的增减机器来应对流量的变化(应用服务器、缓存服务器、关系型数据库服务器、NOSQL服务器)
- 扩展性,在网站增加新的业务产品时,能否可以实现对产品透明无影响,功能之间耦合小,避免牵一发动全身,目前的主要手段是事件驱动(通常利用消息队列)和分布式服务
- 安全性,针对现存或者潜在的各种攻击与窃密手段,能否有可靠的应对策略
网站的高性能架构
不同角度下的网站性能
- 用户视角,在浏览器上直观的感受到网站响应速度
- 开发人员视角,响应延迟、系统吞吐量、并发处理能力、系统稳定性等指标
- 运维人员视角,基础设施性能和资源利用率
性能测试指标
- 响应时间,执行一个操作需要的时间
- 并发数,同时处理的请求数
- 吞吐量,单位时间内系统处理的请求数
性能测试的方法
- 性能测试(一个总称)
- 负载测试
- 压力测试
- 稳定性测试(系统在特定硬件、软件、网络环境条件下,持续运行一段时间是否稳定)
- 系统的最大负载点以及系统的崩溃点
Web前端性能优化
- 减少Http请求(http为无状态,每次请求需要重新建立通信链路)
- 使用浏览器缓存(通过设置HTTP头中的Cache-Control和Expires属性)
- 启用压缩,服务器端对文件进行压缩,在浏览器端对文件进行解压缩
- CSS放在页面最上面,js文件放在最下面(浏览器会在下载完所有的CSS之后才开始对整个页面渲染,加载JS后立即执行)
- 减少Cookie传输
- 使用CDN加速和反向代理加速
应用服务器性能优化
- 分布式缓存(优先使用缓存优化性能)
- 异步(消息队列具有很好的消峰作用,使用异步处理,将短时间的高并发产生的事务消息存储在消息队列中)
- 使用集群
- 代码优化
- 多线程(线程安全问题:使用无状态的对象、使用局部对象、并发访问资源添加锁)
- 资源复用(单例模式和对象池<对象创建比较耗时的情况下使用对象池能够提升性能>)
- 合理使用数据结构
- JVM中GC的优化
- 存储系统的性能优化
合理使用缓存
- 频繁修改的数据不适合使用缓存
- 没有热点的访问,数据缓存没有意义
- 数据的不一致和脏读
- 缓存的可用性
- 缓存如何预热
- 缓存穿透
服务器集群的Session管理
- Session复制
- Session绑定(又称为会话粘滞,利用负载均衡的源地址Hash算法实现,是一个用户的请求总是落在一台服务器上)
- 利用Cookie记录Session(收到Cookie大小的限制,同时会有安全隐患)
- Session服务器
如何构建高可用服务
- 分级管理(分组,做好资源的隔离)
- 超时设置(如果不知道设置多少,可以设置3S )
- 异步调用
- 服务降级
- 幂等性设计
- 数据备份
- 失效转移(失效确认、访问转移、数据恢复)
高可用网站的软件质量保证
- 自动化测试
- 预发布验证
- 自动化发布
- 灰度发布
网站运行监控(不允许没有监控的系统上线)
- 用户行为日志收集
- 服务端日志收集
- 客户端浏览器日志收集
- 服务器性能监控(系统Load、CPU使用率、磁盘IO、网络IO)
- 系统运行数据报告
- 系统报警
- 失效转移
- 自动化优雅降级
应用服务器集群的伸缩性设计(伸缩性设计几乎是稍微有点规模的网站的必须要求)
- HTTP重定向实现负载均衡
- DNS域名解析实现负载均衡
- 反向代理负载均衡(在HTTP协议层面,也叫应用层负载均衡)
- IP负载均衡(在内核进程完成数据分发,请求进入和请求返回,都会经过负载均衡服务器)
- 数据链路层实现负载均衡(三角传输模式,在请求进入经过负载均衡服务器,在请求返回的时候,直接返回给用户)
负载均衡的算法
- 轮训(RR)
- 加权轮训(在轮训的基础上,按照配置的权重将请求分发)
- 随机
- 最少连接(记录每个应用服务器正在处理的连接数,根据服务器当前的资源使用情况)
- 源地址散列(根据请求的IP地址进行Hash计算,这样同一个IP会在同一个服务器)
分布式缓存的伸缩性设计
(上线下线机器,对于整个缓存集群的影响最小)
一致性Hash算法,先构造一个长度为0到2的32次方的整数环,根据节点名称的hash值,将缓存服务器节点放置在Hash环上。
然后根据缓存数据的数据KEY的值计算得到hash值,然后在hash环上顺时针查找距离这个key的hash值最近的缓存服务器节点,从而完成key到服务器的hash映射查找。
在具体应用中,长度为2的32次方的Hash环通常使用二叉树查找来实现,二叉树查找是查找小于查找数的最小数值,树的最右边和最左边节点相连,构成环。
有个小问题,就是新加入节点3(原来有0、1、2三个节点),只影响到节点1,也就是说一部分原来需求访问1的缓存数据现在需要访问节点3,原来的0和2不受影响,这样的话0和2的缓存数据量和压力是1和3的两倍,这种问题咋解决呢?
使用虚拟层的手段,将每台物流缓存服务器虚拟为一组虚拟缓存服务器,将虚拟服务器的hash值放置在hash环上,key在环上先找到虚拟服务器的节点,再得到物流服务器的信息,最终的结果是,新加入一台缓存服务器,将会较为均匀的影响集群中已经存在的所有服务器。例如刚才讨论的问题,新加入的节点3,对应虚拟节点为V30、V31、V32,加入到一致性Hash环中,将影响V01、V12、V13,这三个虚拟节点对应0、1、2三体物理机,这样压力就会均摊。
扩展性和伸缩性的区别
扩展性是针对系统影响最小的情况下,系统功能可持续扩展或提升的能力。
伸缩性,系统通过增加或者减少自身资源规模的方式增强或者减少计算处理事务的能力。
利用消息队列降低系统的耦合性
- 事件驱动架构,通过在低耦合的模块之间传输事件消息,以保持模块的松散耦合,并借助事件消息的通信完成模块的协作,典型的生产者消费者模式
- 分布式消息队列,消息队列可以简单,比如mysql作为消息队列,也可以复杂,例如ESB(企业服务总线等)
利用分布式服务来打造可复用的业务平台
- webservice(通过WSDL来描述服务,通过SOAP来定义对象)
- 臃肿的注册和发现机制
- 低效的xml序列化手段
- 开销相对比较高的http远程通信
- 分布式服务的需求和特点
- 负载均衡(如何是TCP层面,可以做到软负载)
- 失效转移
- 高效的远程通信
- 整合异构系统
- 对应用最小侵入
- 服务版本管理
- 实时监控
- 服务降级
- 服务分组处理
- 服务流控处理(SLA)
- 按照机房等机型权重分发请求
网站的安全架构
- XSS攻击
- CSRF攻击
- SQL注入攻击
- 代码可能存在安全隐患扫描
- 线上日志监控和安全枚举回放日志
- 安全漏洞扫描
信息加密技术
- 单向散列加密(指通过对不同输入长度的信息进行散列计算,得到固定长度的输出,这个散列的过程是单向的)
- 例如常见的MD5
- 输入的任何微小变化可能导致结果完全不同
- 对称加密(加密和解密使用的密钥是同一个)
- 特点是算法简单,加密解密效率高,系统开销小
- 缺点是使用同一个密钥,有安全隐患
- 例如DES算法和RC算法
- 非对称加密(加密和解密不是用一个密钥,例如RSA算法)
- 信息安全传输
- 发送者A通过公开途径获得信息接受者B的公钥,对信息进行加密,然后通过非安全的通道把密文发送给B
- B得到密文之后,用自己的私钥解密,获得明文信息
- 数字签名 (和信息安全传输相反)
- 签名者用自己的私钥对信息进行加密,然后发送给对方
- 接收方用签名者的公钥对信息进行解密,获得明文信息,
- 由于私钥只有签名者拥有,信息具有不可抵赖性,具有签名的性质
- 常用的算法有RSA,HTTPS中传输的浏览器使用的数字证书实质上是经过权威机构认证的非对称加密的公钥
- 信息安全传输
一些常见的大型网站的故障案例
- 写日志引发的故障
- 注意日志的级别
- 应用程序自己的日志输出配置和第三方组件的日志输出分别配置
- 高并发引发数据库访问的故障
- 数据库做好监控
- 如果并发特别高的页面,使用缓存,切记不要使用数据库
- 高并发下锁引发的故障
- 例如一个单例对象中多处使用了synchronized,这样所有的并发请求都要排队获得唯一的一把锁
- 在使用锁的时候一定要慎重啊
- 缓存引发的故障
- 缓存在提升性能的同时,在数据的一致性和系统的可运维性方面带来了很大的挑战
- 线上的生产环境要敬畏,不要随便操作
- 发布过程中要注意流程和监控,发现问题及时回滚处理
http://blog.csdn.net/dananhai381/article/details/38085611