STTNet 0.7.0

第 6 章:WorkerPool

本章说明阻塞任务的投递方式,以及请求快照、响应队列、过载拒绝和退出边界。

1. 适合 WorkerPool 的任务

  • 数据库和缓存客户端调用
  • 文件系统、压缩、图片处理
  • 外部 HTTP/RPC 请求
  • 会睡眠或等待不可预测锁的代码

2. 完整 Demo

#include <sttnet.h>

#include <chrono>
#include <iostream>
#include <thread>

int main()
{
    using namespace stt::network;
    using stt::system::ServerSetting;

    if(!ServerSetting::blockTerminationSignals())
    {
        std::cerr << "failed to block termination signals\n";
        return 1;
    }

    HttpServer server;

    // 限制等待中的 Worker 任务数;达到上限时,
    // STTNet 拒绝新任务,而不是让内存无限增长。
    server.setMaxPendingWorkerTasks(4096);

    server.setFunction("/slow",
        [&server](HttpServerFDHandler &client,
                  HttpRequestInformation &request) {
            // Reactor 回调是非阻塞执行点。数据库调用、
            // 文件访问、RPC、sleep 和不可预测的锁等待
            // 应放进 WorkerPool,不能阻塞网络事件循环。
            server.putTask(
                [](HttpServerFDHandler &workerClient,
                   HttpRequestInformation &workerRequest) {
                    // client/request 是 STTNet 提供的安全快照。
                    // 外层回调局部变量的引用在 Worker 执行时可能已经失效。
                    std::this_thread::sleep_for(std::chrono::milliseconds(200));

                    const std::string result =
                        "worker finished for " + workerRequest.loc;

                    // 服务端 Worker 中,sendText() 会把响应交给
                    // Reactor;Worker 不直接写 socket/TLS。
                    return workerClient.sendText(result) ? 1 : -2;
                },
                client,
                request);

            // 返回 0 表示:当前处理阶段转入 WorkerPool 继续执行。
            // 任务返回 1 后,STTNet 会继续执行下一个已注册阶段。
            return 0;
        });

    // 第二个参数是 WorkerPool 线程数,不是 Reactor 数量。
    // 一个 Server 实例使用一个 Reactor 线程推进网络事件。
    if(!server.startListen(8082, 4))
    {
        std::cerr << "failed to listen on port 8082\n";
        return 2;
    }

    std::cout << "WorkerPool demo listening on http://127.0.0.1:8082\n";
    ServerSetting::waitForTerminationSignal();
    return server.close() ? 0 : 3;
}

3. 回调捕获与生命周期

// 外层回调结束后引用可能失效,因此异步任务使用框架提供的快照。
server.putTask([&client, &request] { /* ... */ }, client, request);

// 安全写法使用 STTNet 传给 Worker lambda 的快照参数。
server.putTask([](HttpServerFDHandler &workerClient,
                  HttpRequestInformation &workerRequest) {
    /* ... */
    return workerClient.sendText("done") ? 1 : -2;
}, client, request);

4. 背压和超时

setMaxPendingWorkerTasks() 限制等待任务数。队列过载时框架会拒绝新任务并增加 worker_task_rejections,而不是无限占用内存。

优雅退出无法强制终止已经开始执行的 C++ 用户任务。数据库、RPC、文件和锁等待任务的运行条件包含有限超时与可终止的返回路径。

5. 运行结果

./build/examples/sttnet_worker_pool
curl -i http://127.0.0.1:8082/slow
预期:约 200 ms 后返回 worker finished for /slow,服务仍能同时处理其他连接。