高并发的相关概念

在某个时间点,有多少个访问量

如果一个系统的日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
    4
    ab -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
2
3
4
5
6
7
8
9
10
11
location ~.*\.(gif|jpg|png|flv|swf|rar|zip)$
{
valid_referers none blocked immoc.com *.imooc.com #如果有不允许的访问,$invalid_referer 为1 ,重定向到错误页面
if($invalid_referer) {
#return 403
rewrite ^/ http://www.imooc.com/403.jpg
} }
  • 加密签名。使用第三方模块HttpAccessKeyModule实现Nginx防盗链
1
2
3
4
5
6
7
accesskey on|off 模块开关

accesskey_hashmethod md5 | sha-1签名加密方式

accesskey_arg GET参数名称呢

accesskey_signature加密规则
1
2
3
4
5
6
7
8
9
10
location ~.*\.(gif|jpg|png|flv|swf|rar|zip)$
{
accesskey on;
#加密方式
accesskey_hashmethod md5;
#获取参数的键
accesskey_arg sign;
#签名规则
accesskey_signatur 'jason$remoe_addr';
}
1
2
3
4
5
6
7
<?php

//md5(jason.ip)
//PHP中的加密规则
$sign = md5('jason'.$_SERVER['REMOTE_ADDR']); echo "<img src = './logo.img?sign='.$sign.'>"

####减少HTTP的请求

性能黄金法则:只有10%-20%的最终用户响应时间花在接受请求的HTML上,剩下的80%-90%时间花在HTML文档所引用的js,css等组件上

如何改善:改善相应时间的最简单的途径就是减少组件的数量,并由此减少HTTP的请求量

HTTP请求连接产生的开销

域名解析–TCP连接–发送请求–等待–下载资源–解析时间

疑问?

DNS缓存、Keep-Alive会不会消除影响

查找DNS缓存也需要时间,多个缓存就要查找多次有可能缓存会被清楚

HTTP1.1协议规定请求只能串行发送,也就是100个请求必须依次逐个发送,前面的一个请求完成才能开始下个请求

减少HTTP请求的方式

  • 图片地图:图片地图允许你在一个图片上关联多个URL,目标URL的选择取决于用户单击了图片上的那个位置
1
2
3
4
5
6
7
8
<img usemap="#map1" src="/image/image.git=f">
<map name="map1">
<area shape='rect' coords='0,0,31,31' href='javascipt:alert('Home')' title='Home'>
<area shape='rect' coords='36,0,66,31' href='javascipt:alert('Cart')' title='Cart'>
...
...
<map>
  • 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
2
3
4
5
6
7
8
9
10
11
12
<?php
//获取响应头的If-Modified-Since参数
$since = $_SERVER['HTTP_IF_MODOFIED_SINCE'];
//设置生存时间
$lifttime = 3600;
//如果没有过期
if (strtotime($since)+ $lifetime > time())
{
header('HTTP/1.1 304 Not Modified');
exit;
}
header('Last-Modified:' . gmdate('D,d M Y H:i:s',time()).'GMT')
本地缓存配置
1
2
3
4
add_header指令:添加状态码为2xx和3xx的相应投信息
add_header name value [always]
可以设置Pragma/Expire/Cache-Control,可以继承
expires指令:通知浏览器过期时间expires time;为负值时表示Cache-Control:no-cache
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# nginx.conf
location ~.*\.(gif|jpg|png|flv|swf|rar|zip)$
{
valid_referers none blocked immoc.com *.imooc.com #如果有不允许的访问,$invalid_referer 为1 ,重定向到错误页面
if($invalid_referer) {
#return 403
rewrite ^/ http://www.imooc.com/403.jpg
}
# 缓存30天
expires 30d;
# 关闭etag
etag off;
# 添加cache-control
add_header
cache-control max-age=3600
}

前端代码和资源压缩

可以让资源文件更小

压缩方式:js,css,image,html代码压缩、
Gzip压缩

js压缩的原理一般是去掉多余的空格和回车,替换长变量名,简化写法

常用的压缩工具:UglifyJS、YUI Compressor
、Closure Compiler

图片压缩:

压缩工具:tinypng、JpegMini,ImageOptim

Gzip压缩: 配置Nginx

1
2
3
4
5
6
gzip on|off
gzip_buffers 32k
gzip_disable
gzip_min_length 200
...
...
 
 
 

PHP如何解决网站大流量与高并发的问题(一)的更多相关文章

  1. PHP解决网站大流量与高并发

    1:硬件方面 普通的一个p4的服务器每天最多能支持大约10万左右的IP,如果访问量超过10W那么需要专用的服务器才能解决,如果硬件不给力 软件怎么优化都是于事无补的.主要影响服务器的速度 有:网络-硬 ...

  2. PHP如何解决网站大流量与高并发的问题(四)

    动态语言的并发处理 相关概念 什么是进程.线程.协程 什么是多进程.多线程 同步阻塞模型 异步非阻塞模型 php并发编程实践 什么是进程.线程.协程 进程 进程是一个执行中的程序 进程的三态模型:多道 ...

  3. 转:基础篇|PHP如何解决网站大流量和高并发

    基础篇 高并发架构基础概念和优化思路 高并发架构相关概念 并发,在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程 ...

  4. PHP如何解决网站大流量与高并发的问题(二)

    转载:https://zhyunfe.github.io/2017/10/02/php-interview-prepare-hc-2/ 数据库缓存 相关概念 什么是数据库缓存? 为什么使用缓存 使用M ...

  5. PHP如何解决网站大流量与高并发的问题

    首先,确认服务器硬件是否足够支持当前的流量. 普通的P4服务器一般最多能支持每天10万独立IP,如果访问量比这个还要大, 那么必须首先配置一台更高性能的专用服务器才能解决问题 ,否则怎么优化都不可能彻 ...

  6. PHP如何解决网站大流量与高并发的…

    首先,确认服务器硬件是否足够支持当前的流量. 普通的P4服务器一般最多能支持每天10万独立IP,如果访问量比这个还要大, 那么必须首先配置一台更高性能的专用服务器才能解决问题 ,否则怎么优化都不可能彻 ...

  7. PHP如何解决网站大流量与高并发的问题(三)

    七层负载均衡的实现 基于URL等应用层信息的负载均衡 Nginx的proxy是一个很强大的功能,实现了7层负载均衡 功能强大.性能卓越,运行稳定 配置简单灵活 能自动提出工作不正常的后端服务器 上传文 ...

  8. PHP 网站大流量与高并发的解决方法

    php 网站如何应对大流量与高并发呢? 首先,确认服务器硬件是否足够支持当前的流量. 普通的P4服务器一般最多能支持每天10万地理IP,如果访问量比这个还要大,则请配置一台更高性能的专用服务器. 否则 ...

  9. 如何解决web大流量,高并发问题

    对于当今大流量的网站,每天几千万甚至上亿的流量,是如何解决访问量问题的呢? 以下是一些总结的方法:  第一,确认服务器硬件是否足够支持当前的流量.  普通的P4服务器一般最多能支持每天10万独立IP, ...

随机推荐

  1. react将多个公共组件归成一类,方便调用

    目录结构 . ├── component # 公共组件存放 ├ ├── example ├ ├ ├── example1.ts # 例子1 ├ ├ ├── example2.ts # 例子2 ├ ├ ...

  2. 微信支付接口--支付成功的回调--超详细Demo

    如果本文对你有用,请爱心点个赞,提高排名,帮助更多的人.谢谢大家!❤ 如果解决不了,可以在文末进群交流. 如果对你有帮助的话麻烦点个[推荐]~最好还可以follow一下我的GitHub~感谢观看! 写 ...

  3. svn忘记密码怎么办?如何获取svn账号和密码?

    SVN作为一种开放源代码的集中式版本控制系统,一直以来都深受所有公司的喜爱.伴随着它使用范围的广泛,一系列问题也随之接踵而至. 我们今天就来谈谈比较常见的但一般除了一个人干着急没办法解决的问题,那就是 ...

  4. php与ajax技术

    web2.0的到来,ajax逐渐成为主流,什么是ajax,ajax的开发模式,优点,使用技术.(ajax概述,ajax使用的技术,需要注意的 问题,在PHP应用ajax技术的应用) 什么是ajax,a ...

  5. Linux 曝出严重安全漏洞,受限用户亦可提权至 Root 身份运行任意命令!(内附解决方案)

    本文首发于:微信公众号「运维之美」,公众号 ID:Hi-Linux. 「运维之美」是一个有情怀.有态度,专注于 Linux 运维相关技术文章分享的公众号.公众号致力于为广大运维工作者分享各类技术文章和 ...

  6. 如何设置CentOS 7开机自动获取IP地址详解

    本例中以CentOS 7举例说明如何设置Linux开机自动获取IP地址和设置固定IP地址. 自动获取动态IP地址 1.输入“ip addr”并按回车键确定,发现无法获取IP(CentOS 7默认没有i ...

  7. springboot+jpa多表查询

    背景 关联起来查询三个表的数据 步骤 定义接收结果的中间类 在 @Query 中编写 HSQL 从数据库查询 代码 定义接收结果的中间类 IterationVo.java /** * Iteratio ...

  8. Linux命令基础3-cd命令

    cd 到带空格的文件夹 [root@cctg-sjc16-grafana ccatgbld]# cd 'my test' [root@cctg-sjc16-grafana my test]# cd . ...

  9. python - django (ORM使用步骤)

    print('asd') """ # 1. 手动创建一个数据库 # 2. 在 Django 项目中设置连接数据库的相关配置(告诉Django 连接哪一个数据库) 在 DA ...

  10. Mybatis下Oracle插入新增返回主键id

    具体xml中sql是这样写,但是要注意SQ_USER.Nextval,SQ_USER是序列,你要替换下自己要进行操作的表的序列,不知道序列的话,可以sql查找下,select * from user_ ...