Skip to content

3)Swoole

🌱 第 1 题(基础认知)

Q1:Swoole 是什么?它解决了什么问题?

📝 标准答案:

Swoole 是一个基于 C 语言编写的 高性能网络通信框架,主要用于 PHP 提供常驻内存、异步非阻塞、协程支持的开发能力。

核心作用:

  • 打破传统 PHP 每次请求即销毁的生命周期;
  • 提供 TCP/UDP/HTTP/WebSocket 服务器;
  • 支持异步 IO(文件、数据库、网络);
  • 内建协程支持(如 Go 一样的并发);
  • 提高性能、并发能力,适合构建微服务、长连接服务、游戏服务、聊天系统等。

🌿 第 2 题(运行机制)

Q2:Swoole Server 有哪几种运行模式?各自的适用场景是什么?

📝 标准答案:

Swoole 提供两种主要运行模式:

模式描述适用场景
Base 模式所有请求都在单进程中处理,适合调试或低并发环境开发调试、单任务
Process 模式(默认)启用多进程模型,主进程 + 管理进程 + worker/task 等子进程高并发、生产环境推荐

子进程类型:

  • Master 进程: 接收客户端请求;
  • Manager 进程: 管理 worker 和 task 进程;
  • Worker 进程: 处理请求逻辑(onReceive、onRequest);
  • Task 进程: 异步任务投递和处理(如发送邮件、写日志等)。

每个进程都是常驻内存的,不销毁,性能远超 FPM 模式。

🌳 第 3 题(协程和异步)

Q3:Swoole 如何实现协程?它与传统的异步写法有什么不同?

📝 标准答案:

Swoole 使用的是 C 语言实现的协程调度器,在 PHP 层提供了轻量级的用户态线程,通过 go {} 启动,支持自动协程调度和 IO Hook(自动协程切换)。

优势对比:

项目传统异步(callback)Swoole 协程
编码风格回调地狱,嵌套复杂同步风格,代码简洁
异常处理不方便 try-catch支持标准 try-catch
并发支持需要额外调度逻辑go() 一键开启并发
开发效率
性能较高更高(协程调度代价低)

例子:

php
go(function () {
    $client = new Swoole\Coroutine\Http\Client('127.0.0.1', 80);
    $client->get('/');
    echo $client->body;
});

等同于同步风格写法,但底层是异步非阻塞执行。

🌲 第 4 题(实战能力)

Q4:如何基于 Swoole 搭建一个 HTTP 服务?并实现一个异步任务(如异步记录日志)?

📝 标准答案:

1. 创建 HTTP 服务:

php
$http = new Swoole\Http\Server("0.0.0.0", 9501);

$http->on("request", function ($request, $response) {
    $response->end("Hello Swoole");
});

$http->start();

2. 使用异步 Task 实现日志写入:

php
$server = new Swoole\Http\Server("0.0.0.0", 9502);

$server->set([
    'task_worker_num' => 2,
]);

$server->on("request", function ($request, $response) use ($server) {
    $server->task([
        'type' => 'log',
        'data' => 'User accessed at ' . date('Y-m-d H:i:s'),
    ]);
    $response->end("Request received");
});

$server->on("task", function ($server, $task_id, $from_id, $data) {
    if ($data['type'] === 'log') {
        file_put_contents('access.log', $data['data'] . PHP_EOL, FILE_APPEND);
    }
});

🪵 第 5 题(资源与性能管理)

Q5:Swoole 中如何避免内存泄漏与资源泄露?生产环境需要做哪些准备?

📝 标准答案:

避免内存/资源泄露的关键点:

  1. 禁止使用全局变量持久保存请求数据;

    • 每个请求数据(如 $request)都应及时释放;
  2. 使用 defer() 注册资源释放操作:

    • 类似于 Go 的 defer,用于释放文件句柄、连接等;
    • 示例:
      php
      go(function () {
          $fp = fopen('log.txt', 'r');
          defer(function () use ($fp) {
              fclose($fp);
          });
      });
  3. 长连接(如 Redis、MySQL)使用连接池,避免频繁创建销毁;

  4. 每隔 N 次请求,定期重启 Worker 进程(可配置 max_request);

生产环境部署注意事项:

  • 使用守护进程运行(daemonize => true);
  • 配置 log_file 查看运行日志;
  • 结合 Supervisorsystemd 保证服务自动拉起;
  • 配置 task_worker_num 根据 CPU 核数调整;
  • 使用 opcache 提高代码执行效率;
  • 开启 open_http2_protocol 支持 HTTP2(如需要);
  • 使用协程客户端(如 Redis、MySQL)提高异步性能;
  • 监控内存、负载、连接数等指标。