高并发处理方案
web资源防盗链
盗链是什么?为什么要防?
在自己页面上显示一些不是自己服务器上的资源(如HTML/CSS/JS/图片/音频/视频等)的现象。
由于别人盗链你的资源会加重你的服务器的负担,所以我们需要防止,
防盗链是什么?如何防盗链?
防止别人通过一些技术手段绕过本站的资源展示页,盗用本站资源,让绕开本站资源展示页的资源链接失效,这样可以大大减轻服务器的压力。
有以下两种方式:
Referer(容易伪造Referer,安全性低)
加密签名(安全性高)
防盗链的工作原理
通过Referer,服务器可以检测到访问目标资源的来源网站,如果是资源文件,则可以追踪到显示它的网页地址。一旦检测到来源网站不是本网站,则进行阻止。
通过签名,根据计算签名的方式,判断请求是否合法,如果合法就显示,否则返回错误信息。
Referer实现
以NGINX为例,前提是加载ngx_http_referer_module模块:
注意:使用none是因为如果浏览器直接访问资源,Referer是为空的,所以这种方式不能彻底阻挡住盗链。
加密签名
以NGINX为例,前提是加载HttpAccessKeyModule实现防盗链:
HTTP请求次数
发现问题
页面加载的时间8090%是花费在引用资源的加载上,只有10%20%的时间是花费在文档的加载上。
HTTP/1.1规定请求只能串行发送。
如何改善?
减少引用资源的数量,从而达到减少HTTP请求的次数。
如何实现减少请求?
图片地图
CSS Sprites(雪碧图)
合并JS文件
图片实现base64编码
CDN加速
什么是CDN加速?
CDN就是内容分发网络,在各处放置服务器来构成一层只能虚拟网络,此处服务器称之为节点服务器。
所谓智能就是会自动根据用户请求信息把请求重新分配到离客户端最近的服务器。
CDN的作用:解决由于服务器与客户端所在区域不同,导致影响数据传输速度和稳定性问题,一句话总结就是让数据传输更快更稳定。
CDN有什么优势?
主要优势如下:
智能cache加速,提高企业站点的访问速度(含大量图片或静态页面最适合,因为CDN相当于是服务器的一个镜像)
跨运营商的网络加速,保证不同网络的用户都能得到很好的访问速度
加速用户远程访问服务器,根据DNS负载均衡技术自动智能选择cache服务器
自动生成远程服务器的镜像(cache服务器),加速访问速度,减轻web服务器的负担,分担流量
CDN的工作原理是什么?
传统访问的原理:
用户在浏览器输入域名,发起请求–》解析域名获取服务器的IP地址–》根据IP地址 找到对应的服务器–》服务器响应并返回数据
使用CDN访问的原理:
用户发起请求–》智能DNS的解析(根据IP判断地理位置、接入网类型、选择路由最 短和负载最轻的服务器)–》获得缓存服务器IP–》把内容返回给用户(如果缓存中有) –》向源站发起请求–》将结果返回给用户–》将结果存入缓存服务器
CDN的使用场景有哪些?
适应场景如下:
网站或应用中大量静态资源的加速分发(如css/js/图片等)
大文件下载
直播网站
CDN如何实现?
浏览器缓存
HTTP缓存分类
分为以下2种:
200 OK,直接从本地缓存中获取响应,最快速、最省流量,因为没有向服务器发送请求
304 Not
Modified,协商缓存,浏览器在本地没有命中的情况下,请求头中会发送一定的校验数据到服务器。如果服务器数据没有改变,服务器直接响应(通过浏览器从本地缓存获取),返回304(快速、发送数据很少,只返回基本的响应头,不返送响应体)
与浏览器本地缓存相关的header
Pragma
Cache-Control
Expires
前端代码和资源压缩优化
让资源更小,加快资源在网络中的传输速度,让网页更快的显示,降低流量和宽带开销。
压缩方式
- HTML压缩(不推荐)
不推荐使用,因为会破坏代码结构
- CSS代码压缩
去除多余的空白符、注释和简化一些代码写法
- JS代码压缩
去除多余的空白符和回车,替换长变量名,简化一些代码写法
图片(JPS、PNG)压缩
Gzip压缩
Gzip压缩是Web服务器对纯文本(HTML/CSS/JS/XML)进行压缩,不能对图片进行Gzip压缩
动态语言静态化
将现代动态语言的逻辑代码生成为静态HTML文件(例如使用smarty生成缓存文件),再次访问时就会重定向到静态文件。
使用场景
对实时性要求不高的页面
为什么要使用静态化?
解决高并发,减轻Web服务器和数据库服务器的压力
静态化实现方式
实现方式如下:
- 使用Smarty模板引擎
- 使用ob系列函数(重点,实现静态化的基础)
编程语言的并发处理
什么是进程、线程和协程?
进程:是系统系进行资源分配和调度的一个独立单位,是一个“执行中的程序”,程序不执行就不会产生进程。一个执行中的程序至少会产生一个进程,当进程获得了处理器时才会从就绪态转变为运行态,处理器不断切换地分配到每个进程中,决定同时有多少进程处于运行态的是处理器的数量(CPU核数)
线程:是系统调度和分配的基本单位,是进程的一个实体,称之为轻量级的进程,线程完全依赖于进程(一个进程可以有多个线程),线程不拥有系统资源。与同属于一个进程的其他线程共享进程拥有的所有资源;一个线程可以创建和撤销另一个线程,同一个进程中的多个线程可以并发执行。一个进程下有多个线程来完成不同的工作的现象称之为多线程。
线程由来:由于用户并发请求,为每个请求都创建一个进程太浪费系统资源和影响响应用户请求的效率,所以引进线程的概念。
协程:是一种用户态的轻量级的线程。
什么是多进程、多线程?
多进程:多个进程处于运行态,进程间通信不方便
多线程:把一个进程分成很多片,每一片都是一个独立的流程,线程间可以相互通信。
IO模型
基础概念
同步:
同步,就是在客户端发出一个功能调用时,在没有得到结果之前,该调用不返回。
通俗点说,就是必须一件一件事做,等前一件事完了之后才做后一件事。
eg:普通的B/S模式(同步):提交请求->等待服务器处理->处理完毕返回,这期间 客户端浏览器不能干任何事
异步:
与同步相对。当C端一个异步过程调用发出之后,调用者没有立即得到结果,实际处 理这个调用的部件在完成后,通过状态,回调来通知调用者。
eg :请求通过事件触发->服务器处理(浏览器仍然可以做其他事情)->处理完毕
阻塞:
阻塞调用,是指调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这 个状态,cpu不会分配时间片,线程暂停运行)函数只有得到结果返回。
eg:比如你去一层(假设是内核缓冲区)取快递,但是不知道什么时候来,你不能干 别的事情,只能等着但是可以睡觉(进程处于休眠状态),因为快递来时一定会打电话 通知。
非阻塞:
与阻塞相对应,指在不能立即得到结果之前,该函数不会阻塞当前线程,而会立即返回。
eg:在等快递的时候,(用轮询的方式)每隔5分钟去一层(内核缓冲区)去看快 递来了没,没来,立即返回;如果快递来了,就放到A楼一层,等你去取。
同步阻塞模型
阻塞IO:
在内核将数据准备好之前,系统调用会一直等待。也就是说,应用程序调用一个IO函 数,等待数据,若数据没有准备好,一直等待;直到数据准备好,从内核空间拷贝到用 户空间,IO函数返回成功。
由图可知:
- 当调用recv()函数时,系统首先检查是否有准备好的数据,如果数据没有准备好,那么系统就处于等待状态;
- 当数据准备好后,将数据从系统缓冲区拷贝到用户空间,然后函数返回。
BIO使用场景:
架构比较固定,连接数比较少,这种方式对服务器资源要求比较高,BIO一般使用在java jdk1.4之前的唯一选择
同步非阻塞模型
非阻塞IO:
如果内核还未将数据准备好,系统调用会直接返回,并且返回EWOULDBLOCK错误 码.也就是说,我们把一个套接口设置为非阻塞就是告诉内存,当所请求的I/O操作无 法完成时,返回一个错误;I/O函数会不断的测试数据是否准备好,直到数据准备好为
止。
由图可知:
(1)这是一个轮询的过程,这对CPU来说是较大的浪费。
(2)每次用户询问内核是否有数据报准备好(文件描述符缓冲区是否就绪),数据报准备 好时,就进行拷贝数据报的操作。
(3)当数据报没有准备好的时候,也不阻塞程序,内核直接返回未准备就绪的信号,等待 用户程序的下一次轮询。
NIO使用场景:
连接数比较多(轻操作),连接是时间较短,比如说 聊天服务器,编程比较复杂。
信号驱动IO模型
信号驱动IO模型:
内核将数据准备好的时候, 使用SIGIO信号通知应用程序进行IO操作 也就是说,这个模型是由信号进行驱动的。
由图可知: (1)首先建立一个信号处理函数,进程继续运行并不阻塞。 (2)当数据准备好时,进程会收到一个SIGIO信号 (3)在信号处理函数中调用I/O操作函数处理数据报
IO复用模型
IO多路转接:
能够同时等待多个文件描述符的就绪状态.也就是说,这种IO模型也是属于阻塞的IO, 但是它可以对多个文件描述符进行阻塞监听,所以它的效率比阻塞IO模型高效。
由图可知: (1)与阻塞式IO相比,类似,多了一个select函数,对其参数中的文件描述符进行循环监听,当某个文件描述符就绪的时候,就对这个文件描述符进行处理。 (2)直到有数据可读或可写时,才真正调用I/O操作函数。
异步IO模型
异步IO:
由内核在数据拷贝完成时,通知应用程序。异步IO使用的不再是read和write的系统 接口了,应用程序调用aio_XXXX系列的内核接口。
由图可知:
(1)当应用程序调用aio_read的时候,内核一方面去取数据报内容,另外一方面将程序控 制权还给应用进程,进程继续执行。
(2)应用进程继续处理其他事务(应用进程就是一种非阻塞的状态)
(3)当内核的数据报就绪的时候,由内核将数据报拷贝到应用进程中,返回给aio_read中 定义好的函数处理程序
AIO使用场景:
适用于连接数较多,连接时间较长,比如 相册服务器,充分地利用OS资源参与进来, jdk1.7开始支持
PHP并发编程
主要有以下方式:
使用swoole扩展
使用消息队列
Kafka/redis/rabbitMQ等
- 接口的并发请求
Curl_multi_init()
select/poll/epoll区别
Select: 有连接数限制,且性能低,windows下提供
Poll: 和select一样,但是没有连接限制,Linux下提供
Epoll: 没有连接数限制,性能最好,Linux下提供
数据缓存
什么是数据缓存
传统关系型数据库都是把数据存储到硬盘中,在高并发的情况下,对数据库服务器会造成巨大的压力(巨大的IO操作),为了缓解此类问题,出现了数据缓存!
作用:
极大地缓解数据库服务器的压力
提高数据的响应速度
为什么使用数据缓存?
如何使用MySQL查询缓存?
如何使用memcache缓存?
如何使用Redis缓存?
Web服务器负载均衡
实现方式
实现方式如下:
七层负载均衡(NGINX)
四层负载均衡(LVS、硬件设备)
七层负载均衡
基于URL等应用层信息实现负载均衡
NGINX负载均衡策略
内置:轮询、加权轮询、ip_hash、url_hash、lest_conn、hash关键数值
外置:fair策略、通用hash、一致性hash
NGINX配置负载均衡
四层负载均衡
有2种方式实现:
LVS
硬件设备
MySQL数据库优化
优化方向
- 字段数据类型优化
索引
SQL语句优化
存储引擎优化
表结构设计优化
数据库服务器架构优化