线程安全问题----互斥锁和递归锁
互斥锁
线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制就是引入互斥锁,互斥锁为资源引入一个状态:锁定与非锁定。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。
image.png
互斥锁会出现死锁的情况:
- 一个线程内部多次加锁没有释放
- 多个程序间相互调用引起死锁
递归锁:无论acquire多少次都不会产生阻塞
递归锁:rlock = threading.RLOCK()
互斥锁: threading.LOCK()
递归锁的原理:- 维护一个Lock和counter变量,用来记录acquire次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。这里以例1为例,如果使用RLock代替Lock,则不会发生死锁;
python解释器和GIL
Cpython中存在全局解释器锁,作用在解释器上,锁的是线程,基于这个锁的存在导致同一进程中同一时刻只能有一个线程运行。
GIL的运行过程:
- 设置GIL
- 切换到一个线程去运行
- 运行指定数量的字节码指令或者线程主动让出控制(可以调用time.sleep(0))
- 把线程设置为睡眠状态
- 解锁GIL
- 再次重复以上步骤
GIL不是python语言的问题,而是Cpython解释器的问题,Jpython就没有GIL
GIL不能利用多核,为什么不解决?- 编译型语言不会出现此问题
- 解释性语言php,python读一行执行一行,运行中并不知道下一行将产生多少个线程,容易产生冲突,并没有规避风险,容易产生数据不安全问题;
细粒度锁的弊端:- 可以利用多核,但加锁导致效率太低
redis分布式锁的实现原理:
背景:某个查询数据库的接口,因为调用量比较大,所以加了缓存,并设定缓存过期后刷新,问题是当并发量比较大的时候,如果没有锁机制,那么缓存过期的瞬间,大量并发请求会穿透缓存直接查询数据库,造成雪崩效应,如果有锁机制,那么就可以控制只有一个请求去更新缓存,其它的请求视情况要么等待,要么使用过期的缓存
image.png
1.redis->setNX(
value);
if (cache->update();
key);
}
缓存过期时,通过setnx获取锁,如果成功了,更新缓存,删除锁
问题:如果意外情况下,创建了锁,但是没有删除锁那么这个锁将一直存在,以至于缓存得不到更新,因此需要给锁加一个过期时间。
https://www.cnblogs.com/softidea/p/5819169.html
mysql主从复制的原理:
https://jaminzhang.github.io/mysql/MySQL-Master-Slave-Replication-Principle/
image.png
Mysql索引的实现原理:
https://zhuanlan.zhihu.com/p/27789389
image.png
image.png
图片 1.png
图片 2.png
python finite state machine有限状态机
-https://buildmedia.readthedocs.org/media/pdf/pyfsm/latest/pyfsm.pdf
https://pythonspot.com/python-finite-state-machine/
https://blog.csdn.net/qq_33528613/article/details/78510950
linux压测工具
https://blog.imdst.com/linuxxia-webya-li-ce-shi-gong-ju/
webbench -c 1000 -t 10 http://127.0.0.1:8888
get与post的本质区别
Ajax原理一篇就够了
https://juejin.im/post/5b1cebece51d4506ae71addf
image.png
image.png
从0到1,Python Web开发的进击之路
Vagrant是一个基于Ruby的工具,用于创建和部署虚拟化开发环境
什么情况适合使用LDAP
- 到此为止,似乎真没有什么好说的了,Phabricator, Confluence, Zabbix, Grafana, 禅道等等,几乎你能想到的任何一个第三方应用都会有说明书教你怎么配置dc, cn, ou这些东西,经过了上面这一番折腾,你怎么着也应该对LDAP的一些术语有所了解了,如果还是不行,说明你玩它的时间还是不够长,再多玩两天,也就明白了。配置好之后的好处就是你再也不用东一块西一块地建用户了,而可以在一个统一的地方集中管理你的用户和群组授权。
- (简单粗暴的)分析:如果使用数据库,你准备让使用服务的人如何接入?1给他开数据库的访问权限?那你是不是还得提供准确的sql查询脚本?2在数据库之上,提供一套web服务?那接入方要严格按照你的api对接咯。这样接入方更换认证服务的时候,很可能是不统一的api,想想都麻烦。认证服务是LDAP的话,接入方的平台确认了之后,接入调用的api就是确定的,只要更换服务的地址,目录的信息就可以了,是不是简单很多。
- ldap是树形数据模型的,可以满足复杂的数据访问更简单快速。sql数据库是二维表结构,无法满足这种情况。ldap本身就是索引结构,访问速度非常快,开销也很小,更新较慢。数据库你要自己建立索引,没索引就超慢。ldap没有事务,对外只提供查询,管理者可以进行更新,因此集群部署非常简单,数据库有事务支持,集群部署和数据同步有非常复杂的要求。最典型的ldap应用就是整合异构认证系统,存组织机构内的账号权限之类的东西,为其他各种软硬件提供统一数据访问入口。
https://segmentfault.com/a/1190000014683418
什么是FastCGI
- https://www.jianshu.com/p/0673005835ee
FastCGI像是一个常驻(long-live)型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一次(这是CGI最为人诟病的fork-and-execute 模式)。标准的CGI对每个请求都会执行“PHP解析器会解析php.ini文件,初始化执行环境”这个步骤,所以处理每个请求的时间会比较长。这明显不合理嘛!那么Fastcgi是怎么做的呢?首先,Fastcgi会先启一个master,解析配置文件,初始化执行环境,然后再启动多个worker。当请求过来时,master会传递给一个worker,然后立即可以接受下一个请求。这样就避免了重复的劳动,效率自然是高。而且当worker不够用时,master可以根据配置预先启动几个worker等着;当然空闲worker太多时,也会停掉一些,这样就提高了性能,也节约了资源。这就是fastcgi的对进程的管理。
什么是uwsgi
- https://blog.codeship.com/getting-every-microsecond-out-of-uwsgi/
http://www.bjhee.com/nginx-uwsgi.html
1.通过调整uwsgi的配置以提高Python web应用程序的吞吐量;
2.处理请求;http或者socket,对外暴露端口,支持高并发:
a.通过调整运行进程的数量 uwsgi.ini
3.该wsgi-file选项用于指定要调用的应用程序可执行文件app.py
4.记录日志文件
wsgi协议定义了server与application之间解耦的规范,即可以实现有多个server,也可以实现有多个wsgi application框架,可以选择任意的server和application组合实现自己的web应用。例如uwsgi和gunicorn都是实现了wsgi server协议的服务器。django,flask是实现了wsgi application协议的web框架。可以根据项目实际情况搭配使用。
socket和socketserver
- 套接字的作用之一就是用来区分不同应用进程,当某个进程绑定了本机ip的某个端口,那么所有传送至这个ip地址上的这个端口的所有数据都会被内核送至该进程进行处理。
- 用socket一次只能和一个客户端进行交互,其余的客户端交互需要排队等候,如果想连接多个客户,可以用socketserver实现并发。
socketserver模块简化了网络服务程序的任务,也是Python标准库中很多服务器框架的基础。- socketserver中包含了两种类,一种为服务类(server class),一种为请求处理类(request handle class)。前者提供了许多方法:像绑定,监听,运行…… (也就是建立连接的过程) 后者则专注于如何处理用户所发送的数据(也就是事务逻辑)。
- 这个几个服务类都是同步处理请求的:一个请求没处理完不能处理下一个请求。要想支持异步模型,可以利用多继承让server类继承ForkingMixIn 或 ThreadingMixIn mix-in classes。
ForkingMixIn利用多进程(分叉)实现异步。
ThreadingMixIn利用多线程实现异步。
利用sockerserver实现并发
进程
- 进程就是运行中的程序,系统进行资源分配和调度的基本单位
- 进程的特征就是多道:宏观上并行,微观上串行
多道程序技术- 进程调度算法:
1.先来先服务(不利于短作业)
2.短作业优先调度
3.时间片轮询
4.多级反馈队列- 多进程
在linux/unix操作系统中,使用multiprocessing模块- 进程间通信
1.套接字
2.队列
3.管道
4.信号量
5.共享内存
广播----------相同的网段表示一个广播域,两个不同的广播域是不能进行通信的
单播
组播
路由器
根据信道情况自动选择和设定路由,以最佳路径、按照前后顺序发送信号。ospf路由协议,大企业RIP,静态路由(route)
最短路径优先
OSI七层模型
image
image
封装的过程就是从上至下,将数据进行打包的过程,并且在每一层加上相应的字段进行标识。
image
image
TCP三次握手
ack,syn,fin
image
image
三次握手过程:
跟着动画来学习TCP三次握手和四次挥手
第一次握手:主机A发送建立TCP连接的请求报文,包含随机生成的seq序列号、并将报文中的SYN字段设置为1,表示需要建立TCP连接
第二次握手:
主机B回复,包含seq序列号,回复报文的SYN设置为1,同时产生ACK字段(ack值是在A发送来的seq序列号基础上加1),目的是让A收到信息时,知晓自己的TCP建立请求得到了验证
第三次握手:
A收到B的TCP连接验证请求后,向B发送ACK报文段,建立ESTABLISHED状态,完成三次握手
为什么要三次握手?
防止已过期的连接请求报文突然又传送到服务器,因而产生错误。
image
TCP四次挥手:
image
为什么是四次挥手?
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
(1) TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。
(2) 服务器收到这个FIN,它发回一个ACK确认。
(3) 服务器关闭客户端的连接,发送一个FIN给客户端。
(4) 客户段发回ACK报文确认
ARP协议
作用:
1.通过ip找到mac地址,原理是把消息广播出去,找到对应ip单播回应
2.维护映射的缓存表
补充:
1.ARP是解决同一个局域网上的主机和路由器的IP地址和硬件地址的映射问题
2.ARP进程在本局域网上广播发送一个ARP请求分组,然后本局域网上的所有主机上运行的ARP进程都会收到此请求
3.虽然ARP请求分组是广播发送的,但是ARP响应分组是单播,即从一个源地址发送到一个目的地址
4.局域网内部使用
5.物理地址是数据链路层和物理层使用的地址,IP地址是网络层和以上各层使用的地址
6.如果路由器连接两个网络,则具有两个硬件地址。
7.MAC地址只有本地局域网有效
image
image
用户访问网站的基本流程
1.先找本地的hosts和DNS的缓存表
2.如果没有,则找本地配置的local DNS地址,例如:DNS 8.8.8.8LOCAL
3.LDNS找到目标网站的授权DNS服务器(专门负责解析域名的服务器),找到记录,然后返回给LDNS(本地缓存解析的地址),然后返回给浏览器
4.浏览器拿到网址对应的ip地址,请求相应的服务器,返回结果
4.1 用户拿到ip来找网页服务器,运用tcp/ip协议。首先三次握手,建立socket连接
4.2 三次握手之后,开始建立http请求,http响应(请求报文,响应报文)
4.3 http断开,然后TCP断开,四次挥手
hosts映射
用户访问网站流程框架
用户访问网站主要技术点
C/S和B/S的区别
HTTP协议版本
1.0和1.1
http/1.0
http/1.1
HTTP请求方法
在HTTP通信中,每个http请求报文都包含一个方法,用以告诉web服务器需要执行什么具体的动作,这些动作包括:获取指定的web页面、提交内容到服务器、删除服务器上资源文件等,这些http请求报文中包含的方法被称为HTTP请求方法。常用方法如下:get,put,delete,post,option。
HTTP状态码
200-----服务器成功返回网页
301-----永久跳转,所有请求的网页将永久跳转到被设定的新的位置
403-----forbidden,禁止访问,无权限
404-----NOT Found 服务器找不到客户端请求的指定页面,可能是资源不存在
500-----内部服务器错误,一般是服务器的设置或者内部程序问题导致
502----bad gateway 坏的网关,一般是反向代理服务器下面的节点出问题导致。后端服务不可用或没有完成响应网关服务器
301跳转
301
301重定向的意义
HTTP请求报文介绍
分为:请求报文和响应报文
请求报文
HTTP请求报文由请求行、请求头header、空行和请求报文主体组成
http请求报文
请求行:
包含请求方法get、URL字段(/index.html)和HTTP协议版本
作用:用来说明客户端想要做什么
请求行
请求头部:
请求头部由键值对组成,每行一对,关键字和值用英文冒号“:”分隔。
作用:通知服务器有关于客户端请求的信息
典型的请求头有:
User-Agent:产生请求的浏览器类型。
Accept:客户端可识别的内容类型列表。
Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
请求头
空行:
最后一个请求头部信息之后是一个空行,发送回车符和换行符
作用: 通知web服务器空行以下不会有请求头部的信息了
请求报文主体:
作用:包括了要发送给web服务器的数据信息
请求主体不会应用于HTTP的get命令方法,而是应用于post方法。响应报文
image.png
1.起始行
用来说明服务器响应客户端请求的状况,例如:HTTP/1.1 200 OK
2.响应头部
文件类型、字符集,连接状态等
3.空行
通知客户端空行下无头部信息
4.响应报文主体
包含要返回给客户端的数据,可能是文本,也可能是二进制的(图片、视频)
响应报文
请描述http协议的原理
image.png
image.png
HTTP报文请求应答流程
DNS
1.主要负责把网站域名解析为对应的ip地址
例如:把域名解析为ip,这个从域名到ip的解析过程,称作A记录
2.设置别名
设置CNAME别名记录,这个别名解析功能常被CDN加速服务商应用
3.DNS系统类似于一棵倒挂着的树(和linux系统目录结构类似),它的顶点也是跟,只不过这个顶点使用点(.)来表示,不是目录的根斜线(/)
运输层重要概念:
1.两个主机进行通信本质上市两个主机中的应用进程互相通信,IP协议虽然能把分组送到目的主机,但是这个分组还停留在主机的网络层而没有交付主机中的应用进程。
2.运输层有两个重要功能:复用和分用,复用是指发送方不同的应用进程可以使用同一个运输层协议传送数据,分用是指接收方的运输层在剥去报文的首部后能把数据正确交付给目的应用进程。
3.网络层是为主机之间提供逻辑通信,运输层是为应用进程之间提供端到端的逻辑通信。
4.两个协议:TCP传输控制协议,UDP用户数据报协议
为什么通过端口来标志应用进程?
1.运输层使用协议端口号,简称端口
2.单个计算机的进程是用进程标识符(一个不大的整数)来标志的。
3.不同的操作系统使用不同格式的进程标识符,没有统一格式
4.进程的创建和撤销都是动态的,通信的一方无法识别对方机器上的进程。**
5.我们往往需要利用目的主机提供的功能来识别终点,而不需要知道具体实现这个功能的进程是哪一个
socket
两个主机进行通信本质上市两个主机中的应用进程互相通信,通过ip和端口可以识别对方服务对应应用进程
用户数据报文协议UDP
1.udp只在ip的数据报服务上增加很少的功能,那就是:复用和分用以及差错检测
2.无连接,因此减少了开销和发送数据报之前的时延
3.尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的连接状态。
4.面向报文
发送方的udp对应用程序交下来的报文,在添加首部后就向下交付IP层。
udp对应用层交付下来的报文,既不合并也不拆分,而是保留报文的边界
应用层交给udp多长的报文,udp都照样发送,即一次发送一个报文
报文太长,udp把它交付给IP层,IP层分片,降低了IP层的效率,接收方IP层进行重组
报文太短,交给IP层后会使IP数据报的相对长度太大,也降低了IP层的效率
正式因为udp基于面向报文,完整交付,所以不会出现黏包现象
5.UDP没有拥塞控制
好处:
因此网络出现的拥塞不会使源主机的发送效率降低。针对实时应用场景很重要(qq,直播,视频会议),允许网络发生拥塞时丢失数据,但却不允许数据有太大的时延。udp正好符合要求。
坏处:
udp可能会引起严重的网络拥塞问题,当某一片数据传送中丢失,接收方便无法重组,将导致丢弃整个udp数据帧。
UDP如何进行可靠传输:
实时通信领域存在一个三角平衡关系——成本、质量和时延三者的制约关系
1)尽力可靠:通信的接收方要求发送方的数据尽量完整到达,但业务本身的数据是可以允许缺失的。
2)无序可靠:通信的接收方要求发送方的数据必须完整到达,但可以不管到达先后顺序。
3)有序可靠:通信接收方要求发送方的数据必须按顺序完整到达。
RUDP 的重传是发送端通过接收端 ACK 的丢包信息反馈来进行数据重传,发送端会根据场景来设计自己的重传方式,重传方式分为三类:定时重传、请求重传和 FEC 选择重传。
udp不会发生黏包现象:
1.udp无连接,就没有流的概念
2.面向报文,不会使用块的合并优化算法
3.报文有消息边界
TCP传输控制协议
1.面向连接,提供全双工通信,三次握手,四次挥手
tcp长连接-----定时发送数据包(心跳),以维持连接状态,例如:数据库得连接
tcp短连接-----web网站的http服务,并发量大,但每个用户无需频繁操作的情况
2.可靠交付(无差错,不丢失,不重复,按序到达)
3.面向字节流,容易出现黏包现象
TCP黏包现象
成因:
1.拆包机制,TCP连接的两端都设有发送缓存和接收缓存,当缓冲区长度大于MTU
2.面向字节流的特点,Nagle优化算法,合并小包
3.数据无边界
本质:接收端不知道传送的字节流的长度
解决黏包方法:
1.发送时告知数据量大小
2.struct
原理:长度数字可以被转换成一个标准大小的4字节数字(根据这个特点可以预先发送数据长度)
过程:
1.先发送struct装换好的数据长度4字节(struct.pack()和struct.unpack())
2.再发送数据
TCP可靠传输的工作原理
1.停止等待协议
A发送完一个分组后,暂时保留已发送分组的副本(超时重传时使用)
分组和确认分组都必须进行编号
如果B收到重复的分组,则直接丢弃重复的分组,不向上层交付,同时向A发送确认信号。
2.滑动窗口协议--------实现流量控制
为了提高速度,TCP并没有按照字节单个发送而是将数据流划分为片段。片段内所有字节都是一起发送和接收的,因此也是一起确认的。
对于不按序到达的数据TCP是先临时存放在接收窗口缓存中,等到字节流所缺少的字节收到后,再按照顺序交付上层的应用进程。
3.TCP的拥塞控制
慢开始-------先探测网络情况,由小到大的动态增大拥塞窗口数值
拥塞避免
快重传
快恢复
发送缓存:
1)发送应用程序传送给发送方TCP准备发送的数据
2)保存TCP已经发出但尚未收到确认的数据
接收缓存:
1)存放按序到达,尚未被接受吧应用程序读取的数据
2)为按序到达的数据
总结
也就是说投入的成本、获得的质量和通信的时延之间是一个三角制约 (LEQ) 关系,所以实时通信系统的设计者会在这三个制约条件下找到一个平衡点,TCP 属于通过增大延迟和传输成本来保证质量的通信方式,UDP 是通过牺牲质量来保证时延和成本的通信方式
有关静态网页的架构思想
在高并发、高访问量的场景下做架构优化,涉及的关键环节就是把动态网页转换成静态网页,而不直接请求数据库和动态服务器,并且可以把静态内容推送到前端缓存(或CDN)中提供服务,这样可以提升用户体验,节约服务器和维护成本。
高并发网站架构从动态转为静态的实例
门户新闻业务
门户新闻
视频网站业务
视频业务
电商网站
电商网站
网站流量度量术语(*****)
IP
独立IP数,是指不同ip地址的计算机访问网站时被计算的总次数。衡量网站流量的重要指标。
缺点:用户上网往往是通过NAT转换,因此每次连接网络的IP可能不一样PV(page view)访问量
用户每次访问一个网站页面就计算一个PV
PV是网站被访问的页面数量的一个指标,但不能直接知道有多少人访问了这个网站。
PV
UV(unique visitor)
独立访客,同一个客户端访问网站被计算为一个访客,UV一般是以客户端COOKIE等技术作为统计依据的,实际统计可能会有误差。
考虑到一台客户端可能会有多人使用的情况,因此UV实际上并不一定是独立的自然人访问。
企业网站对IP、PV、UV的度量
通过IP度量
- 分析web服务器日志,对IP地址段去重后计数。
- 在网站的每一个页面结尾,嵌入JS等统计程序代码,待用户加载网页后,IP即传给统计IP的服务器(谷歌统计工具GA)
通过PV统计
PV统计方法
UV
通过客户端http请求报文分析
image.png
- 通过cookie鉴别
image.png
image.png
web服务器
Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以向浏览器等Web客户端提供文档, [1] 也可以放置网站文件,让全世界浏览;可以放置数据文件,让全世界下载。目前最主流的三个Web服务器是Apache Nginx IIS。
常用来提供静态web服务的软件
- Apache和Nginx
常用来提供动态服务的软件
Nginx服务器
- 开源的,支持高性能的,高并发的www服务和代理服务软件。
- 高并发(特别是静态资源),占用系统资源少,功能丰富
- 优秀的web服务软件
- 反向代理负载均衡的软件
- 缓存服务
- 支持具备URI重写功能的Rewrite模块。(实现伪静态)
正向代理和反向代理的区别
NG为什么支持高并发
- nginx采用多进程单线程,非阻塞,异步IO
- 工作原理:https://cloud.tencent.com/developer/article/1031821
- 基于epoll,支持IO多路复用[apache和nginx]
(https://www.cnblogs.com/yum777/p/6244935.html)- Nginx采用的是多进程(单线程)&IO多路复用模型
select和epoll的区别
- select轮询每一个被监听的项,看是否有读操作,监听项越多,效率越低,poll比select监听的多
- IO多路复用,可同时监听多个socket是否活跃
nginx的安装
nginx虚拟主机配置
虚拟主机概念
所谓虚拟主机,在web服务里就是一个独立的网站站点,这个站点对应独立的域名(或端口),具有独立的程序和资源目录,可以独立的对外提供服务供用户访问。
虚拟主机
- 虚拟机主机类型
基于域名、基于ip,基于端口
基于域名的虚拟主机原理是根据请求报文的请求头里的HOST
虚拟主机的配置
- Nginx配置文件nginx.conf重启生效
nginx/sbin/nginx -s reload- Nginx.conf中location
locationfastcgi和wsgi的对比
wsgi的工作方式
- 当Web服务器接收到一个请求后,可以通过Socket把环境变量和一个callback回调函数传递给后端Web应用程序,Web应用程序处理完成后,调用callback函数,把结果返回给WebServer。
这种方式的优点有:
- 异步化,通过callback将Web请求的工作拆解开,可以很方便地在一个线程空间里同时处理多个Web请求
- 方便进行各种负载均衡和请求转发,不会造成后端Web应用阻塞
nginx反向代理与负载均衡
- 反向代理的效果就是负载均衡集群的效果
- 反向代理服务器:Nginx、LVS、Haproxy
- https://www.jianshu.com/p/5f901c55eaec
浅析Nginx的工作模式及原理
- 在Nginx中,连接请求由为数不多的几个仅包含一个线程的进程worker以高效的回环机制进行处理,而每个worker可以并行处理数千个的并发连接和请求。
- Nginx在内部其实是维护了一个accept_mutex,其实就是一个锁,确保在某一时刻,一个请求只能被一个worker进程捕获。当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,这样一个完整的请求就是这样的了。
- 异步/非阻塞/事件驱动
EPOLL模型,提供一种事件驱动机制,它可以监控多个事件是否准备好了,如果准备好了,那么就放入EPOLL队列中。这种机制是异步的。通过这样,WORKER进程只需要循环处理EPOLL队列中的请求,我们只需要在请求间不断切换,而这种切换是不需要付出什么代价的,通过这种循环处理已经准备好的请求,从而Nginx可以高效的处理高并发的问题。
IO模型浅析
IO的本质是socket读取,分为两个阶段:
1.等待网络数据分组到达,然后复制到内核缓冲区
2.数据从内核缓冲区复制copy到进程缓冲区同步阻塞IO(传统IO模型)
- 线程:运行状态,阻塞状态,就绪
客户端每发起一个请求,服务端就会生成一个线程来处理请求,遇到IO就阻塞,如果系统最大的线程数达到瓶颈时,新来的请求就没办法处理了。同步非阻塞IO
- 由于socket是非阻塞的方式,因此用户线程发起IO请求时立即返回。但并未读取到任何数据,用户线程需要不断地发起IO请求,直到数据到达后,才真正读取到数据,继续执行。
- 整个IO请求的过程中,虽然用户线程每次发起IO请求后可以立即返回,但是为了等到数据,仍需要不断地轮询、重复请求,消耗了大量的CPU的资源。一般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。
IO多路复用
- 客户端每发一次请求,服务端并不是每次都创建一个新线程来处理,而是通过IO多路复用技术来处理。就是把多个IO的阻塞复用到同一个select阻塞上,从而使系统在单线程的情况下可以同时处理多个客户端的请求。这种方式的优势是开销小,不用为每个请求建立线程,可以节省系统开销。
- IO多路复用模型是建立在内核提供的多路分离函数select基础之上的,使用select函数可以避免同步非阻塞IO模型中轮询等待的问题。
- 用户首先将需要进行IO操作的socket添加到select中,然后阻塞等待select系统调用返回。当数据到达时,socket被激活,select函数返回。用户线程正式发起read请求,读取数据并继续执行。
- 从流程上来看,使用select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视socket,以及调用select函数的额外操作,效率更差。但是,使用select以后最大的优势是用户可以在一个线程内同时处理多个socket的IO请求。用户可以注册多个socket,然后不断地调用select读取被激活的socket,即可达到在同一个线程内同时处理多个IO请求的目的。而在同步阻塞模型中,必须通过多线程的方式才能达到这个目的。
- 注意:虽然上述方式允许单线程内处理多个IO请求,但是每个IO请求的过程还是阻塞的(在select函数上阻塞),平均时间甚至比同步阻塞IO模型还要长。
select,poll,epoll机制的原理与区别
- select轮询每一个被监听的项,看是否有读操作,监听项越多,效率越低
- poll比select监听的多
- epoll:用户线程只注册自己感兴趣的socket或者IO请求,然后去做自己的事情,等到数据到来时再进行处理,则可以提高CPU的利用率。
epoll事件驱动机制,可以监听多个活跃的socket放入epoll队列中,这种机制是异步的,worker进程只需要处理epoll队列中的请求。异步IO
- IO多路复用是最常使用的IO模型,但是其异步程度还不够“彻底”,因为它使用了会阻塞线程的select系统调用。因此IO多路复用只能称为异步阻塞IO,而非真正的异步IO。
https://www.cnblogs.com/fanzhidongyzby/p/4098546.html
网友评论