swoole学习第七讲(学习swoole需要掌握的知识)
轮询、长轮询、长连接、单工、全双工、半双工区别
-
轮询
:客户端发送request请求,服务端回应response响应,连接关闭,循环往复 -
长轮询
:客户端发送request请求并设置较长的超时时间,服务端在一段时间内查询(比如循环10此,每次循环sleep 1s),该请求10秒后返回,如果在这段时间内查询到,服务器将立即返回,客户端重新发起新的请求 -
长连接
:双方建立起连接不断开,如果有新的数据需要传输,则直接复用这个连接,无需再建立一个新的连接 -
短连接
: 双方建立连接后,数据传输完就断开,如果需要继续发送数据,则还需要继续建立新的连接 -
单工
:一方只能发信息,另一方则只能收信息,通信是单向的。 -
半双工
:双方都能发信息,但同一时间则只能一方发信息。 -
全双工
:双工在同一时间可以互相发送消息
socket、websocket、http之间的关系
TCP/IP分层模型-
socket
: 是位于应用层
和传输控制层(tcp/ip层)
之间的一层抽象出来的接口(interface)
,接口
如果想要被人使用那么需要具体的实现类(class)
去实现,socket
适用于多种网络协议,主流的就是tcp/ip,我们按照socket接口规范
实现对tcp/ip协议的封装,我们把这种规范
叫做socket
-
websocket
andhttp
差异 | websocket | http |
---|---|---|
数据传输方式 | 双工 | 单工 |
消息模式 | request/response | bi-direction(双向) |
服务器推技术 | 天生不支持 依靠长轮询或流技术实现 |
默认支持 |
开销 | 每个请求开销适中 | 建立连接开销适中 后续发送消息最小化开销 |
连接方式 | 长连接(协议本身实现) | http1.0短连接/http1.1长连接 利用的是tcp/ip层面实现的长连接) |
媒介/优势 缓存 | 不可能支持 | 核心特性 |
基于协议 | TCP/IP | TCP/IP |
通信模型 | socket | socket |
协议层次 | 应用层协议 | 应用层协议 |
可靠性 | 可靠 | 可靠 |
依赖关系 | 依赖http协议 靠http头转换为websocket协议 |
不依赖 |
适用场景 | 实时性高 | 不需要实施更新/高度可缓存 |
支持范围 | 广泛支持 | 现代语言、客户端 |
并行、并发、同步、异步、阻塞、非阻塞、进程、线程、CPU核心之间的关系
-
CPU核心
:是指物理上,也就是硬件上存在着几个核心。比如,双核就是包括2个相对独立的CPU核心单元组,四核就包含4个相对独立的CPU核心单元组。 -
进程
:是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的基本单位。 -
线程
:是进程的一个执行单元,是进程内科调度实体。比进程更小的独立运行的基本单位。线程也被称为轻量级进程。
进程、线程关系 -
并行
:同一时刻
(比如3:00这一个时刻)执行多个任务,比如我们的电脑是4核心的,最少同时可以支持4个线程同时运行(intel超线程技术一个核心可以模拟多个线程) -
并发
:一段时间内
(比如3:00~~4:00)执行多个任务,同一时刻只有一个任务在执行,只是因为CPU执行太快了,我们没有感觉到 -
同步IO
:同步IO
整个过程进程(Process)会被阻塞,直到内核(Kernel)同步IO
操作被完成,内核(Kernel)返回执行结果,进程(Process)解除阻塞 -
异步IO
:异步IO
整个过程进程(Process)不会被阻塞,当内核执行IO任务完成时,内核(Kernel)会主动发送完成回调(信号)给进程(Process),告诉进程(Process)执行完了,期间IO任务靠内核(Kernel)来完成,和进程(Process)没有关系 -
阻塞IO
:阻塞IO
整个过程进程(Process)会被阻塞,直到内核(Kernel)阻塞IO
操作被完成,内核(Kernel)返回执行结果,进程(Process)解除阻塞 -
非阻塞IO
:非阻塞IO
只有当内核(Kernel)执行真正的IO操作时才会被阻塞,在执行非IO操作时并不会阻塞IO,执行IO操作是靠进程(Process)不断的去询问,最终内核(kernel)去执行,等待IO完成后一并返回给进程(Process)执行结果,解除进程(Process)阻塞
阻塞/非阻塞侧重说明IO过程中进程的状态,同步/异步侧重说IO完成后进程获取结果的一个方式
办港台通行证可以去出入境大厅办,也可以在网上办,办完后直接寄给你。
- 异步IO(网上办):网上填好资料,其他的你就不用管了,该干嘛干嘛。直到收到通行证。OK,你现在可以去香港澳门嗨了。
- 大厅办,又可以分两种情况:
- 阻塞IO(排队等候):在排队的过程中你不能跑去做其他事情了吧。直到排到你了,你就和办证的美女姐姐完成办证过程,这个过程你也是离开不了。
- 非阻塞IO(叫号等候):人民政府觉得办证要人性化,所以采用了叫号机制。你拿了号以后,可以在大厅中呆着时不时看看大屏幕是不是排到你了,或者出去抽根烟逛个街看个美女,再回来看看是不是排到你了。直到排到你了,你就需要到窗口完成办证过程了。
- IO多路复用(雇人排队): 假设有一个人只要给他钱,他就可以拿着你的号替你排队,但是办证过程需要你本人。所以排到你的号了,他就打个电话叫你回来办。这样你就可以同时帮你爸妈三姑六婆等等办通行证一起办了。这就是IO多路复用了,你街也逛得爽了,美女也看够了,还能同时办多个通行证,这过程简直爽呆。但就是需要另外付给号阪机构钱,开销比自己排队多了。
- 所以上面几种方式中,异步IO最省事,IO多路复用也挺好用的,只不过多了一次系统调用的(select/poll/epoll)开销。
- 详细参考https://blog.csdn.net/historyasamirror/article/details/5778378
为什么有HttpServer、WebSocketServer、TcpServer、UdpServer,它们之间的关系是什么,该选择什么?
HttpServer
:应用层协议,对传输层协议在封装,遵循http协议
WebSocketServer
: 应用层协议,对传输层协议在封装,基于http协议,遵循websocket协议
TcpServer
传输层协议
UdpServer
: 传输层协议
如下图,顶层为应用层,中间通过socket抽象层关联到传输层
总结:
Http
/websocket
协议是基于传输层tcp
/udp
协议实现的传输层协议,更加方便开发人员使用,应用层协议能实现的,通过传输层协议也能实现,在以快速实现功能的前提下,当让挑最简单的来使用了,如果你不想加班的话。同理,这些server是相应协议的实现,websocket支持长连接,http不支持长连接,根据对应的业务选择相应的server
- 举个例子
TCP实现了Socket接口,而TCP是面向stream传输的,直接用Socket容易出问题,比如粘包问题。WebSocket是一个应用层协议,更抽象,不需要考虑这些问题。所以当然可以直接用Socket实现长连接,不过仍然需要实现自己的上层协议来处理分包,比较麻烦,不如直接用WebSocket。自己的客户端使用自己的私有协议还行,但浏览器的话更需要一个统一的应用层协议,所以WebSocket就出现了。
IO/CPU之间的关系
- 计算机硬件上CPU通过DMA来访问磁盘等IO,也就是请求发出后,CPU就不再管了,直到DMA处理器完成任务,再通过中断告诉CPU完成了。所以,单独的一个IO时间,对CPU的占用是很少的,阻塞了就更不会占用CPU了,因为程序都不继续运行了,CPU时间交给其它线程和进程了。虽然IO不会占用大量的CPU时间,但是非常频繁的IO还是会非常浪费CPU时间的,所以面对大量IO的任务,有时候是需要算法来合并IO,或者通过cache来缓解IO压力的。
总结:在涉及到IO操作时,CPU是只管发IO指令的,具体的读取、并将读到的信息处理是硬盘自己自己来实现的,DMA是跑腿的
协程
-
协程
:协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。总结下来相当于实现了一个内核调度器,这个内核调度器在操作系统层面上是抢占式的,但是协程所实现的调度器是协同式。
众所周知swoole和go都实现了协程,但是两者之间还是有些不同的,详见swoole官网介绍 https://wiki.swoole.com/wiki/version/?id=1018&version=5
在编程中,会遇到IO密集型和CPU密集型这两种情况
swoole为什么线程安全:swoole一个进程下同时只有一个线程在执行任务,当任务类型为CPU密集型时,因为只有一个线程,所以在操作堆(heap)数据时不需要使用锁,go语言时多线程,操作堆(heap)数据时多个线程需要加锁,由于swoole设计的原因,所以时线程安全的,但是执行IO密集操作这又是另一回事了,需要为了保证数据的一致性,还是要加锁,比如数据库的行锁等。