高并发的相关概念
在某个时间点,有多少个访问量
如果一个系统的日PV在千万以上,有可能是一个高并发的系统
QPS: 每秒钟请求或者查询的数量,在互联网领域,指每秒相应请求数(指HTTP请求)
吞吐量: 单位时间处理的请求数量
响应时间: 从请求发出到收到相应花费的时间
PV: 综合浏览量 page view 页面浏览量或者点击量,一个访客在24小时之内的浏览量或者点击量
UV: 独立访客unique visitor,一定时间范围内相同访客多次访问网站,只计算一独立个访客
带宽: 计算带宽大小需关注两个指标,峰值流量和页面平均大小
日网站带宽 = PV/统计时间(s) 平均页面大小(k) 8
峰值一般是平均值的倍数,根据实际情况来定
QPS不等于并发连接数量
QPS是每秒HTTP的请求数量,并发连接数量是系统同事处理的请求数量
峰值每秒请求数(QPS) = (总PV数 80%) / (6小时秒数 20%)
代表80%的访问量集中在20%的时间(28定律)
压力测试:
-
压力测试
常用的性能测试工具
ab(apache benchmark)模拟并发请求100次,总共请求5000次
1
2
3
4ab -c 100 -n 5000 http://**.com
//-c 并发数
//-n 请求数量
注意事项:
测试机器与被测试机器分开 | 不要对线上服务做压力测试 | 观察测试功工具ab在机器以及被测试的前端机的CPU、网络等不超过75%
-
QPS达到50:不需要优化
-
QPS达到100: 假设关系型数据库的每次请求在0.01s完成,假设单个页面只有1个SQL,那么100QPS以为这1秒钟完成100次请求,但是此时我们并不能保证数据库查询能完成100次
方案:数据库缓存层,数据库的负载均衡
- QPS达到800:
假设我们使用百兆贷款,以为这网站出口的实际宽带是8M左右
假设每个页面只有10k,在这个并发下,百兆贷款已经吃完
方案: CDN加速,负载均衡
- QPS达到1000:
假设使用mem缓存数据,每个页面对mem的请求数远大于直接对db的请求
mem的悲观并发数在2w左右,但是有可能在之间内网宽带已经吃光,表现不稳定
方案: 静态HTML缓存
- QPS达到2000:
这个级别下,文件系统访问锁都成为了灾难
方案: 做业务分离,分布式存储
测试能承受的最大并发
测试最大承受的QPS值
高并发解决方案案例
-
流量优化
防盗链处理
前端优化:减少http请求(合并css,js,图片)、添加异步请求、启用浏览器缓存和文件压缩、CDN加速、建立独立图片服务器
服务端优化:页面静态化、并发处理
数据库优化:数据库缓存(mem,redis),分库分表、分区操作、读写分离、负载均衡
Web服务器优化:负载均衡
Web资源防盗链
盗链概念:
盗链是指在自己的页面上展示一些并不在自己服务器上的内容
常见的小站盗用大战的图片、音乐、视频、软件资源
通过盗链的方法可以减轻自己服务器的负担,因为真实的空间和流量均是来自别人的服务器
防盗链的概念:
防止别人通过一些技术手段盗用自己站点的资源,让资源在别人的站点上无法访问
可以大大减轻服务器以及带宽压力
工作原理: 通过Referer或者签名,网站可以检测目标网页访问的来源网页
- Referer(有漏洞,可伪装)
nginx 模块,ngx_http_referer_module用来阻挡来源非法的域名请求
Nginx指令valid_referers,全局变量$invalid_referer
valid_referers none|blocked|server_names|string…
none 代表为空时
blocked 代表来源头部不为空,但是里面的值被防火墙删除
server_names 代表信任的地址
1 | location ~.*\.(gif|jpg|png|flv|swf|rar|zip)$ |
- 加密签名。使用第三方模块HttpAccessKeyModule实现Nginx防盗链
1 | accesskey on|off 模块开关 |
1 | location ~.*\.(gif|jpg|png|flv|swf|rar|zip)$ |
1 | <?php |
####减少HTTP的请求
性能黄金法则:只有10%-20%的最终用户响应时间花在接受请求的HTML上,剩下的80%-90%时间花在HTML文档所引用的js,css等组件上
如何改善:改善相应时间的最简单的途径就是减少组件的数量,并由此减少HTTP的请求量
HTTP请求连接产生的开销
域名解析–TCP连接–发送请求–等待–下载资源–解析时间
疑问?
DNS缓存、Keep-Alive会不会消除影响
查找DNS缓存也需要时间,多个缓存就要查找多次有可能缓存会被清楚
HTTP1.1协议规定请求只能串行发送,也就是100个请求必须依次逐个发送,前面的一个请求完成才能开始下个请求
减少HTTP请求的方式
- 图片地图:图片地图允许你在一个图片上关联多个URL,目标URL的选择取决于用户单击了图片上的那个位置
1 | |
- CSS Sprites
CSS Sprites中文翻译CSS精灵,通过使用合并图片,通过指定的cssbackground-image 和backgroud-position来显示元素
- 合并脚本和样式表
使用外部的js和css文件引用的方式,因为这样比直接写在页面中性能要更好一点
把多个脚本合并成一个脚本,把多个css合并成一个css
- 图片使用Base64编码减少页面请求数
采用base64的编码方式将图片直接嵌入到网页中,而不是从外部载入
1 | <img src='data:image/gif;base64,/9j/4AAQSkZJ....'> |
浏览器缓存和数据压缩
高并发下只能通过提升服务器负责解决吗?
缓存只能做数据库缓存吗?
相关概念
HTTP缓存机制
前端代码和资源的压缩
缓存分类
HTTP缓存模型中,如果请求成功会有三种情况
- 200 from memory cache:直接从本地缓存中获取相应,最快速,最省流量,因为根本没有向服务器发送请求
本地缓存
相关Header
Pragma:HTTP1.0时代的遗留产物,该字段被设置为no-cache时没,会告知浏览器禁用本地缓存,每次都向服务器发送请求
Expires:HTTP1.0时代用来启动本地缓存的字段,expires值对应一个形如Thu,31 Dec 2037 23:55:55 GMT的格林威治时间,告诉浏览器缓存实现的时刻,如果时间还没到,标明缓存有效,无需发送请求,但是Expire是Nginx发送的,如果浏览器时间不准确,会造成很大的影响
Cache-Control:HTTP1.1针对Expires时间不一致的解决方案,运用Cache-Control告知浏览器缓存国企的时间间隔而不是时刻,即使具体时间不一致,也不影响缓存的管理
no-store:禁止浏览器缓存响应
no-cache:不允许直接使用本地缓存,先发起请求和服务器协商
max-age=delta-seconds:告知浏览器该相应本地缓存有效的最长期限,以秒为单位
优先级
Pragma > Cache-Control > Expires
- 304 Not Modified:协商缓存,浏览器在本地没有命中的情况下请求头中发送一定的校验数据到服务端,如果服务端数据没有改变,浏览器从本地缓存相应,返回304
相关Header
Last-Modified:通知浏览器资源的最后修改时间
If-Modified-Since:得到资源的最后修改时间后,会将这个信息通过If-Modified-Since提交到服务器做检查,如果没有修改,返回304状态码
ETag:HTTP1.1推出,文件的指纹标识符,如果文件内容修改,指纹会改变
If-None-Math:本地缓存失效失败,会携带此值去请求服务端,服务端判断该资源是否改变,如果没有改变,直接使用本地缓存,返回304
- 200 OK 以上两种缓存失败,服务器返回完整相应数据,没有用到缓存,相对最慢
缓存策略的选择
适合本地缓存的内容
- 不变的图像,如logo,图标
- js,css静态文件
- 下载的文件
适合使用协商缓存
- HTML文件
- 经常替换的图片
- 经常修改的js,css文件
- js,css文件的加载可以加入文件的签名来拒绝签名 index.css?签名|index.签名.js
不建议缓存的内容
- 用户隐私等敏感数据
- 经常改变的api数据接口
Nginx配置缓存策略
1 | <?php |
本地缓存配置
1 | add_header指令:添加状态码为2xx和3xx的相应投信息 |
1 | # nginx.conf |
前端代码和资源压缩
可以让资源文件更小
压缩方式:js,css,image,html代码压缩、
Gzip压缩
js压缩的原理一般是去掉多余的空格和回车,替换长变量名,简化写法
常用的压缩工具:UglifyJS、YUI Compressor
、Closure Compiler
图片压缩:
压缩工具:tinypng、JpegMini,ImageOptim
Gzip压缩: 配置Nginx
1 | gzip on|off |