Swoole扩展的6种模式深入详解


Posted in PHP onMarch 04, 2021

前言

并发问题可以理解为两个问题

  • 并发连接数,就是支持同时接受多少客户端TCP连接
  • 并发请求数,每秒能处理多少请求

Swoole底层基于epoll,所以第一个问题在Swoole扩展中实际上不存在任何问题。使用Swoole可以轻松应对10万甚至100万长连接。开发者唯一需要做的就是修改

ulimit -n

将系统最大文件描述符改为 10万或更大。

不同的模型每秒能处理多少请求数,这个是应用层需要考虑的问题。而且不同的场景下有些模式无法使用。真正的难题就是在这里。实际上

工具永远是死的,而人是活的。

再复杂艰难的场景也阻挡不了聪明的工程师。合理利用Swoole提供的各项功能可以巧妙解决各种难题。

第一 Worker同步阻塞

这个模式的使用方法:

  • swoole_server设置为SWOOLE_PROCESS
  • 只使用Worker进程
  • 根据不同的情况设置worker_num的数值
  • 设置dispatch_mode参数为1或3
  • Worker进程内使用同步阻塞的代码编写方式,这里不使用任何异步IO接口

这个模式的瓶颈就在与onRequestonReceive里代码逻辑的处理速度。按照快慢可以分为几种

  1. 外网CURL调用。这个最慢,快的数百毫秒,慢的情况可能需要几十秒
  2. 内网RPC或Http接口,这个取决与这个接口的速度
  3. MySQL复杂查询,一条SQL如果没有索引可能需要几百毫秒,甚至几秒或更长时间。而如果是主键查询或者索引足够有效可能只需要几毫秒
  4. Redis/Memcache,内存数据库局域网而且是长连接,调用一次可能只需要几百微秒也就是0.x毫秒就能返回
  5. 读取磁盘文件,普通机械磁盘未命中PageCache引起磁盘寻道,可能需要几十毫秒。SSD磁盘速度就快多了几毫秒即可完成随机读取。
  6. 内存文件系统或共享内存,读取/tmp或/dev/shm下的共享文件本质上是读取共享内存,仅需几微妙到几十微秒即可完成。如果是直接读共享内存可能更快,纳秒级别。

进程数量

根据上面的IO耗时,设置适当的进程数量即可。

  • IO很慢就设置几百个Worker进程,如操作MySQL、CURL、大量读写磁盘
  • IO很快就可设置少量进程,如操作Redis、内存文件系统、共享内存

投递模式

如果请求是无状态的可以使用dispatch_mode=1或3,轮循投递或者区分忙闲投递。

长连接应用

比如聊天室,网络游戏。连接之间需要交互的应用。 可以使用 MySQL/Redis/文件 存储用户的连接fd,分组信息。要向某个用户发数据可以根据UID查出对应的fd,发送数据即可。发送分组,可以根据分阻ID查询出fd列表,循环发送数据即可。

第二 Worker非阻塞+Task

这种模式是典型的同步+异步,复杂的业务逻辑使用同步阻塞在Task进程中处理,简单要求高并发的逻辑使用异步非阻塞在Worker进程中处理。

使用方法

  • 使用SWOOLE_PROCESS模式
  • dispatch_mode 设置为2(默认就是2,可不做任何设置)
  • worker_num 设置为CPU核数
  • task_worker_num 根据业务逻辑的耗时情况进行设置,如果平均耗时较长,需要设置数百个进程,耗时较短可设置几十个进程

Worker进程

在这个模式中,Worker进程不能有任何同步阻塞的操作,只处理请求响应或数据接收发送,仅进行PHP数组或对象操作或其他计算逻辑。具体参考 模式3 Worker进程全异步。

Task进程

无状态地处理任务,并返回结果。需要注意单个Task的执行时间,避免处理时间太长导致Task排队过多。

第三 Worker全异步

这个模式就是真正的异步非阻塞编程,在代码中只能使用Swoole提供的异步非阻塞IO操作,不得执行任何普通的PHP阻塞IO函数,如curl、mysql、redis、fsockopen、stream、socket、proc_open等。

与模式二 不同的是全异步服务器不使用Task进程,即使是很复杂的业务逻辑也在Worker进程中执行。纯异步编程需要对开发者要求较高。

使用方法

  • dispatch_mode设置为2
  • worker_num 设置为CPU核数

逻辑实现

Worker进程内的PHP代码只能进行下列3种操作:

  • 使用swoole_redis、swoole_mysql、swoole_http_client、swoole_client+async操作
  • 进行PHP数组、对象操作或其他内存计算逻辑
  • 使用swoole_server的send、push、close、response->end等操作

适用场景

  • 长连接服务
  • 对并发能力和吞吐量有较高要求
  • 团队开发者技术水平较高

弊端和解决方案

  • 纯异步需要使用嵌套回调的方式编写代码,与传统的编程模式完全不同,异步是事件驱动式的,代码不是顺序执行的。
  • 异步嵌套回调的方式在程序逻辑复杂后会变得难以维护

可使用 Promise 或 Yield/Generator 简化异步编程。

第四 Base模式+同步阻塞

Base模式是一个简化版本,Base模式下Swoole的运行原理与Node.js完全一致,是单线程的。对TCP客户端的Accept、Send、Recv、Close都是同一个进程内操作的。

与Process同步阻塞模式不同的是BASE模式下Worker进程的调度由操作系统实现。因此可以实现一个Leader-Follower模式的服务器程序。

使用方法

  • 使用SWOOLE_BASE模式
  • worker_num根据逻辑代码的耗时情况设置几百或几十
  • worker进程内使用同步阻塞IO操作

适用场景

  • 适合短连接 & 请求响应式 服务,如Web服务、RPC服务
  • 这种模式不能实现单连接并发,客户端的连接被某个Worker进程Accept之后,只能在此进程内处理请求

第五 Process

Process提供了对进程管理的封装。基于Process可实现:

多进程+进程间通信编程

将其他语言编写的程序包装为子进程,重定向标准输入输出到管道,与该程序进行通信。可实现任意编程语言为我PHP所用。

第六 sendMessage

到此这篇关于Swoole扩展的6种模式深入详解的文章就介绍到这了,更多相关Swoole扩展的5种模式内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

PHP 相关文章推荐
解决控件遮挡问题:关于有窗口元素和无窗口元素
Jan 28 PHP
php 用checkbox一次性删除多条记录的方法
Feb 23 PHP
PHP的explode和implode的使用说明
Jul 17 PHP
php切割页面div内容的实现代码分享
Jul 31 PHP
PHP时间格式控制符对照表分享
Jul 23 PHP
php传值赋值和传地址赋值用法实例分析
Jun 20 PHP
示例详解Laravel的注册重构
Aug 14 PHP
php array_key_exists() 与 isset() 的区别
Oct 24 PHP
php 函数使用可变数量的参数方法
May 02 PHP
详谈PHP中public,private,protected,abstract等关键字的用法
Dec 31 PHP
php 处理png图片白色背景色改为透明色的实例代码
Dec 10 PHP
php框架CI(codeigniter)自动加载与自主创建对象操作实例分析
Jun 06 PHP
php中Swoole的热更新实现代码实例
Mar 04 #PHP
PHP安装扩展mcrypt以及相关依赖项深入讲解
Mar 04 #PHP
PHP实现页面静态化深入讲解
Mar 04 #PHP
php实现对短信验证码发送次数的限制实例讲解
Mar 04 #PHP
swoole锁的机制代码实例讲解
Mar 04 #PHP
PHP实现chrome表单请求数据转换为接口使用的json数据
Mar 04 #PHP
windows系统php环境安装swoole具体步骤
Mar 04 #PHP
You might like
ZF等常用php框架中存在的问题
2008/01/10 PHP
PHP中json_encode、json_decode与serialize、unserialize的性能测试分析
2010/06/09 PHP
9条PHP编程小知识及易犯的小错误
2015/01/22 PHP
Laravel与CI框架中截取字符串函数
2016/05/08 PHP
Thinkphp5.0 框架的请求方式与响应方式分析
2019/10/14 PHP
PHP 代码简洁之道(小结)
2019/10/16 PHP
js压缩工具 yuicompressor 使用教程
2010/03/31 Javascript
jQuery源码中的chunker 正则过滤符分析
2012/07/31 Javascript
JS通过分析userAgent属性来判断浏览器的类型及版本
2014/03/28 Javascript
禁止iframe页面的所有js脚本如alert及弹出窗口等
2014/09/03 Javascript
AngularJS基础学习笔记之指令
2015/05/10 Javascript
js+css简单实现网页换肤效果
2015/12/29 Javascript
js父页面中使用子页面的方法
2016/01/09 Javascript
浅谈javascript中的数据类型转换
2016/12/27 Javascript
js实现简单的获取验证码按钮效果
2017/03/03 Javascript
JS计算两个时间相差分钟数的方法示例
2018/01/10 Javascript
Vuejs2 + Webpack框架里,模拟下载的实例讲解
2018/09/05 Javascript
详解Vue组件之间通信的七种方式
2019/04/14 Javascript
JS实现返回上一页并刷新页面的方法分析
2019/07/16 Javascript
如何利用 JS 脚本实现网页全自动秒杀抢购功能
2020/10/12 Javascript
[02:43]DOTA2英雄基础教程 圣堂刺客
2013/12/09 DOTA
用Python输出一个杨辉三角的例子
2014/06/13 Python
python结合shell查询google关键词排名的实现代码
2016/02/27 Python
python3操作mysql数据库的方法
2017/06/23 Python
Python实现购物程序思路及代码
2017/07/24 Python
Python基于递归算法求最小公倍数和最大公约数示例
2018/07/27 Python
Win10下python3.5和python2.7环境变量配置教程
2018/09/18 Python
在python 中实现运行多条shell命令
2019/01/07 Python
python pycharm最新版本激活码(永久有效)附python安装教程
2020/09/18 Python
俄罗斯天然和有机产品、健康生活网上商店:Fitomarket.ru
2020/10/09 全球购物
国旗下讲话演讲稿
2014/05/08 职场文书
党员群众路线剖析材料
2014/10/08 职场文书
初中学生操行评语
2014/12/26 职场文书
pytest进阶教程之fixture函数详解
2021/03/29 Python
使用pandas生成/读取csv文件的方法实例
2021/07/09 Python
python垃圾回收机制原理分析
2022/04/13 Python