PHP如何解决网站大流量与高并发的问题(一)「建议收藏」

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

大家好,又见面了,我是全栈君。

高并发的相关概念

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

如果一个系统的日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
...
...
 

 

 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/112149.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • JsonArray转换List

    JsonArray转换List将List转换为JsonArray:AppResponse<List<ProjectVo>>allProject=projectServiceFeign.findAllProject();//转jsonStringtoJSONString=JSON.toJSONString(allProject.getData());//保存到redis中,设置失效时间redisTemplate.opsForValue().set(“projectStr”,toJSONStr

  • 02_ElasticSearch索引操作总结归纳

    02_ElasticSearch索引操作总结归纳

  • 【c#】将DataTable的时间精确到毫秒

    【c#】将DataTable的时间精确到毫秒【c#】将DataTable的时间精确到毫秒

  • 说说你对servlet 的理解或者 servlet 是什么?「建议收藏」

    说说你对servlet 的理解或者 servlet 是什么?「建议收藏」说说你对servlet的理解或者servlet是什么?Servlet(ServletApplet),全称JavaServlet,是用Java编写的服务器端程序。而这些Servlet都要实现Servlet这个接口。其主要功能在于交互式的浏览和修改数据,生成动态Web内容。Servlet运行于支持Java的应用服务器中。 HttpServlet重写doGet和doPost

  • ftp工具哪个好用_iis搭建ftp服务器

    ftp工具哪个好用_iis搭建ftp服务器相信很多网友都听说过ftp扫描工具,但是却对其不是很了解,ftp扫描工具是一种ftp账号软件,用户可在ftp扫描工具的帮助下轻松对网站地址进行扫描,从而采集到账号密码、网站收录等多种信息。在对ftp扫描工具做了大概了解之后,小编带大家解读ftp扫描工具如何使用?一、ftp客户端ftp客户端推荐使用iis7服务器管理工具,可以批量管理ftp站点。它是一款服务于windows及linux系统的批量管理工具,同时也是ftp及vnc的客户端。下载地址:http://yczm.iis7.com/?ccxd二

  • pytest指定用例_文件夹排列顺序自定义

    pytest指定用例_文件夹排列顺序自定义前言测试用例在设计的时候,我们一般要求不要有先后顺序,用例是可以打乱了执行的,这样才能达到测试的效果.有些同学在写用例的时候,用例写了先后顺序,有先后顺序后,后面还会有新的问题(如:上个用例返回

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号