架构概念
一套系统的软件架构就是这个系统所需的结构体的集合,包括:软件元素,软件元素之间的关系,以及二者的属性。 从视角不同一般分为:
- 逻辑架构
关注于各个组件之间的关系,如:用户界面、数据库、外部系统接口。主要面向的是业务逻辑,也是架构设计中容易被初涉架构的架构师所忽略的核心。
如流行的N层架构:表现层,业务逻辑层,数据层。 - 物理架构
关注于如何将软件元素放到物理设备上,如:代理服务器、Web服务器,缓存服务器、数据库服务器、NoSQL服务器、队列服务器、搜索服务器。 - 系统架构
性能、可扩展性、伸缩性、可用性、安全性
有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。
在平衡性能、扩展性、伸缩性、可用性、安全性这5个系统架构要素下,实现系统功能需求。
架构模式
为了应对高并发访问、海量数据处理、高可靠运行等一系列问题,大型互联网公司在实战提了许多解决方案,以实现网站的高性能、高可用、易伸缩、可扩展、安全等各种技术架构目标,这些解决方案可以被重复使用,从而被抽炼成为大型网站的架构模式
分层
应用层 - 服务层 - 数据层 应用层:视图层 业务逻辑层 服务层:数据接口层 逻辑处理层 分层是逻辑上的,物理部署上根据规模决定 从一开始就要分层,因为分层对网站日后向分布式方向发展至关重要
分割
也就是纵切,把不同功能的服务分割开,包装成高内聚低偶合的模块单元,一方面有助于软件的开发和维护,一方面,便于不同模块的分布式部署。 分割粒度根据网站规模来决定,如:用户,搜索,反作弊,消息
分布式
将不同的模块部署到不同的服务器上,服务器越多,CPU,内存,存储空间资源就越多。
分布式遇到的问题:
- 性能:通过网络
- 可用性:服务器多,宕机
- 一致性:多台机器数据保持同步,分布式事务
- 可维护性:机器多,网络依赖复杂
分布式分类:
- 分布式应用和服务
将分层和分割后的模块部署到不同的服务器上。 - 分布式静态资源
将JS、CSS、图片独立分布式布署 - 分布式数据和存储
将产生和处理的海量数据存放到多台机器上面,MySQL,NoSQL - 分布式计算
后台业务,如:搜索引擎的索引构建,数据仓库的计算,Hadoop、Mapreduce - 分布式配置、分布式锁、分布式文件系统。。。。
集群
将多台服务器部署相同的应用,这一堆服务器叫集群。使用集群的目的:
- 高可用
- 高性能
缓存
将数据放到离计算最近的位置,可以提高访问速度,缓存后端的计算压力
本机缓存由远而近是:一级缓存,二级缓存、三级缓存、内存
缓存种类:
- CDN
- 反向代理
- 本地缓存
- 分布式缓存
使用缓存的前提:
- 数据访问热点不均衡,部分数据会被频繁访问,需要使用缓存:如最新20条动态
- 数据不会很快过期,否则会产生脏数据
数据库的设计都是按照有缓存的负载前提下设计的。
异步
主要是为了解耦,可以使用队列来实现这个目标。
- 类和类之间解偶:接口/中间类
- 模块与模块之间解偶:队列
异步的好处:
- 提高可用性
- 增高响应速度
- 消除并发访问高峰
问题:可能会对用户体验、业务流程造成影响
冗余
高可用的手段:冗余
应用服务:集群
数据:定期备份、主从结构。
对数据实时热备、灾备数据中心
自动化
开发:
- 自动化代码管理
- 自动化测试
- 自动化代码审查
- 自动化部署
- 自动化安全检查
运维:
- 自动化监控
- 自动化报警
- 自动化失效转移
- 自动化失效恢复
- 自动化降级
- 自动化分配资源
安全
程序实现安全:XSS、SQL注入、编码转换
- 通过密码、手机检验码进行身份认证;
- 登录交易对通信数据加密
- 验证码防止机器人程序对网站攻击
- 敏感信息过滤:反作弊
架构指标
性能
响应时间
执行一个操作需要的时间
<code>打开一个网站 几秒 数据查查询一次 10毫秒 机械硬盘一次寻址定位 4毫秒 机械硬盘顺序读1M数据 2毫秒 SSD顺序读1M数据 0.3毫秒 从Redis读一个数据 0.5毫秒 从内存读1M数据 10多微秒 Java程序本地方法调用 几微秒 /<code>
CPU操作时间
<code>从CPU到 大约需要的CPU周期 大约需要的时间(单位ns) 寄存器 1 cycle L1 Cache ~3-4 cycles ~0.5-1 ns L2 Cache ~10-20 cycles ~3-7 ns L3 Cache ~40-45 cycles ~15 ns 跨槽传输 ~20 ns 内存 ~120-240 cycles ~60-120ns 网络传输2K数据 1微秒 /<code>
并发数 :同时处理请求的数目
吞吐量: 单位时间内系统处理的请求数量,如请求数/秒,页面数每秒,访问人数每天
一些高大上的指标:
- TPS:每秒处理事务数
- HPS:每秒HTTP请求数
- QPS:每秒的查询数
性能计数器: 运维人员关注的指标,服务器或操作系统的性能指标,如:系统负载(top命令),对象与线程数、内存使用情况、CPU使用情况,磁盘IO,网络IO。这些指标超出阈值后,系统都可能会出问题。
优化:
前端优化
- 减少http请求/使用浏览器缓存/压缩/CSS放上面,JS放下面/减少Cookie传统
- CDN加速/反向代理
- 缓存优化
- 异步队列
- 集群
代码优化
- 多线程/内存/
- 存储优化
- SSD/分布式文件系统
扩展性
对现有系统影响最小的情况下,系统功能可以持续扩展和提升的能力。
高扩展性的关键是:高内聚,低耦合 -> 模块拆分
- 分布式消息队列
- 分布式服务
大型网站遇到的问题:
- 编译、布署困难:代码多,编译时间长,布署机器多
- 代码分支管理困难:复用代码的修改经常会造成冲突
- 数据库连接耗尽:
- 新增业务困难:在一个乱如麻的系统中增加新业务,维护旧功能异常痛苦,一脚全是雷,大家干的热火朝天,就是问题多多。
解决方法:拆、拆、拆 (重要的事情要说3遍)
- 拆成低耦合的模块,独立部署。
- 纵拆:将大应用拆为多个小应用独立部署
- 横拆:将复用的业务拆分出来,独立部署,对外提供稳定的接口。
服务提供者启动后在服务注册中心注册,服务消费者想使用某项服务时,先从服务注册中心获取服务提供者列表,找到服务的接口,然后根据负载均衡策略将服务请求发送到对应的服务器上。
可扩展的数据结构
NOSQL:CouchBase、MongoDB、HBase
利用开放平台建设网站生态圈
OpenAPI
伸缩性
不需要改变软件的软硬件设计,只需要部署服务器数量就可以扩大或缩小服务处理能力。 根据功能进行物理分离实现伸缩:
横向分离:不同的业务模块分离布署。
纵向分离:业务流程分离部署。
单一功能通过集群来实现伸缩:一头牛拉不动时,不找更强壮的牛,而是找两头牛
应用服务器集群的伸缩性设计
- Http重定向:302
- DNS域名解析:二级域名
- 反向代理负载:Nginx
- IP负载均衡
- 数据链路层负载均衡:LVS
分布式缓存集群的伸缩性设计
- 一致性Hash算法
数据库伸缩性设计
- 主从架构
- 读写分离
NoSQL
- HBase的的HRegion的分裂
可用性
可用性就是不出故障。 不可用时间=故障修复时间点-故障发现时间点
可用性指标=(1-不可用时间/总时间)100%
<code>2个9基本可用, 88小时 3个9是较高可用, 小于9小时 4个9是高可用, 53分钟 5个9是极高可用, 5分钟/<code>
业务拆分
- 无状态应用:负载均衡、Session管理
- 基础服务高可用:分级管理、超时设置、异步调用、服务降级、幂等性设计
- 数据高可用:数据备份、失效转移
安全性
XSS(跨站点脚本攻击):消毒
注入攻击:请求参数消毒,参数绑定
CSRF(跨站点请求伪造):表单Token、验证码、Referer检查
Hash: Md5, SHA, 防止使用彩虹表碰撞,要加盐Hash
对称加密:交换密钥是难题
非对称加密:公钥加密,私钥解密;私钥签名,公钥验签;