核心主线:Swoole协程属于用户态轻量级协程,由Swoole扩展在PHP层实现调度,不依赖操作系统内核线程;依托IO多路复用epoll,IO阻塞时自动切换协程,实现单进程高并发。

一、协程基础核心术语

  1. 协程 Coroutine(Coro)
    本质:用户态的轻量执行流,在同一个操作系统线程内调度,切换不需要内核态上下文切换。
    作用:一个Worker进程内,可创建成千上万个协程,处理大量并发请求。遇到协程化IO(Redis、MySQL、HTTP客户端)自动挂起,让出执行权,其他就绪协程继续运行。
    要点:协程不是操作系统线程,内核完全感知不到协程;只有Worker进程、线程对内核可见。
    关联:协程调度器、yield。

  2. 协程调度器 Coroutine Scheduler
    本质:Swoole内置的调度器,运行在Worker进程的单一线程中。
    作用:管理所有协程,负责协程的创建、挂起、恢复、销毁;IO事件就绪后唤醒对应协程。
    要点:单线程调度,同一时刻,一个Worker内只有一段协程代码在CPU上执行。

  3. 协程上下文 Coroutine Context
    本质:保存协程运行现场的内存结构,保存当前函数调用栈、寄存器、局部变量。
    作用:协程挂起时,保存现场;恢复执行时,读取现场继续运行。
    要点:协程切换,本质就是切换这块上下文,开销远小于操作系统进程/线程上下文切换。每个协程拥有独立栈。

  4. 协程栈 Coroutine Stack
    本质:每个协程独立的内存栈,存放函数局部变量、函数调用帧。
    作用:协程切换时,栈跟着上下文保存。
    要点:Swoole默认协程栈有固定大小,大量递归会栈溢出;和操作系统线程栈不是一回事。

  5. 主协程 / 根协程 Main Coroutine
    本质:Worker进程启动后默认的执行流。
    作用:用来监听事件、创建子协程。
    要点:业务HTTP/WebSocket请求,都是在主协程里创建子协程处理。

  6. 子协程 Child Coroutine
    由主协程go()创建出来的业务协程,用来处理单次请求、单次IO任务。
    go(function(){}) 就是创建子协程。

二、协程状态与切换术语

  1. 挂起 Suspend
    本质:协程遇到协程化IO阻塞,主动让出CPU执行权,保存上下文,进入等待状态。
    作用:不会阻塞整个Worker线程,调度器切换执行其他就绪协程。
    例子:协程调用协程版MySQL查询,网络IO未返回 → 协程suspend。

  2. 恢复 Resume
    IO事件就绪,调度器找到被挂起的协程,加载上下文,继续从暂停位置执行代码。

协程核心:suspend + resume,完成切换。

  1. 就绪状态 Ready
    协程已经完成等待,可被调度器选中上CPU执行。

  2. 运行状态 Running
    协程正在CPU执行代码。

  3. 终止状态 Dead
    协程代码执行完毕,自动销毁,释放协程栈内存。

  4. 非抢占式调度
    Swoole协程调度模式。只有协程主动suspend(IO阻塞)才会切换,不会像操作系统线程那样,由内核按时间片强制打断。
    要点:如果代码存在同步阻塞代码(sleep、非协程curl、同步文件IO),协程不会主动让出CPU,整个Worker卡住,所有协程全部阻塞。这是高频踩坑点。

三、IO事件与底层联动术语

  1. 事件循环 EventLoop
    本质:Swoole Worker内部的epoll事件循环,协程调度器依托EventLoop。
    作用:监听所有socket的可读、可写事件;IO事件到达,通知协程调度器resume对应的协程。
    要点:EventLoop和协程调度器绑定,是协程异步IO的根基。

  2. 协程化客户端(Coroutine Client)
    Swoole封装的协程版客户端:Co\Mysql、Co\Redis、Co\Http\Client。
    本质:底层封装socket,IO等待时自动suspend当前协程。
    要点:必须使用协程化客户端,普通同步客户端不会触发协程切换,会阻塞Worker。

  3. IO多路复用 epoll
    操作系统内核提供的事件监听能力。EventLoop底层依赖epoll,一次性监听大量socket文件描述符。
    关联:前面Socket、TCP的知识点。

  4. 文件描述符 fd
    网络连接、文件在内核中的标识,EventLoop监听fd事件。

四、协程并发安全术语

  1. 协程竞态条件(Race Condition)
    本质:同一个Worker内多个协程,并发读写同一块进程内共享内存变量,执行顺序不可预测,产生脏数据。

重点:不同Worker进程内存隔离,不存在这个问题;同一Worker内部协程共享内存,会出现竞态。

  1. 协程锁 Co\Lock
    Swoole提供的协程专用锁,用于协程之间互斥访问共享变量。
    要点:协程锁是用户态锁,只作用于当前Worker内的协程,不能跨Worker进程。

  2. 协程通道 Channel(Co\Channel)
    协程之间通信的工具,生产者-消费者模型,协程安全。
    作用:协程之间传递数据,自带阻塞等待,可做协程间同步,替代锁。
    要点:Channel仅在同一个Worker进程内生效,不能跨进程。

  3. 协程局部变量 Coroutine Local(CID静态隔离)
    Co::getCid() 获取协程唯一ID。利用协程ID做数据隔离,模拟协程私有变量。
    要点:PHP全局/静态变量是进程维度共享,不是协程私有;必须手动基于CID隔离,否则多协程覆盖数据。

  4. 协程ID CID
    每个协程唯一编号,同一个Worker内唯一;不同Worker协程CID会重复。

五、协程生命周期与API术语

  1. go()
    创建协程的入口函数,传入回调函数,立即创建并交由调度器调度。
go(function(){
    // 子协程业务代码
});
  1. co::sleep()
    协程版休眠,不会阻塞Worker,只是挂起当前协程,其他协程继续跑。
    区分:原生sleep()是同步阻塞,卡住整个Worker。

  2. defer
    协程延迟回调。协程结束之前,自动执行defer注册的函数。类似资源释放、关闭连接。
    作用:协程无论正常结束还是抛出异常,defer代码都会执行,用来释放数据库连接、关闭句柄。

  3. 协程退出/异常
    协程内部抛出未捕获异常,当前协程终止,不会导致整个Worker进程崩溃(Swoole新版本)。

六、协程限制与坑点术语

  1. 协程上下文污染
    同一个Worker,多个协程共用进程资源。例如全局静态变量、单例对象,协程并发修改互相覆盖。

面试高频坑:很多人把Swoole协程和PHP-FPM请求隔离混淆。PHP-FPM每个请求是独立进程天然隔离;Swoole同一个Worker协程共享全局变量。

  1. 同步阻塞陷阱
    调用非协程化阻塞函数,不会触发协程切换,整个Worker线程卡住,所有协程暂停。
    典型:sleep()、file_get_contents同步读文件、普通curl。

  2. 协程嵌套
    协程内部继续go创建新协程,支持嵌套。

  3. 最大协程数 max_coroutine
    配置项,单个Worker进程允许创建的协程上限,防止创建海量协程耗尽内存。

七、进程 vs 协程术语横向对照

  1. 进程:操作系统内核管理,有独立虚拟地址空间,切换成本高;进程间内存隔离,靠IPC通信。
  2. 协程:Swoole用户态调度,共享所属Worker进程的地址空间;切换成本极低;同Worker内协程共享内存,存在竞态。

八、高频易混术语庖丁拆解

  1. 协程锁 vs 操作系统互斥锁
    协程锁:用户态,仅阻塞协程,不会阻塞整个线程;只在当前Worker内生效。
    操作系统锁:内核态,阻塞整个线程,可跨进程。

  2. Channel vs 共享内存
    Channel:协程内消息传递,协程安全,仅同Worker。
    共享内存shm:跨进程共享内存,需要自己加锁,不是协程原生能力。

  3. co::sleep() vs sleep()
    co::sleep:协程挂起,Worker不阻塞;
    sleep:内核系统调用,阻塞整个Worker线程,所有协程全部暂停。

  4. CID协程ID vs PID进程ID
    PID:操作系统进程编号,内核可见;
    CID:Swoole内部协程编号,内核完全不知道。

九、完整执行链路串联

Worker进程启动,开启EventLoop事件循环(epoll);
收到HTTP请求,go()创建子协程;
协程执行业务,调用协程Redis客户端发起网络请求;
socket等待数据包,协程自动suspend挂起,调度器切换其他协程执行;
Redis数据返回,epoll触发可读事件,调度器resume恢复该协程;
协程拿到数据,继续执行业务,返回HTTP响应;
协程执行完毕自动销毁,defer回调执行,释放资源。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐