25 | Q&A (2): 特権プロセスの権限とは具体的に何ですか?
こんにちは、ウェンミンです。
このコラムは現在まで更新されており、OpenResty の 2 番目のセクションで OpenResty API の学習が完了しました。おめでとうございます。あなたは取り残されておらず、今も積極的に学び、実践しており、熱心に考えを残しました。
コメントでいただいたご質問はとても貴重なものが多く、そのほとんどはアプリ内ですでに回答していますが、携帯電話では回答しにくい典型的で興味深い質問をピックアップして、今日のQ&Aコンテンツとして取り上げさせていただきましたそして返信に集中しました。一方で、重要なポイントを見逃さないようにするためでもあります。
今日はこの 6 つの質問を見てみましょう。
最初の質問、特権プロセスの権限
Q: 特権プロセスとは何ですか? OpenResty を起動する人が一般ユーザーの場合、root 権限を取得するにはどうすればよいですか? さらに、教師は、特権プロセスの使用シナリオとは何であるかを紹介できます。
A: 実際には、特権プロセスの権限はマスター プロセスの権限と同じままです。OpenResty を通常のユーザーとして起動した場合、マスターは通常のユーザーの権限となり、この時点では特権プロセスには特権がありません。
この点はよく理解しておく必要があり、一般ユーザーが開始したプロセスには root 権限がありません。
特権プロセスの使用シナリオとしては、ログのクリーニングや OpenResty 自体の再起動など、高い権限を必要とするタスクを処理するために特権プロセスを使用するのが一般的です。注意する必要があるのは、ワーカープロセスのタスクを特権プロセスに引き渡さないことです。これは、特権プロセスがそれを実行できないためではなく、セキュリティ上のリスクがあるためです。
タイマータスクを特権プロセスにオフロードした開発者を見たことがあります。なぜ彼はこんなことをしたのでしょうか?特権プロセスは 1 つだけであるため、タイマーが繰り返し開始されることはありません。
これは非常に賢いと思いませんか。worker.id のような愚かな方法を使わずに実行できます。ただし、忘れないでください。タイマーのタスクがユーザーの入力に関連している場合、これはバックドアを離れるのと同じではないでしょうか? 明らかに非常に危険です。
2 番目の質問、ステージングとデバッグ
Q: 先生、実行中のステージに関係なくngx.say('hello')
、OpenResty はこのステージの残りのコードを実行した後、他のステージを実行し続けるのではなく、クライアントに直接応答しますか? これが私がテストしたものです。
A: 実際にはそうではなく、その実行フェーズのシーケンス。
最初にコンテンツ内でテストを実行しngx.say
、次にログまたはボディ フィルター ステージで使用しngx.log
てログを出力して試すことができます。
開発者がよく混乱する点でもある OpenResty でのコードのデバッグの問題については、コラムでは特に言及しませんでしたが、たまたま Q&A でこの問題について話しました。
実はOpenRestyでのコードデバッグにはブレークポイントなどの高度な機能はなく(有料のプラグインもいくつかありますが使ったことはありません)、出力を見るにはngx.say
とngx.log
。OpenResty の作成者や貢献者を含む、私が知っている開発者は、この方法でデバッグを行っています。したがって、保証として強力なテスト ケースとデバッグ ログが必要です。
質問 3、ngx.exit とハンズオン ラボ
Q: 先生、本文中のこの文は、「OpenResty の HTTP ステータス コードには、特別な定数があります。そのとき、リクエストはクライアントに直接返されるのではなく、現在の処理ステージを終了して次のステージに入ります。」ngx.OK
。」ngx.exit(ngx.OK)
私の記憶では、ngx.OK
これは HTTP ステータス コードとみなされるべきではなく、対応する値は 0 です。私の理解は次のとおりです。
ngx.exit(ngx.OK)
、およびngx.exit(ngx.ERROR)
、リクエストは現在の処理ステージを終了し、次のステージに入ります。ngx.exit(ngx.DECLINED)
- また
ngx.exit(ngx.HTTP_*)
、ngx.HTTP_*
各種HTTPステータスコードをパラメータとして使用すると、クライアントに直接応答します。
そう思うかどうかは分からないですよね?
A: 最初の質問に関しては、ngx.ok
これは確かに http ステータス コードではなく、値 0 を持つ OpenResty の定数です。
2番目の質問については、ngx.exit
公式文書の公式文書で実際に次のように答えることができます。
When status >= 200 (i.e., ngx.HTTP_OK and above), it will interrupt the execution of the current request and return status code to nginx.
When status == 0 (i.e., ngx.OK), it will only quit the current phase handler (or the content handler if the content_by_lua* directive is used) and continue to run later phases (if any) for the current request.
ただし、このドキュメントではngx.exit(ngx.ERROR)
OpenResty がngx.exit(ngx.DECLINED)
。たとえば次のように、自分でテストを行うことができます。
location /lua {
rewrite_by_lua "ngx.exit(ngx.ERROR)";
echo hello;
}
明らかに、この場所にアクセスすると、http 応答コードが空であり、応答本文も空であり、次の実行ステージに入らないことがわかります。
実際、同じ文でも、OpenResty の学習プロセスを徐々に深めていくと、ある段階でドキュメントもテスト ケースも質問に答えられないことが必ずわかります。現時点では、アイデアを検証するために独自のテスト ケースを構築する必要があります。手動でテストすることも、test::nginx
構築された。
4 番目の質問、変数と競争
Q: こんにちは、先生、以下の質問があります。
- 前述したように、
ngx.var
変数のスコープは nginx C モジュールと lua-nginx-module モジュールの間です。よくわからないのですが、リクエストという観点から見ると、ワーカープロセス内の単一のリクエストを指すのでしょうか? - 私の理解では、モジュール内の変数を操作するときに、2 つの操作の間にブロック操作がある場合、競合が発生する可能性があります。したがって、2 つの操作の間にブロック操作がない場合、CPU 時間が経過した直後に、現在のプロセスが準備完了キューに入ります。競合が発生する可能性はありますか?
A: これらの質問を順番に見ていきましょう。
まず、ngx.var
変数正しいです。実際、ngx.var
リクエストのライフサイクルはリクエストのライフサイクルと一致しており、リクエストが終了すると消滅します。ただし、その利点は、C モジュールと Lua コードの間でデータを受け渡しできることです。これは他の方法では実行できません。
第 2 に、変数の競合に関しては、実際には、2 つの操作の間に競合がある限りyield 操作
、ブロッキング操作の代わりに競合が発生する可能性があり、ブロッキング操作がある場合には競合は発生しません。言い換えれば、Nginx イベント ループに主導権を渡さない限り、競合は発生しません。
5 番目の質問は、共有辞書の操作をロックする必要がありますか?
Q: 先生、複数のワーカーが同時にデータを保存する場合、ロックする必要がありますか? たとえば、次の例:
resty --shdict 'dogs 10m' -e 'local dogs = ngx.shared.dogs
local lock= ngx.xxxx.lock
lock.lock()
dogs:set("Jim", 8)
lock.unlock()
local v = dogs:get("Jim")
ngx.say(v)
'
A: 実際には、ここで自分自身をロックする必要はありません。共有辞書 (共有辞書) に対する操作は、取得であっても設定であっても、すべてアトミックです。この種のロックのような処理は、OpenResty によって考慮されています。
6 番目の質問は、OpenResty で時間を更新するにはどうすればよいですか?
Q:ngx.now()
フェッチ時間は、再開関数がスタックを復元するときに発生しますか?
A: Nginx はパフォーマンスを第一に設計されており、時間をキャッシュします。この時点で、ngx.now
ソース。
static int
ngx_http_lua_ngx_now(lua_State *L)
{
ngx_time_t *tp;
tp = ngx_timeofday();
lua_pushnumber(L, (lua_Number) (tp->sec + tp->msec / 1000.0L));
return 1;
}
ngx.now()
現在時刻を取得する機能の背後に、実はNginxのngx_timeofday
機能がわかります。ngx_timeofday
この関数は実際にはマクロ定義です。
#define ngx_timeofday() (ngx_time_t *) ngx_cached_time
ngx_cached_time
ここの値はngx_time_update
関数内でのみ更新されます。
したがって、質問は単純化して、ngx_time_update
いつ呼び出されるのかということになります。ngx_time_update
Nginx のソースコードで追跡すると、イベント ループの中に all の呼び出しが出現することがわかり、この問題が理解できます。
この質問を通じて、オープンソース プロジェクトの利点は、手がかりをもとにソース コードから答えを見つけることができ、まるで事件を解決しているかのように感じられることであることもわかるはずです。
今日は主にこれらの質問に答えていきます。最後に、メッセージ エリアに引き続きご質問を書き込んでいただければ、引き続き回答させていただきます。コミュニケーションやQ&Aを通じて、学んだことを収入に変えるお手伝いができれば幸いです。この記事を転送することも歓迎です。コミュニケーションをとり、一緒に進歩しましょう。