OpenResty における ストリーミング HTTP レスポンス出力
このビデオでは、OpenResty でストリーミング HTTP レスポンスボディの出力を行う方法をご紹介いたします。
cd ~/
mkdir stream-resp/
cd stream-resp/
まず、いつものようにサブディレクトリ構造を作成します。
mkdir logs conf html
次に、テンプレート設定を迅速に記述します。
vim conf/nginx.conf
そして、このファイルに以下の編集を加えます。
- 8080 ポートをリッスンする HTTP サーバーを作成します。
/test
ロケーションを追加します。- Chrome ウェブブラウザを満足させるために、
application/octet-stream
MIME タイプを指定することが重要です。 - content_by_lua_block ディレクティブを使用して Lua コードを追加します。
- 1秒ごとに1行の出力を行います。
- Nginx の書き込みバッファをフラッシュするために、ngx.flush メソッドを明示的に呼び出す必要があります。これは 100% ノンブロッキングな呼び出しです。
- そして、各ループの反復で
ngx.sleep
を使用して 1 秒間スリープします。これもノンブロッキングです。 - 最後に、
html
ディレクトリのルートロケーションを作成します。
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 8080 reuseport;
location = /test {
default_type application/octet-stream;
content_by_lua_block {
for i = 1, 4 do
ngx.say("hello ", i)
ngx.flush(true)
ngx.sleep(1) -- sec
end
}
}
location / {
default_type text/html;
root html;
}
}
}
ここで、ディレクトリツリー全体を確認しましょう。
tree .
良さそうですね。
では、この OpenResty アプリケーションを起動します。
openresty -p $PWD/
curl
を使用して HTTP ロケーションにクエリを送る時が来ました。
curl 'http://127.0.0.1:8080/test'
素晴らしいですね。確かに毎秒1行の文字が生成されています!
この HTTP API が本当にノンブロッキングであるかを検証するために、weighttp
ツールを使用してロードテストを行うことができます。ここでは意図的にレスポンスを遅くしているため、時間がかかることにご注意ください。
weighttp -c 500 -k -n 500 127.0.0.1:8080/test
このように、500 の同時リクエストがある状況でも、毎秒 120 以上のリクエストを処理できています!各リクエストの完了に 4 秒かかることに注意してください。しかも、これはたった 1 つのワーカープロセスと 1 つの OS スレッドだけで実現しています。
さらに同時接続数を増やすこともできますが、そのためには Nginx の設定を適切に調整する必要があります。
vim conf/nginx.conf
例えば、worker_connections
をより大きな値に設定します。
アクセスログのバッファリングを有効にすることで、さらなるパフォーマンス向上が期待できます。また、リクエストメモリプールのサイズを減らすこともできます。
では、Web ブラウザでテストするための HTML ページを作成しましょう。
vim html/a.html
このファイルで以下の編集を行います:
- 出力を保持するための
DIV
タグを追加します。 - 先ほどの HTTP ロケーションに AJAX リクエストを送信する JavaScript を追加します。
DIV
要素を取得します。- ストリーミングレスポンスを受信するための JavaScript 関数を追加します。
- 新しいデータがあることを確認します。
- 新しいデータを
DIV
要素に追加します。ここでは簡略化のため、特殊な HTML 文字のエスケープは行いません。 - 1 秒ごとに新しい受信レスポンスデータをチェックします。
- Firefox はより洗練された方法をサポートしていますが、Chrome もサポートする必要があります。
- 最後に、レスポンスボディストリームの終了を処理します。
- レスポンスデータの最終チェックを行います。
- 定期的なタイマーを削除します。
- 最終的な出力結果をウェブページに追加します。
- 簡潔さを保つため、ここではエラー処理を省略しています。
<!doctype html>
<html>
<body>
<div style="margin: 2em;" id="out"></div>
<script>
(function () {
let xhttp = new XMLHttpRequest();
xhttp.open("GET", "/test", true);
xhttp.send();
let div = document.getElementById("out")
let total_len = 0
let check_resp = function () {
let resp = xhttp.responseText
let len = resp.length
if (len > total_len) {
let new_data = resp.substring(total_len, len)
total_len = len;
div.innerHTML += new_data + "<br/>"
}
};
let timer = setInterval(check_resp, 1000);
check_resp();
xhttp.onreadystatechange = function () {
if (this.readyState == 4) {
check_resp();
clearInterval(timer);
div.innerHTML += "done<br/>";
}
};
})();
</script>
</body>
</html>
ディレクトリ構造全体をもう一度確認しましょう。
tree .
OpenResty サーバーを再読み込みしたり再起動したりする必要はありません。これは単なる静的 HTML ページだからです。
ps aux|grep nginx|grep -v /tmp/
Chrome でこの HTML ページを開く時が来ました。
うまく機能しました!以上が本日お伝えしたい内容です。
著者について
章亦春(Zhang Yichun)は、オープンソースの OpenResty® プロジェクトの創始者であり、OpenResty Inc. の CEO および創業者です。
章亦春(GitHub ID: agentzh)は中国江蘇省生まれで、現在は米国ベイエリアに在住しております。彼は中国における初期のオープンソース技術と文化の提唱者およびリーダーの一人であり、Cloudflare、Yahoo!、Alibaba など、国際的に有名なハイテク企業に勤務した経験があります。「エッジコンピューティング」、「動的トレーシング」、「機械プログラミング」 の先駆者であり、22 年以上のプログラミング経験と 16 年以上のオープンソース経験を持っております。世界中で 4000 万以上のドメイン名を持つユーザーを抱えるオープンソースプロジェクトのリーダーとして、彼は OpenResty® オープンソースプロジェクトをベースに、米国シリコンバレーの中心部にハイテク企業 OpenResty Inc. を設立いたしました。同社の主力製品である OpenResty XRay動的トレーシング技術を利用した非侵襲的な障害分析および排除ツール)と OpenResty XRay(マイクロサービスおよび分散トラフィックに最適化された多機能
翻訳
英語版の原文と日本語訳版(本文)をご用意しております。読者の皆様による他の言語への翻訳版も歓迎いたします。全文翻訳で省略がなければ、採用を検討させていただきます。心より感謝申し上げます!