uWebSockets.js 遇見Http3

HTTP/3 引入運(yùn)行在 UDP 上的新(不同)傳輸協(xié)議 QUIC 意味著理論上和目前實(shí)驗(yàn)上的延遲減少,目前標(biāo)準(zhǔn)已發(fā)布,在開始之前可以參閱《WebSockets和HTTP》
uWebSockets.js 現(xiàn)在已經(jīng)增加了實(shí)驗(yàn)性 HTTP/3 支持,值得一試。由于是實(shí)驗(yàn)性質(zhì),存在一些先決條件:
- 不是所有的平臺都能夠正常運(yùn)行起來,文章涉及的代碼只在
x64 Linux上運(yùn)行成功,基于 Docker 容器運(yùn)行 - 如果
localhost接口沒有ipv6地址,將無法工作,但可以通過./quiche-client --no-verify https://[::1]:9004/來進(jìn)行訪問
quiche-client 安裝
quiche 是 IETF 指定的 QUIC 傳輸協(xié)議和 HTTP/3 的實(shí)現(xiàn),提供了用于處理 QUIC (《QUIC 簡介及 NodeJs 簡單示例》) 數(shù)據(jù)包和處理連接狀態(tài)的低級 API。應(yīng)用程序負(fù)責(zé)提供 I/O(例如套接字處理)以及支持計(jì)時(shí)器的事件循環(huán)。
具體的安裝可以參閱 quice git。
uWebSockets 安裝
npm install uWebSockets.js#binaries --save
服務(wù)器端點(diǎn)是通過一個(gè)簡單的帶有模式匹配和通配符的 URL 路由器定義的:
const uWS = require("uWebSockets.js");
uWS.H3App({
key_file_name: "./key.pem",
cert_file_name: "./cert.pem",
})
.get("/*", (res, req) => {
res.end("遇見H3,一切都變得美好!");
})
.listen(9004, (listenSocket) => {
if (listenSocket) {
console.log("監(jiān)聽端口號: 9004!");
}
});
使用 quiche-client 訪問服務(wù)器很容易:
quiche-client --no-verify https://[::1]:9004/
性能
首先通過創(chuàng)建運(yùn)行最小的 Node.js HTTP/1.1 服務(wù)器來作為參考點(diǎn),無需任何路由或加密,在單核上以 100% 的 CPU 情況下進(jìn)行壓力:
const http = require("http");
const requestListener = function (req, res) {
res.end("HTTP1 服務(wù)");
};
const server = http.createServer(requestListener);
server.listen(8080);
在這臺特定的機(jī)器上,在 100% 的 CPU 時(shí)間(一個(gè)內(nèi)核)下每秒收到 18k 個(gè)請求。現(xiàn)在將其與 uWebSockets.js 中的 H3 進(jìn)行比較。
在單核上 100% 的 CPU 情況下,每秒可以處理高達(dá) 291k 的請求,并且還是在加密和 URL 路由解析的情況下,整整 16 倍的加速!
為什么快這么多?部分原因是 HTTP/3 具有適當(dāng)?shù)恼埱蟛⑿行?pipelining 。所有主要 Web 瀏覽器都認(rèn)為 HTTP/1.1 中的pipelining 不可用和禁用,但為了完整起見,將在此基準(zhǔn)測試中啟用 HTTP/1.1 流水線并再次運(yùn)行它!
在所有條件相同的情況下,使用 Node.js 內(nèi)置 HTTP/1.1 服務(wù)器每秒獲得 28k 請求。與 uWebSockets.js HTTP/3 支持相比,仍然是 10 倍的差異。
注意:
HTTP/3必須是TLS 1.3加密和 URL 路由的!

很明顯,與Node.js相比,性能數(shù)據(jù)是非常高的,如果想要HTTP/3的特性,將無法使用普通的 Node.js 。
uWebSockets.js 現(xiàn)在構(gòu)建了高度實(shí)驗(yàn)性的 HTTP/3,將開始持續(xù)穩(wěn)定的支持。一個(gè)大概的計(jì)劃是在 6 個(gè)月內(nèi)發(fā)布一個(gè)穩(wěn)定版本,在 1 個(gè)月內(nèi)應(yīng)該發(fā)布一個(gè)包含實(shí)驗(yàn)支持的版本。同時(shí),可以開始將應(yīng)用程序移植到 uWebSockets.js 中。
這樣做意味著可以在不改變?nèi)魏螛I(yè)務(wù)邏輯的情況下從 uWS.App 切換到 uWS.H3App , uWebSockets.js 在與 HTTP/1.1 相同的接口下公開 HTTP/3。
不過目前處于概念驗(yàn)證階段并且非常實(shí)驗(yàn)性,運(yùn)行條件有點(diǎn)苛刻,在使用上還需謹(jǐn)慎。