swoole的强大之处,你可能只是略知一二!

news2024/11/15 5:23:48

首先 swoole 是 php 的一个扩展程序

swoole 是一个为 php 用 c 和 c++ 编写的基于事件的高性能异步 & 协程并行网络通信引擎

swoole 是一个多进程模型的框架,当启动一个进程 swoole 应用时,一共会创建 2+n+m 个进程,n 为 worker 进程数,m 为 TaskWorker 进程数,1 个 master 进程和一个 manager 进程,关系如下图所示

Master 进程为主进程,该进程会创建 Manager 进程、Reactor 线程等工作进 / 线程

1、Reactor 线程:

  • 负责维护客户端 TCP 连接、处理网络 IO、处理协议、收发数据

  • 完全是异步非阻塞的模式

  • 全部为 C 代码,除 Start/Shudown 事件回调外,不执行任何 PHP 代码

  • 将 TCP 客户端发来的数据缓冲、拼接、拆分成完整的一个请求数据包

  • Reactor 以多线程的方式运行

2、Worker 进程:

  • 接受由 Reactor 线程投递的请求数据包,并执行 PHP 回调函数处理数据

  • 生成响应数据并发给 Reactor 线程,由 Reactor 线程发送给 TCP 客户端

  • 可以是异步非阻塞模式,也可以是同步阻塞模式

  • Worker 以多进程的方式运行

3、TaskWorker 进程 :

  • 接受由 Worker 进程通过 swoole_server->task/taskwait 方法投递的任务

  • 处理任务,并将结果数据返回(使用 swoole_server->finish)给 Worker 进程

  • 完全是同步阻塞模式

  • TaskWorker 以多进程的方式运行

A: 网络通信引擎

网络通信引擎,是为 php 提供网络通信能力的,传统的 php 程序都是启动 php-fpm,前边再有一层 nginx 或者 apache,打开浏览器访问就 OK,但是从浏览器访问到服务器这一阶段涉及到了网络强求,但是这一阶段跟 php 脚本没有任何的关系,php 只需要处理好数据生成需要展示的内容就完成使命了,声明周期当中,请求到来前和请求完成后都没有 php 脚本什么事,而 swoole 提供的一大能力就是扩展了 php 的生命周期,无需 php-fpm 或者 nginx 或者 apache 之类的工具帮助就可以启动一个 web 服务,并且从服务启动前,启动后,链接进入,请求到来,请求结束,链接切断,服务终止都在 php 脚本的掌控之中,这样的话 php 脚本就会涉及到大量的网络通讯处理,而这个网络通讯处理的能力正是来源于 swoole! 网络通信引擎,是为 php 提供网络通信能力的,传统的 php 程序都是启动 php-fpm,前边再有一层 nginx 或者 apache,打开浏览器访问就 OK,但是从浏览器访问到服务器这一阶段涉及到了网络强求,但是这一阶段跟 php 脚本没有任何的关系,php 只需要处理好数据生成需要展示的内容就完成使命了,声明周期当中,请求到来前和请求完成后都没有 php 脚本什么事,而 swoole 提供的一大能力就是扩展了 php 的生命周期,无需 php-fpm 或者 nginx 或者 apache 之类的工具帮助就可以启动一个 web 服务,并且从服务启动前,启动后,链接进入,请求到来,请求结束,链接切断,服务终止都在 php 脚本的掌控之中,这样的话 php 脚本就会涉及到大量的网络通讯处理,而这个网络通讯处理的能力正是来源于 swoole!

B:基于事件的高性能异步

同步:

就拿读取文件内容来说吧

file_get_contents () 执行完才能执行下边的代码 这样就很容易造成程序的阻塞

否则下边的代码就无法输出文件的内容

传统 php 都是这样阻塞式的顺序执行的

这是常见的同步编程

异步:

代码在执行到 ajax 的时候,函数会直接返回,你马上就可以看到屏幕上打印出的 lol

这就是异步,这样你永远不会被 IO 阻塞,但是它带来了新的问题,在你运行到 lol 之后你就不知道现在代码运行到哪里去了,你只能等待回调被触发,然后屏幕上打印响应的 log, 它的执行不是单层顺序的,而是嵌套的

如果在业务代码当中 这样层层嵌套可读性可想而知

当然这是前端异步请求后端接口

swoole 当中处理异步回调嵌套使用的是协程

你知道什么叫协程吗?你知道线程是干啥的吗?你又知道进程吗?

如果想深入了解 swoole 的强大之处 你还得要了解传统 php 的 lnmp 环境的整套运行机制,这些你都了解吗?

目前 swoole 当中的异步也是协程化的,所以你必须充分理解协程到底是个什么东西!

C:协程

到底什么是协程?

通俗的说,协程就是一段段协作方式执行的程序,协作来完成一件事,协作就是协同作业。我们知道团队协同来做事,比个人单独来做事,效率肯定要高,因为团队协同可以发挥各成员的能动性、优势互补。这是拿人来比喻。我们拿做事来比喻举个例子:比如我们做饭,比如有以下环节洗菜、切菜、烧水、炒菜、煮米饭,人作为主体来操作,那么如果按部就班的做,先烧水,再洗菜,在切菜,再炒菜,再煮饭,那这顿饭要做很长时间比如总共 30 分钟吧,如果我们通过协同方式,先烧水,放灶火上就可以做其他洗菜、切菜的准备,再煮米饭,然后再来洗菜、切菜,再查看煮米饭,再炒菜,…,如此循环往复切换,最后水烧好,米饭也煮好了,菜也炒好了,饭也 OK 了,这样我们耗时可能只有 10-15 分钟,看到了吗,这就是生活中的 “协程”,由人来合理调度安排不同的环节,充分利用各种不同的资源和时间,来达到提高效率。协程是计算机程序,调用的则是不同的程序,处理者主要由 CPU 完成,处理对象是各种 IO 资源,处理的方式是不同的语言编写的程序。我们知道,CPU 可以调度不同的程序,让程序调用不同的 IO 资源,最初的进程是通过 CPU 频繁的切换来完成调用程序的,是操作系统按一定算法分配的时间片抢占被动方式来切换的,未考虑程序实际执行状况,这样切换程序会带来一定问题,而协程作为一种新的工作模式,可以让程序协作方式来执行,在需要使用 CPU 时,交给程序处理,遇到耗时的 IO 资源操作时会让出 CPU,交给处理其他程序,这样互相协作来执行,而不是抢占式的,就像交通规则,大家都遵守按一定规则礼让先行,不随便抢道,协同方式,程序都会执行的良好。

我们来看具体的案例:

go(function () {
    echo "hello go1 \n";
});
echo "hello main \n";
go(function () {
    echo "hello go2 \n";
});

Copy

上面的代码执行结果:

root@b98940b00a9b /v/w/c/p/swoole# php co.php
hello go1
hello main
hello go2

Copy

执行结果和我们平时写代码的顺序,好像没啥区别。实际执行过程:

  • 运行此段代码,系统启动一个新进程

  • 遇到 go(), 当前进程中生成一个协程,协程中输出 heelo go1, 协程退出

  • 进程继续向下执行代码,输出 hello main

  • 再生成一个协程,协程中输出 heelo go2, 协程退出

我们来稍微改一改,体验协程的调度:

use Co;
go(function () {
Co::sleep(1); // 只新增了一行代码
echo "hello go1 \n";
});
echo "hello main \n";
go(function () {
echo "hello go2 \n";
});

Copy

\Co::sleep () 函数功能和 sleep () 差不多,但是它模拟的是 IO 等待 (IO 后面会细讲). 执行的结果如下:

root@b98940b00a9b /v/w/c/p/swoole# php co.php
hello main
hello go2
hello go1

Copy

怎么不是顺序执行的呢?实际执行过程:

  • 运行此段代码,系统启动一个新进程

  • 遇到 go(), 当前进程中生成一个协程

  • 协程中遇到 IO 阻塞 (这里是 Co::sleep() 模拟出的 IO 等待), 协程让出控制,进入协程调度队列

  • 进程继续向下执行,输出 hello main

  • 执行下一个协程,输出 hello go2

  • 之前的协程准备就绪,继续执行,输出 hello go1

到这里,已经可以看到 swoole 中 协程与进程的关系 , 以及 协程的调度 , 我们再改一改刚才的程序

go(function () {
Co::sleep(1);
echo "hello go1 \n";
});
echo "hello main \n";
go(function () {
Co::sleep(1);
echo "hello go2 \n";
});

Copy

我想你已经知道输出是什么样子了:

root@b98940b00a9b /v/w/c/p/swoole# php co.php
hello main
hello go1
hello go2

Copy

协程快在哪?减少 IO 阻塞导致的性能损失

大家可能听到使用协程的最多的理由,可能就是 协程快. 那看起来和平时写得差不多的代码,为什么就要快一些呢?一个常见的理由是,可以创建很多个协程来执行任务,所以快. 这种说法是对的,不过还停留在表面

首先,一般的计算机任务分为 2 种

  • CPU 密集型,比如加减乘除等科学计算

  • IO 密集型,比如网络请求,文件读写等
    其次,高性能相关的 2 个概念

  • 并行:同一个时刻,同一个 CPU 只能执行同一个任务,要同时执行多个任务,就需要有多个 CPU 才行

  • 并发:由于 CPU 切换任务非常快,快到人类可以感知的极限,就会有很多任务 同时执行 的错觉

了解了这些,我们再来看协程,协程适合的是 IO 密集型 应用,因为协程在 IO 阻塞 时会自动调度,减少 IO 阻塞导致的时间损失!

协程在遇到 IO 阻塞的时候会让出 cpu 的控制权,其他协程拿到去执行其他协程的任务,当 IO 阻塞过去之后回过头来继续往下执行!

要点:

  1. 协程在阻塞的时候只是阻塞了当前这个协程 并不会阻塞整个的进程 因为协程是在线程内部的,即使阻塞了也会让出控制权,挂起,等待当前协程的 IO 不阻塞在回过头来继续执行,也就是同步的代码完成了异步的功能!相当强悍!

  1. 从宏观的角度看,程序员搞出来的多个协程在不发生任何协程阻塞的前提是是顺序执行的 一旦发生阻塞 你可以把多个协程理解为并行的 同时在执行的!

  1. 协程是在单进程单线程当中实现的 你可以在里面实现成千上万的协程 并且效果极高! 每个协程去干不同的事!协作制的无需加锁没有抢占,串行的!什么叫串行呢?每次执行一个协程 遇到 IO 阻塞 挂起 执行接下来的程序 可能还是个协程 如果再遇到 IO 阻塞再挂起 继续往下执行 当 IO 阻塞完成回过头来继续往下执行没执行完的协程程序 每次都是一个协程在执行,串行化的!

  1. 协程之间每秒可以进行百万千万次切换! 线程之间切换需要加锁 加锁就很浪费资源!进程间切换更浪费资源,因为上线文很大!更多详细内容请自行百度!

  1. 协程很小切换还快 每秒百万千万级别的切换 所以 一个进程里面 只要你的内存够用 你就可以无止境的创造协程出来干事情!

  1. 事件驱动和异步为 swoole 提供了高性能 而协程解决了异步回调代码嵌套的问题 提高了代码可读性和维护性 也是 swoole 最大的特色!

d:混合服务器

你可以随意创建一个 http tcp websocket http2 服务 并且能轻松承载成千上万的请求

这个可以去官网 看如何创建 http 服务 tcp 服务 websocket 服务

websocket 是 http 升级而来的 创建了 websocket 服务就自带了 http 服务

创建好服务 直接 start 就可以运行一个 http 服务或者其他 tcp 等的服务了 而无需 nginx apache 的任何参与!

有服务端必有客户端 我们可以在代码里面通过

new Swoole\Coroutine\Http\Client(127.0.0.1,9501);

去链接 http 服务器

当然其他的也一样 自己去看手册 这里只是说明 swoole 有多么的强大

e:协程之间通讯 channel

通道(channel)是协程之间通信交换数据的唯一渠道,而协程 + 通道的开发组合即为著名的 csp 编程模型

在 swoole 当中 channel 常用于连接池的实现和协程并发的调度

如图所示 第一个协程执行完成之后我们会往 channel 通道当中 push 一个元素 第二个也是 当然第一个一定是 IO 阻塞的 第二个没有 我们在 for 循环里面 获取 channel 里面的值的时候由于第一个阻塞 $chan->pop () 也是阻塞的 因为整体都是在一个协程里面 只有当大的协程里面的两个小协程都完成了 这里的 $chan->pop 才会执行 接触阻塞 最后才会执行 echo 语句! 这是 swoole 当中协程并发的一个很好的案例应用

f:毫秒定时器

毫秒定时器是异步回调的方式来实现的!

还可以使用协程方式 采用同步阻塞的方式来实现定时器!

之前用 sleep 会阻塞整个进程 现在你在协程里面搞 Co:sleep (0.1) 阻塞的是当前协程 而不会阻塞整个进程!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/399750.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

maven将jar文件上传至本地仓库及私服

maven官方仓库有些依赖并不存在&#xff0c;现在项目都是maven直接获取jar&#xff0c;当maven获取不到时&#xff0c;需要我们把jar上传至maven仓库。已 ImpalaJDBC41.jar 文件为例&#xff0c;如&#xff1a;希望上传后&#xff0c;设置的依赖为&#xff1a;<dependency&g…

数字化工厂装配线生产管理看板系统

电力企业业务复杂&#xff0c;组织结构复杂&#xff0c;不同的业务数据&#xff0c;管理要求也不尽相同。生产管理看板系统针对制造企业的生产应用而开发&#xff0c;能够帮助企业建立一个规范准确即时的生产数据库。企业现状&#xff1a;1、计划不清晰&#xff1a;生产计划不能…

python程序设计基础 实验四

⭐python实验专栏&#xff0c;欢迎订阅与关注&#xff01; ★观前提示&#xff1a;本篇内容为python程序设计实验&#xff0c;代码内容经测试没有问题&#xff0c;但是可能会不符合每个人实验的要求&#xff0c;因此以下内容建议仅做思路参考。 一、实验目的 &#xff08;1&am…

2.webpack loader

webpack默认只能处理 以 .js 为后缀名的文件&#xff0c;其他的文件需要用loader&#xff0c;比如 css-loader 可以打包处理.css相关的文件less-loader 可以打包处理 .less相关的文件babel-loader 可以打包处理webpack无法处理的高级JS语法 目录 1 css-loader 1.1 安装 1…

[学习笔记] 2. 数据结构

数据结构视频地址&#xff1a;https://www.bilibili.com/video/BV1uA411N7c5 数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成。简单来说&#xff0c;数据结构就是设计数据以何种方式组织并存储在计算机中。 比如:列表、集合与字…

“小霞”黄绮珊绮望三十巡回演唱会将于3月18日杭州大剧院震撼开唱!

•中年成名 四十余载静待盛放 歌手黄绮珊&#xff0c;1991年正式进入歌坛&#xff0c;至今已满三十周年。黄绮珊前半生的歌手之路好像并不是那么顺畅。虽然一直有着华语乐坛的顶尖歌唱实力&#xff0c;但在45岁之前&#xff0c;黄绮珊一直处于“歌红人不红”的状态。不少人听过…

postgresql 自动备份 bat实现

postgres数据据备分,用cmd命令有些烦,写了个bat实现 BAT脚本中常用的注释命令有rem、@rem和:: rem、@rem和::用法都很简单,直接在命令后加上要注释的语句即可。例如下图,语言前加了rem,运行BAT时就会自动忽略这个句子。需要注释多行时,每行前面都要加上rem、@rem和::。…

Kalman Filter in SLAM (3) ——Extended Kalman Filter (EKF, 扩展卡尔曼滤波)

文章目录1. 线性系统的 Kalman Filter 回顾2. Extended Kalman Filter 之 DR_CAN讲解笔记2.1. 非线性系统2.2. 非线性系统线性化2.2.1. 状态方程f(xk)f(x_k)f(xk​)在上一次的最优估计状态x^k−1\hat{x}_{k-1}x^k−1​处线性化2.2.2. 观测方程h(xk)h(x_k)h(xk​)在这一次的预测…

企业知识管理应该怎么做?

企业知识管理是指企业利用各种信息技术手段&#xff0c;对企业内部的知识进行收集、整理、分析和传递&#xff0c;以提高企业的知识水平和竞争力。企业知识管理涉及到企业内部的各种知识&#xff0c;包括技术知识、专业知识、经验知识、市场知识等。 企业知识管理的方式可以分为…

DETR目标检测算法学习记录

引言 无论是One Stage中的YOLO还是Two-Stage中的Faster-RCNN&#xff0c;其虽然都在目标检测领域有着一席之地&#xff0c;但无一例外都是基于Anchor的模型算法&#xff0c;这就导致其在输出结果时不可避免的进行一些如非极大值抑制等操作来进一步选择最优解&#xff0c;这会带…

uniCloud基础使用

获取openID云函数use strict; exports.main async (event, context) > {//event为客户端上传的参数console.log(event : , event)// jscode2session 微信小程序登录接口&#xff0c;获取openidconst {code} event;// 云函数中如需要请求其他http服务&#xff0c;则使用uni…

Day912.多环境配置隔离 -SpringBoot与K8s云原生微服务实践

多环境配置隔离 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于多环境配置隔离的内容。 多环境支持&#xff0c;是现在互联网开发研发和交付的主流基本需求。通过规范多环境配置可以规范开发流程&#xff0c;并同时提示项目的开发质量和效率等。 一个公司应该规范…

网络使用情况监控

您的网络是否经常成为网络紧张或带宽瓶颈的牺牲品&#xff1f;瓶颈并不一定意味着带宽不足&#xff1b;它们可能是由占用带宽到严重网络威胁等任何因素造成的。密切监控您的网络并分析带宽使用情况和网络流量对于找到问题的根源非常重要。NetFlow Analyzer是最先进的网络使用情…

Simulink自动化-Matlab脚本自动创建Runnable及mapping

文章目录前言设计Excel模板编写matlab脚本自动添加Function到Simulink模型自动mapping Function与Runnable总结前言 在之前的一篇文章中&#xff0c;介绍了Autosar S/R接口的自动创建及mapping,传送门&#xff1a;Simulink自动化-Matlab脚本自动生成Autosar RTE S/R接口及mapp…

mujoco安装及urdf转xml方法记录

参考 mujoco210及mujoco-py安装 下载适用于Linux或 OSX的 MuJoCo 2.1 版二进制文件 。 将mujoco210的下载的目录解压到~/.mujoco/mujoco210路径下. 注意&#xff1a;如果要为包指定非标准位置&#xff0c;请使用环境变量MUJOCO_PY_MUJOCO_PATH。 验证是否安装成功&#xff08…

springcloud3 fegin服务超时的配置和日志级别的配置2

一 fegin的概述 1.1 fegin的默认超时时间 默认fegin客户端只等待1秒钟&#xff0c;超过1秒钟&#xff0c;直接会返回错误。 1.2 架构图 1.2.1 说明 1.2.2 启动操作 1.先启动9001,9002 eureka 2.启动9003 服务提供者 3.启动9006消费者 1.3 情况验证 1.3.1 正常默认情…

云端IDE:TitanIDE v2.6.0 正式发布

原文作者&#xff1a;行云创新技术总监 邓冰寒 引言 云原生集成开发环境 TitanIDE v2.6.0 正式发布了&#xff0c;一起来看看都有那些全新的体验吧&#xff01; TitanIDE 是一款云IDE, 也称 CloudIDE&#xff0c;作为数字化时代研发体系不可或缺的一环&#xff0c;和企业建设…

C++网络编程(一)本地socket通信

C网络编程(一) socket通信 前言 本次内容简单描述C网络通信中&#xff0c;采用socket连接客户端与服务器端的方法&#xff0c;以及过程中所涉及的函数概要与部分函数使用细节。记录本人C网络学习的过程。 网络通信的Socket socket,即“插座”,在网络中译作中文“套接字”,应…

项目管理必备:如何绘制一份优秀的甘特图?

本文一共分为两部分—— 分享60Excel甘特图模板&#xff0c;简单省事儿分享两种甘特图制作教程&#xff0c;高效快捷 第一部分——60甘特图模板 分享一些项目管理甘特图的模板&#xff0c;省事儿&#xff01;高效&#xff01;简单&#xff01; Excel甘特图表模板自取&#xf…