OpenResty FAQ | Privileged Process-Berechtigungen, Ausführungsphase und mehr

API7.ai

November 11, 2022

OpenResty (NGINX + Lua)

Dieser Artikel enthält sechs häufig gestellte Fragen:

1. Berechtigungen privilegierter Prozesse

F: Was ist ein privilegierter Prozess? Wie könnte ein nicht-privilegierter Benutzer root-Berechtigungen erhalten? Können Sie einige Szenarien für privilegierte Prozesse vorstellen?

A: Die Berechtigungen des privilegierten Prozesses sind die gleichen wie die des master-Prozesses. Wenn Sie OpenResty als nicht-privilegierter Benutzer starten, erbt der master-Prozess die Berechtigungen des Benutzers, was bedeutet, dass der "privilegierte Prozess" derzeit keine Rechte hat.

Es ist leicht zu verstehen, dass es keine Root-Berechtigungen gibt, wenn ein normaler Benutzer einen Prozess startet.

Was die Anwendungsszenarien für privilegierte Prozesse betrifft, verwenden wir sie im Allgemeinen für Aufgaben, die hohe Berechtigungen erfordern, wie das Bereinigen von Protokollen und das Neustarten von OpenResty. Seien Sie jedoch vorsichtig, den privilegierten Prozess nicht für die Ausführung von Worker-Prozessaufgaben zu verwenden, da dies ein Sicherheitsrisiko darstellt.

Ein Entwickler führt alle timer-Aufgaben im privilegierten Prozess aus. Warum macht er das? Weil es nur einen privilegierten Prozess gibt, und auf diese Weise wird der timer nicht wiederholt gestartet.

Der Entwickler ist "schlau", da er das Ziel erreicht hat, ohne worker.id zu verwenden. Vergessen Sie jedoch nicht, es ist sehr gefährlich, wenn die timer-Aufgabe auf die Eingabe des Clients angewiesen ist.

2. Phasen und Debugging

F: Nachdem ngx.say('hello') ausgeführt wurde, wird OpenResty dem Client direkt antworten, nachdem die restliche Logik in der aktuellen Phase ausgeführt wurde? Bedeutet dies, dass es nicht weiter in späteren Phasen ausgeführt wird?

A: Nein. Wir können uns die Ausführungsphase ansehen:

image

Sie können ngx.say zunächst in der content-Phase testen und dann ngx.log in der log- oder body filter-Phase verwenden, um das Protokoll auszugeben.

In früheren Artikeln habe ich das Problem des Code-Debuggings in OpenResty nicht speziell erwähnt, was Entwickler möglicherweise verwirrt.

Es gibt keine erweiterten Funktionen zum Debuggen von Code in OpenResty, wie z.B. Breakpoints (es gibt einige kostenpflichtige Plugins, die ich jedoch nicht verwendet habe), und Sie können nur ngx.say und ngx.log verwenden, um die Ausgabe zu sehen. So machen es alle Entwickler, die ich kenne, einschließlich der Autoren und Mitwirkenden von OpenResty. Daher benötigen Sie robuste Testfälle und Debug-Protokolle als Sicherheit.

3. Die Praxis von ngx.exit

F: In einem früheren Artikel gab es eine Beschreibung: Der HTTP-Statuscode von OpenResty hat eine spezielle Konstante ngx.OK. Nach der Ausführung von ngx.exit(ngx.OK) verlässt die Anfrage die aktuelle Phase und geht zur nächsten Phase über, anstatt direkt zum Client zurückzukehren.

Ich erinnere mich, dass ngx.OK nicht als HTTP-Statuscode betrachtet werden sollte, sein Wert ist 0. Mein Verständnis ist:

  • Nach der Ausführung von ngx.exit(ngx.OK), ngx.exit(ngx.ERROR) oder ngx.exit(ngx.DECLINED) verlässt die Anfrage die aktuelle Phase und geht zur nächsten Phase über.
  • Wenn ngx.exit(ngx.HTTP_*) die verschiedenen HTTP-Statuscodes von ngx.HTTP_* als Parameter nimmt, wird es direkt dem Client antworten.

Ich bin mir nicht sicher, ob mein Verständnis richtig ist.

A: Bezüglich Ihrer ersten Frage ist ngx.ok kein HTTP-Statuscode, sondern eine Konstante in OpenResty mit dem Wert 0.

Was die zweite Frage betrifft, kann die offizielle Dokumentation für ngx.exit die genaue Antwort sein:

  1. Wenn status >= 200 (d.h. ngx.HTTP_OK und höher), wird die Ausführung der aktuellen Anfrage unterbrochen und der Statuscode an nginx zurückgegeben.

  2. Wenn status == 0 (d.h. ngx.OK), wird nur der aktuelle Phasen-Handler (oder der Content-Handler, wenn die content_by_lua*-Direktive verwendet wird) beendet und die späteren Phasen (falls vorhanden) für die aktuelle Anfrage fortgesetzt.

Die Dokumentation erwähnt jedoch nicht, wie OpenResty mit ngx.exit(ngx.ERROR) und ngx.exit(ngx.DECLINED) umgeht. Wir können einen Test wie folgt durchführen:

location /lua {
    rewrite_by_lua "ngx.exit(ngx.ERROR)";
    echo hello;
}

Wenn Sie diesen location besuchen, können Sie sehen, dass der HTTP-Antwortcode leer ist, der Antwortkörper ebenfalls leer ist und es nicht zur nächsten Ausführungsphase geht.

Je tiefer Sie in den Lernprozess von OpenResty eintauchen, desto mehr werden Sie feststellen, dass weder die Dokumentation noch die Testfälle Ihre Fragen beantworten können. An diesem Punkt müssen Sie Ihre eigenen Testfälle erstellen, um Ihre Ideen zu überprüfen. Sie können dies manuell tun oder die Tests zu dem von test::nginx erstellten Testfallset hinzufügen.

4. Variablen und Race Conditions

F: Wie bereits erwähnt, liegt der Gültigkeitsbereich der ngx.var-Variable zwischen den Modulen nginx C und lua-nginx-module.

  1. Ich verstehe das nicht ganz. Aus der Sicht der Anfrage bedeutet dies eine einzelne Anfrage in einem Worker-Prozess?

  2. Mein Verständnis ist, dass wir Variablen innerhalb eines Moduls manipulieren. Wenn es zwischen zwei Operationen eine blockierende Operation gibt, kann es eine Race Condition geben. Wenn es also keine blockierende Operation zwischen zwei Operationen gibt und es gerade passiert, dass der aktuelle Prozess in die Ready-Queue eintritt, wenn die CPU-Zeit abgelaufen ist, kann es dann eine Race Condition geben?

A: Schauen wir uns diese Fragen an.

Zunächst, bezüglich der ngx.var-Variable, ist Ihr Verständnis korrekt. Der Lebenszyklus von ngx.var ist der gleiche wie die Anfrage, und er verschwindet, wenn die Anfrage endet. Sein Vorteil ist jedoch, dass die Daten in C-Modulen und Lua-Code übergeben werden können, was auf andere Weise nicht möglich ist.

Zweitens, solange es eine yield-Operation zwischen zwei Operationen gibt, kann es eine Race Condition geben, nicht jedoch bei einer blockierenden Operation. Mit anderen Worten, solange Sie die Initiative nicht an die Event-Loop von NGINX abgeben, gibt es keine Race Condition.

5. Das shared dict benötigt keine Sperren

F: Wenn mehrere Worker gleichzeitig Daten speichern, ist es dann notwendig, Sperren hinzuzufügen?

Zum Beispiel:

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: Sie müssen hier keine Sperre hinzufügen, da sowohl get- als auch set-Operationen auf dem shared dict atomar sind. OpenResty hat diese Art von sperrartiger Verarbeitung bereits berücksichtigt.

6. Zeitoperationen in OpenResty

F: Wenn ngx.now() verwendet wird, um die Zeit zu erhalten, geschieht dies dann in der resume-Funktions-Wiederherstellungsphase?

A: NGINX ist mit dem Fokus auf Leistung entworfen und speichert die Zeit zwischen. Wir können dies durch den Quellcode von ngx.now überprüfen:

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;
}

Wie Sie sehen können, steht hinter der ngx.now()-Funktion, die die aktuelle Zeit abruft, die ngx_timeofday-Funktion von NGINX. Die ngx_timeofday-Funktion ist eine Makrodefinition:

#define ngx_timeofday()      (ngx_time_t *) ngx_cached_time

Hier wird der Wert von ngx_cached_time nur in der ngx_time_update-Funktion aktualisiert.

Die Frage lautet also: "Wann wird die ngx_time_update-Funktion aufgerufen?" Wenn Sie dies im NGINX-Quellcode verfolgen, werden Sie sehen, dass die Aufrufe von ngx_time_update in der Event-Loop erfolgen, dann ist dieses Problem gelöst.

Zusammenfassung

Sie sollten auch durch diese Fragen feststellen können, dass der Vorteil von Open-Source-Projekten darin besteht, dass Sie den Spuren folgen und Antworten im Quellcode suchen können, was Ihnen das Gefühl gibt, einen Fall zu lösen.

Schließlich hoffe ich, dass ich durch Kommunikation und Fragen und Antworten dazu beitragen kann, dass Sie das Gelernte in das Erreichte umwandeln können. Sie sind auch eingeladen, diesen Artikel weiterzuleiten, und wir werden gemeinsam kommunizieren und uns verbessern.