中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

PHP "真異(yi)步(bu)" TrueAsync SAPI 與 NGINX Unit 集成

PHP "真異步" TrueAsync SAPI 與 NGINX Unit 集成

現在的(de) Web 開發(fa)和過去最大(da)的(de)區(qu)別是什(shen)么?一(yi)句話:沒(mei)人(ren)再愿意等服務器響應(ying)了。

七八年前,甚至更早的時候(hou),模塊(kuai)加(jia)載、組件打包、腳本解釋、數據(ju)庫查詢——這些步驟慢一(yi)點,對業(ye)務(wu)和用(yong)戶也不會造成太大影響。

現(xian)在不一樣了。Web 開(kai)發(fa)的(de)(de)核心已經變(bian)成(cheng)了最大化(hua)服務器(qi)響應速(su)度。這種轉變(bian)來自網速(su)的(de)(de)提升和單頁應用(yong)(SPA)的(de)(de)普及。對(dui)后端來說,就(jiu)是要能處(chu)理海(hai)量的(de)(de)快速(su)請求,還得把負載分配好。

經典(dian)的雙池架(jia)構(請(qing)求(qiu) worker + 任務 worker)不(bu)是(shi)憑空出現的。

一(yi)個(ge)(ge)請(qing)求(qiu)一(yi)個(ge)(ge)進(jin)程的模型(xing),根本(ben)扛不住(zhu)大批量(liang)的輕量(liang)請(qing)求(qiu)。該上并(bing)發(fa)了(le)——一(yi)個(ge)(ge)進(jin)程同(tong)時處理多個(ge)(ge)請(qing)求(qiu)。

并發處(chu)理帶來了(le)新要(yao)求:服務(wu)器代碼要(yao)盡可(ke)能貼近(jin)業(ye)務(wu)邏輯(ji)。以前不(bu)(bu)是(shi)這(zhe)樣的。以前可(ke)以用 CGI 或(huo) FPM 把 Web 服務(wu)器和(he)腳本文件分得清清楚(chu)楚(chu),很優雅。現在這(zhe)招不(bu)(bu)好使了(le)。

所以現在的方案要么就是把組件集成得盡量緊密,要么干脆把 Web 服務器當內部模塊嵌進去。NGINX Unit 就是這(zhe)么(me)干的——它把 JavaScript、Python、Go 這(zhe)些語(yu)言直(zhi)接(jie)嵌到 worker 模塊里。PHP 也有模塊,但一(yi)直(zhi)以來,PHP 在這(zhe)種直(zhi)接(jie)集(ji)成里沒撈到什么(me)好處,因為還是一(yi)個 worker 只能處理(li)一(yi)個請求。

集成特性

架構

這個集成分三層:

C 層(nxt_php_sapi.c, nxt_php_extension.c)

  • 在 PHP 里注冊 TrueAsync SAPI
  • 給每個請求創建協程
  • 通過 nxt_unit_run() 管理事件循環
  • 通過 nxt_unit_response_write_nb() 實現非阻塞數據傳輸

PHP 擴展層(NginxUnit 命名空間)

  • NginxUnit\Request - 請求對象
  • NginxUnit\Response - 響應對象,支持非阻塞發送
  • NginxUnit\HttpServer::onRequest() - 注冊請求處理器

用戶代碼(entrypoint.php)

  • 通過 HttpServer::onRequest() 注冊處理器
  • 使用 Request/Response API
  • 完全異步執行

請求流程

HTTP 請求 → NGINX Unit → nxt_php_request_handler()
                              ↓
                  創建協程 (zend_async_coroutine_create)
                              ↓
                  nxt_php_request_coroutine_entry()
                              ↓
                  創建 Request/Response 對象
                              ↓
                  調用 entrypoint.php 中的回調函數
                              ↓
                  response->write() → nxt_unit_response_write_nb()
                              ↓
                  response->end() → nxt_unit_request_done()

非阻塞 I/O

調用 $response->write($data) 時:

  1. 數據通過 nxt_unit_response_write_nb() 發送
  2. 緩沖區滿了,剩余數據進 drain_queue
  3. 緩沖區空出來,觸發 shm_ack_handler
  4. 異步寫入,不阻塞協程

配置

unit-config.json

{
  "applications": {
    "my-php-async-app": {
      "type": "php",
      "async": true,              // 啟用 TrueAsync 模式
      "processes": 2,              // 工作器數量
      "entrypoint": "/path/to/entrypoint.php",
      "working_directory": "/path/to/",
      "root": "/path/to/"
    }
  },
  "listeners": {
    "127.0.0.1:8080": {
      "pass": "applications/my-php-async-app"
    }
  }
}

重要"async": true 會激(ji)活(huo) TrueAsync SAPI,而不是(shi)標準的(de) PHP SAPI。

加載配置

curl -X PUT --data-binary @unit-config.json \
  --unix-socket /tmp/unit/control.unit.sock \
  //localhost/config

entrypoint.php

基本結構:

<?php

use NginxUnit\HttpServer;
use NginxUnit\Request;
use NginxUnit\Response;

set_time_limit(0);

// 注冊請求處理器
HttpServer::onRequest(static function (Request $request, Response $response) {
    // 拿請求數據
    $method = $request->getMethod();
    $uri = $request->getUri();

    // 設響應頭
    $response->setHeader('Content-Type', 'application/json');
    $response->setStatus(200);

    // 發數據(非阻塞)
    $response->write(json_encode([
        'message' => 'Hello from TrueAsync!',
        'method' => $method,
        'uri' => $uri
    ]));

    // 結束響應
    $response->end();
});

API 參考

Request

  • getMethod(): string - HTTP 方法(GET、POST 等)
  • getUri(): string - 請求 URI
  • getRequestContext(): ?mixed - 請求上下文(TODO)
  • getRequestContextParameters(): ?mixed - 上下文參數(TODO)
  • createResponse(): Response - 創建 Response 對象(通常不需要)

Response

  • setStatus(int $code): bool - 設置 HTTP 狀態碼
  • setHeader(string $name, string $value): bool - 添加響應頭
  • write(string $data): bool - 發送數據(非阻塞操作)
  • end(): bool - 完成響應并釋放資源

注意

  • setStatus()setHeader() 要在第一次 write() 之前調用
  • 調用過 write() 后,響應頭就發出去了
  • end() 必須調用,完成請求

生命周期

HttpServer::onRequest(function (Request $req, Response $resp) {
    // 1. 響應頭還能改
    $resp->setStatus(200);
    $resp->setHeader('Content-Type', 'text/plain');

    // 2. 第一次 write() 把響應頭發出去了
    $resp->write('Hello ');

    // 3. 現在響應頭改不了了
    // $resp->setHeader() → 報錯!

    // 4. 可以繼續寫數據
    $resp->write('World!');

    // 5. 結束請求(必須調!)
    $resp->end();
});

運行和測試

啟動 NGINX Unit

./build/sbin/unitd \
  --no-daemon \
  --log /tmp/unit/unit.log \
  --state /tmp/unit \
  --control unix:/tmp/unit/control.unit.sock \
  --pid /tmp/unit/unit.pid \
  --modules ./build/lib/unit/modules

重要--modules 參數必須加(jia),用來加(jia)載 PHP 模(mo)塊。

查看日志

tail -f /tmp/unit/unit.log

測試

curl //127.0.0.1:8080/

響應:

{
    "message": "Hello from NginxUnit TrueAsync HttpServer!",
    "method": "GET",
    "uri": "/",
    "timestamp": "2025-10-04 15:30:00"
}

負載測試

wrk -t4 -c100 -d30s //127.0.0.1:8080/

調試

GDB

gdb ./build/sbin/unitd
(gdb) set follow-fork-mode child
(gdb) run --no-daemon --log /tmp/unit/unit.log ...

設置斷點

break nxt_php_request_handler
break nxt_php_request_coroutine_entry
break nxt_unit_response_write_nb

實用命令

# 停止所有 NGINX Unit 進程
pkill -9 unitd

# 檢查控制套接字
ls -la /tmp/unit/control.unit.sock

# 獲取當前配置
curl --unix-socket /tmp/unit/control.unit.sock //localhost/config

內部實現

初始化

  1. nxt_php_extension_init()NginxUnit 命名空間注冊類
  2. worker 啟動時加載 entrypoint.php
  3. HttpServer::onRequest() 把回調存到 nxt_php_request_callback

請求處理

  1. NGINX Unit 調用 nxt_php_request_handler(req)
  2. 創建協程:zend_async_coroutine_create(nxt_php_request_coroutine_entry)
  3. 協程指針存到 req
  4. 協程加入激活隊列
  5. 控制權回到事件循環 nxt_unit_run()

協程激活

  1. 事件循環調用 nxt_unit_response_buf_alloc 回調
  2. 回調通過 zend_async_coroutine_activate() 激活協程
  3. 執行 nxt_php_request_coroutine_entry()
  4. 創建 PHP Request/Response 對象
  5. 調用用戶回調
  6. response->end() 后協程結束

異步發送

  1. response->write()nxt_unit_response_write_nb()
  2. 沒發完,剩下的進 drain_queue
  3. 緩沖區空了,觸發 shm_ack_handler()
  4. shm_ack_handler 繼續寫,需要的話調 end()

未來計劃

  • 實現 Request::getRequestContext()
  • 添加請求頭支持
  • 添加 POST 數據解析
  • WebSocket 支持
  • 流式響應

總結

NGINX Unit TrueAsync PHP 集成讓 PHP 真正擁有了異步處理能(neng)力(li)。通過(guo)(guo)協程機(ji)制,單個進程可以(yi)同時(shi)處理多個請求,這在(zai)過(guo)(guo)去是無法想(xiang)象的。

對(dui)于 PHP 生態來說,這是(shi)一個(ge)(ge)重(zhong)要的(de)轉(zhuan)折點。傳統的(de) PHP-FPM 模式下,每個(ge)(ge)請(qing)求獨占一個(ge)(ge)進程,在高并發場景下資源(yuan)消(xiao)耗(hao)巨(ju)大。現(xian)在有了 TrueAsync,PHP 可以(yi)像 Node.js、Go 那樣高效處理并發請(qing)求,同時保持語言本身(shen)的(de)簡潔性。

雖然目前還有(you)一些(xie)功能(neng)在開發中,比如完整的請求頭(tou)支持、POST 數據解析、WebSocket 等,但現有(you)的功能(neng)已(yi)經(jing)足(zu)夠構建(jian)高性能(neng)的 API 服務。非(fei)阻(zu)塞 I/O、協(xie)程調度、事件循環——這(zhe)些(xie)核心機制都已(yi)經(jing)就位。

對于需要(yao)處理(li)高并發請求(qiu)的 PHP 應(ying)用,特別是 API 服務、微(wei)服務架構(gou),NGINX Unit TrueAsync 提(ti)供(gong)了一個值(zhi)得認真考(kao)慮(lv)的選(xuan)擇(ze)。它不(bu)需要(yao)改變太多現有代碼(ma)結構(gou),卻能(neng)帶來性能(neng)上的顯著提(ti)升。

posted @ 2025-10-15 08:08  JaguarJack  閱讀(189)  評論(0)    收藏  舉報