高并发解决方案(上)
一、防盗链
什么是盗链?
盗链通常是一些名小网站来盗取一些有实力的大网站的地址(比如一些音乐、图片、软件的下载地址)然后放置在自己的网站中,通过这种方法盗取大网站的空间和流量,如果自己的网站被他人盗链,不仅自己的网站知名度和访问量得不到提升,还会降低自己服务器的运行速度。
如何防止他人盗链?
防盗链的工作原理是网站可以检测目标网页访问的来源网页,如果是资源文件,则可以跟踪到显示他的网页地址,一旦检测到来源不是本站即进行阻止或者返回指定页面
那么如何进行检测呢?
1.通过http协议中的表头字段referer
referer能够表示从哪儿链接到当前的网页或文件,通过referer,网站可以检测目标网页访问的来源网页,如果是资源文件,则可以跟踪到显示它的网页地址。以Ngnix服务器为例,利用Nginx 模块 ngx_http_referer_module 用于阻挡来源非法的域名请求
以下是通过配置nginx 来阻止除ygt.com对服务器资源的访问并返回403
配置代码:
valid_referers none|blocked|server_names|string...;
none: "referer" 来源头部为空的情况
blocked: "referer" 来源头部不为空,但是里面的值被代理或者防火墙删除了,这些值都不以http://或者https://开头
location ~ .*\.(gif|jpg|png|flv|swf|rar|zip)$ { valid_referers none blocked ygt.com; if($invalid_referer) { #return 403; rewrite ^/http://www.ygt.com/403.jpg } }
2.加密签名
针对检查refer的方式,可以在页面中间件里面先进入目的地址的另外一个页面再转到目的页面即可,这样页面的refer就是目的站点自己的。所以还可以通过另一种方法:加密签名
对文件请求链接的后面加上指定签名参数,然后在服务器中进行验证:
$sign = md5('jiami'. $_SERVER['REMOTE_ADDR']); //指定加密参数 jiami + ip地址组成加密参数 echo '<img src = "./xxx.png?sign = '.$sign. '">';
根据服务器所写代码 在nignx 中使用第三方模块HttpAccessKeyModule实现防盗链
accesseky on|off 模块开关 accesseky_hashmethod md5|sha-1 签名加密方式 accesskey_arg GET参数名称 acceskey_signature 加密规则
location ~ .*\.(gif|jpg|png|flv|swf|rar|zip)$
{
accesseky on;
accesseky_hashmethod md5;
accesskey_arg sign;
acceskey_signature "jiami$remote_addr";
expires 30d;//过期时间
}
二、减少HTTP请求
在web页面渲染过程中,服务器连接数据库并计算返回数据 , http请求以及数据(文件)经过网络传输 , 文件在浏览器中计算渲染呈选; 其中大约80%的时间都耗在了http请求上,过多的http请求会影响页面的呈现速度
如何减少http请求?
1.制作图片地图:允许一个图片关联多个url,即将多个图片合并为一个图片,如以下例子
2.css sprites
通过css中的background-position来定位图片中的某一具体部分,它比图片地图更灵活
3.合并脚本和样式文件(js css)
javascript和css可以嵌入html文档中内联 ,还可以放入外部脚步样式表中,前者会增加文档大小,并且不符合低耦合的开发思路,使得代码较难维护,但后者增加了http请求数,对于时间上来说会比较耗时,所以要根据实际情况来决定如何俩配合使用比较好
4.图片使用Base64编码减少页面请求数
采用base64编码方式将图片直接嵌入到网页中,而不是从外部载入,通过使用data:URL数据形式可以替代http请求,甚至可以用于script和a标签中,其缺陷是Base64编码会增加图片的大小,并且嵌在网页中,会加大网页的数据量,
三、浏览器缓存和压缩优化
浏览器缓存能够提高响应速度,在http缓存模型中,如果成功会有三种情况
① 200 from cache: 直接从本地缓存中获取响应 (最快速,最省流量,因为根本没有向服务器发送请求)
② 304 Not Modified: 协商缓存,浏览器在本地没有命中的情况下,请求头中发送一定的校验数据到服务端,如果服务端数据没有改变,则浏览器从本地缓存响应,返回304 (快速,发送的数据很少,只返回一些基本的响应头信息,数据量很小,不发送实际响应体)
③ 200 OK :以上两种缓存全部失败,服务器返回完整响应,没有用到缓存,相对最慢
那么我们如何配置缓存比较好呢?
首先要了解与缓存相关的几个http头部:
pragma: HTTP1.0时代的遗留产物,该字段被设置为no-cache时,会告知浏览器禁用本地缓存,即每次都向服务器发送请求
Expires: HTTP1.0时代用来启用本地缓存的字段,expires值对应一个形如Thu, 31 Dec 2037 23:59:59 GMT的格林威治时间,告诉浏览器缓存实现的时刻,如果还没到该时刻,表明缓存有效,无需发送请求 (缺陷:浏览器与服务器时间无法保持一致,如果时间差距大,就会影响缓存结果)
Cache-Control : HTTP1.1针对Expires时间不一致的解决方案,运用Cache-Control告知浏览器缓存过期的时间间隔而不是时刻,即时具体时间不一致,也不影响缓存的管理
Cache-Control 参数:
no-store: 禁止浏览器缓存响应
no-cache:不允许直接使用本地缓存,先发起请求和服务器协商
max-age = dalta-seconds : 告知浏览器该响应本地缓存有效的最长期限,以秒为单位
优先级 Pragma > Cache-Control > Expires
什么是协商缓存?
当浏览器没有命中本地缓存,如本地缓存过期或者响应中声明不允许直接使用本地缓存,那么浏览器肯定会发起服务端请求,服务端会验证数据是否修改,如果没有修改,通知浏览器使用本地缓存
相关头部:
Last-Modified:通知浏览器资源的最后修改时间
If-Modified-Since :浏览器得到服务器返回的资源的最后修改时间后,会将这个信息通过If-Modified-Since 提交到服务器做检查,如果没有修改,返回304 状态码
ETag : HTTP1.1推出,文件的指纹标识符,如果文件内容修改,指纹会改变
If-None-Match: 本地缓存失效,会携带此值去请求服务端,服务端判断该资源是否改变,如果没有改变,直接使用本地缓存,返回304
了解了相关http头部信息后,接下来了解缓存策略的选择:
适合缓存的内容有:
不变的图像,如logo,图标等,js/css静态文件 ,可下载的内容,媒体文件
适合使用协商缓存的有
html文件,经常替换的图片,经常修改的js,css文件(js.css文件的加载可以加入文件的前面来拒绝缓存 index.css?签名 index.签名.js)
不建议缓存的内容有
用户隐私等敏感数据,经常改变的api数据接口
例子:
利用Nginx配置缓存策略:
相关指令:
add_header 指令:添加状态码为2xx和3xx的响应头信息
add_header name value [always]; 可以设置Paragma expires cache-control
expires time 通知浏览器过期时长 为负值表示Cache-Control: no-cache;当为正或0时,就表示Cache-Contorl: max-age= 指定的时间
当为max时,会把expires设置为“Thu,31 Dec 2037 23:55:55” GMT,cache-control 设置到10年
Etag指令 :指定签名
etag on|off 默认是on
前端代码和资源的压缩
通过压缩前端代码和资源,可以让资源文件更小,加快文件在网络中的传输速度,让网页更快的展现,降低带宽和流量开销
压缩方式:
1.JS代码压缩 js压缩的原理一般是去掉多余的空格和回车、替换长变量名、简化一些代码的写法等。利用js代码压缩工具如:UgligyJS、YUICompressor、Closure Compiler
2.CSS代码压缩 原理跟JS压缩原理类似,去除空白符,注释并优化一些css语义规则等 工具:CSS Compressor
3.HTML代码压缩 不建议使用代码压缩,有时会破坏代码结构,可以使用Gzip压缩,转换后要检查代码结构
4.图片压缩 工具:tinypng 、JpegMini 、ImageOptim
5.其他自动化构建工具Grunt
四、CDN加速
CDN的全称是Content Delivery Network,即内容分发网络 尽可能避开互联网上有可能影响数据传输双速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层虚拟网络
CDN系统能够实时地根据网络流量和各节点的链接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上
传统web访问:
用户在浏览器输入域名发起请求--->解析域名获取服务器IP地址--->根据IP地址找到对应的服务器--->服务器响应并返回数据
CDN访问:
用户发起请求--->智能DND的解析(根据IP判断地理位置、接入网类型、选择路由最短和负载最轻的服务器)--->取得缓存服务器IP--->把内容返回给用户(如果缓存中有)--->向源站发起请求--->将结果返回给用户--->将结果存入缓存服务器
场景:
站点或者应用中大量静态资源的加速分发,列如css,js,图片和HTML 大文件下载,直播
实现:
cdn加速服务、lvs负载均衡、Nginx反向代理