PHP高并发处理方案

1字数 2684阅读 2107

web资源防盗链

盗链是什么,为什么要防?

  1. 在自己页面上显示一些不是自己服务器的资源(图片、音频、视频、css、js等)
    由于别人盗链你的资源会加重你的服务器负担,所以我们需要防止,而且会影响统计

防盗链是什么? 有哪几种方式?

  • 防止别人通过一些技术手段绕过本站的资源展示页,盗用本站资源,让绕开本站资源展示页面的资源链接失效 大大减轻服务器压力
    1、Referer (易伪造referer,安全性低)
    2、加密签名 (安全性高)

防盗链的工作原理

  • 通过Referer,服务器可以检测到访问目标资源的来源网站,如果是资源文件,则可以跟踪到显示它的网页地址。一旦检测到来源网站不是本站进行阻止
  1. Referer实现 以Nginx为例,前提加载ngx_http_referer_module模块,注意:为什么要none呢?因为如果通过浏览器直接访问资源,referer就是为空,所以这种方式不能彻底阻挡住盗链。
location ~* \.(gif|jpg|png|webp)$ {
#指令valid_referers  全局invalid_referer
   valid_referers none blocked domain.com *.domain.com ;
   if ($invalid_referer) {
        return 403;
        #rewrite ^/ http://www.domain.com/403.jpg;
   }
}
  1. 通过签名,根据计算签名的方式,判断请求是否合法,如果合法则显示,否则返回错误信息
    加密签名
#以Nginx为例,前提加载第三方模块HttpAccessKeyModule实现防盗链
location ~* \.(gif|jpg|png|webp)$ {
    accesskey on;
    accesskey_hashmethod md5;
    accesskey_arg key;
    accesskey_signature "mysrc$remote_addr";
}

减少HTTP请求次数

发现问题

8090%是花费在页面引用控件的加载上,只有1020%是花费在文档的加载上,HTTP/1.1协议规定请求只能串行发送,换句话就是100个请求,只能一个一个发送,上一个请求完成才能进行下一个请求

如何改善?

  • 减少引用控件数量,从而达到减少HTTP请求次数
  1. CSS Sprites(雪碧图)
    原理:合拼图片,再使用css的background-image和background-position来指定显示元素 CSS Sprites与图片地图性能差不多,但CSS Sprites更加简单灵活
  2. 合并JS与CSS文件:加载一个JS文件比加载多个JS文件要快,一般会使用前端自动构建工具打包合并
  3. 图片使用base64编码
    注意:图片base64除了可以使用在<img>中,还可以使用在css的background-image中
  4. 图片地图 把多张图片合成一张,再使用<map>标签来实现对图片上不同区域的链接
<img src="img/planets.gif" width="145" height="126" alt="Planets" usemap="#planetmap">
<map name="planetmap">
  <area shape="rect" coords="0,0,82,126" alt="Sun" href="sun.htm">
  <area shape="circle" coords="90,58,3" alt="Mercury" href="mercur.htm">
  <area shape="circle" coords="124,58,8" alt="Venus" href="venus.htm">
</map>

CDN加速

  • CDN 就是内容分发网络,在各处放置服务器来构成一层智能虚拟网络,此处服务器称之为节点服务器。所谓智能就是会自动根据用户请求信息把请求重新分配到离客户端最近的服务器。
  • CDN的作用: 解决由于服务端与客户端所在区域的不同,导致影响数据传输速度和稳定性问题,一句话总结就是让数据传输更快更稳定。

CDN有什么优势?

1、智能Cache加速,提高企业站点的访问速度(含大量图片或静态页面最适合,因为CDN相当于是服务器的一个镜像)
2、跨运营商的网络加速,保证不同网络的用户都能得到很好的访问速度
3、加速用户远程访问服务器,根据DNS负载均衡技术自动智能选择Catch服务器
4、自动生成远程服务器的镜像(Catch服务器),加速访问速度,减轻Web服务器的负担,分担流量

CDN的工作原理是什么?

CDN适用场景有哪些?

  • 网站或应用中大量静态资源的加速分发 (例如:css/js/图片等)
  • 大文件下载
  • 直播网站

CDN如何实现?

浏览器缓存

  • 高并发下只能通过提高服务器负载来解决? NO,流量、前端、服务器、数据库
  • 缓存只能是数据库缓存吗? NO,还有浏览器缓存
  • HTTP缓存分类(2种)
    1. 200 OK (from memory cache) 直接从本地缓存中获取响应,最快速、最省流量,因为没有向服务器发送请求
    2. 304 Not Modified 协商缓存,浏览器在本地没有命中的情况下,请求头中会发送一定的校验数据到服务器。如果服务端数据没有改变,服务端直接响应(通知浏览器从本地缓存获取),返回304(快速、发送数据很少,只返回最基本的响应头,不发送响应体)
    3. 以上两种缓存全部失败,服务器返回完整响应体(200 OK),没有用到缓存,速度最慢
      与浏览器本地缓存相关的header Pragma Cache-Control Expires
    4. 前端代码和资源压缩优化 让资源文件更小,加快文件在网络中传输,让网页更快的展示,降低流量和宽带开销

压缩方式

  • JS、CSS、HTML、图片压缩和Gzip压缩
  • JS代码压缩
  • 去除一些多余的空格和回车,替换长变量名,简化一些代码写法;压缩工具:在线版和安装版在线压缩工具
  • CSS代码压缩,与JS压缩原理一样,去除空白符、注释和优化一下语义化
  • HTML代码压缩(不推荐,镇用) 不推荐使用,因为会破坏代码结构。
  • 图片(JPG、PNG)压缩
    压缩工具:tinypng/JpegMini/ImageOptim
  • Gzip压缩 Gzip压缩是Web服务器对纯文本文件(JS/CSS/XML/HTML)进行压缩
    注意:千万不要对图片进行Gzip压缩
    //以Nginx为例
# 开启gzip
gzip on;
# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
# gzip 压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明,推荐6
gzip_comp_level 6;
# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php;
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 禁用IE 6 gzip
gzip_disable "MSIE [1-6]\.";
# 压缩存储的缓冲
gzip_buffers 16 64k;
# 开启压缩的http版本
gzip_http_version 1.1;

动态语言静态化

  • 将现代动态语言的逻辑代码生成为静态HTML文件(静态化实际作用:缓存成一个html文件),再次访问时就会重定向到静态文件
  • 适用场景
    1. 对实时性要求不高的页面
  • 为什么要使用静态化?
    1. 解决高并发,减轻Web服务器和数据库服务器压力
  • 静态化实现方式有几种?
    1. 使用Smarty模板引擎
    2. 使用ob系列函数
    3. 使用Smarty模板引擎
//缓存存放目录
$smarty->cache_dir=$ROOT.'/cache'; 
//开启缓存
$smarty->caching=true; 
//缓存过期时间
$smarty->cache_lifetime=3600;
//加载模板
$smarty->display();
//清除所有缓存文件
$smarty->clearAllCache();
//清除特定模板的缓存
$smarty->clearCache('index.tpl');
使用ob系列函数(重点,实现静态化基础)
//开启输出缓冲区
ob_start(); 
//获取输出缓冲区内容
ob_get_contents();
//清空(擦掉)输出缓冲区
ob_clean();
//送出输出缓冲区内容并关闭缓冲
ob_end_flush();
//得到当前缓冲区的内容并删除输出缓冲区
ob_get_clean();

动态语言的并发处理

  • 什么是进程?什么是线程?什么是协程?
    1. 进程:是一个“执行中的程序”,程序不执行就不会产生进程。一个执行中的程序至少会产生一个进程,当进程获得了处理机时才会从就绪状态变为运行状态,处理机不断切换地分配到每个进程中。决定同时有多少个进程处于运行状态的是处理器数量(CPU核数)进程的三态模型:多个程序在系统中运行时,进程在处理机中交替运行,状态在不断切换。三态分别是:就绪、运行、阻塞
    2. 进程的五态模型(在三态的基础上发展而来):新建态、运行态、终止态、就绪态、等待态
    3. 线程:之为轻量级的进程,程序执行流的最小单元。线程依赖于进程(一个进程可以有多个线程),线程不拥有系统资源。与同属一个进程的其他线程共享进程拥有的全部资源;一个线程可以创建和撤销另一个线程,同一个进程中的多个线程可以并发执行。一个进程下有多个线程来完成不同的工作称之为多线程。(一个进程下至少会有一个线程)
    4. 线程由来:由于用户并发请求,为每个请求都创建一个进程显然太浪费系统资源和影响响应用户请求的效率,所以引进线程的概念。
    5. 协程:是一种用户态轻量级的线程。
  • 协程与线程的区别
    1. 协程是由用户自己调度,而线程是用系统调度
    2. 协程是异步的,而进程线程是同步的
    3. 一个线程可以有多个协程,一个进程也可以单独拥有多个协程
    4. 协程会保留上一次调用的状态
  • 什么是多线程?什么是多进程?
    1. 多进程:2个或2个以上的进程处于运行状态,进程间通信不方便
    2. 多线程:把一个进程分为很多片,每一片都是一个独立的流程,线程间可以互相通讯

同步阻塞模型
异步非阻塞模型

PHP并发编程实战

  • 使用swoole扩展
  • 使用消息队列
  • 接口的并发请求
    1. curl_multi_init()

数据缓存

  • 什么是数据缓存?
    传统关系型数据库都是把数据存储到硬盘中,在高并发情况下,对数据库服务器会造成巨大压力(巨大IO操作),为了解决此问题,数据缓存由此而生!
  • 作用:
    1. 极大地缓解数据库服务器的压力
    2. 提高数据的响应速度
  • 缓存形式有:内存缓存、文件缓存 推荐使用内存缓存

如何使用Mysql查询缓存?
如何使用Memcache缓存?
如何使用redis缓存?

Web服务器负载均衡

  • 七层负载均衡(Nginx)
    1. 基于URL等应用层信息实现负载均衡 一般使用Nginx(功能强大、性能卓越、运行稳定)来实现, 配置简单灵活
      内置 加权轮询、IP Hash 外置 fair策略、通用Hash、一致性Hash
      Nginx配置负载均衡
http{
    upstream cluster{
        server srv1;
        server srv2;
        server srv3;
    }
    server{
        listen 80;
        location / {
            proxy_pass http://cluster;
        }
    }
}
  • 四层负载均衡(LVS/硬件设备)
  1. LVS
    1. LVS负载均衡的三种方式:NAT、DR和TUN
  2. 硬件设备
    1. 硬件设备:通过报文中的目标地址和端口,再加上负载均衡设备的服务器选择方式,决定最终选择的内部服务器

MySQL数据库优化

  • 优化方向
  1. 字段数据类型优化
    1. tinyint/smallint/int/bigint的选择
    2. char/varchar
    3. enum 固定分类
  2. IP地址数据如何存?
    1. 把IP地址转整型类型存储

索引
SQL语句优化
存储引擎优化
表结构设计优化
数据库服务器架构优化
读写分离

推荐阅读更多精彩内容