lua: Lua-Skriptingunterstützung für NGINX
Installation
Sie können dieses Modul in jeder RHEL-basierten Distribution installieren, einschließlich, aber nicht beschränkt auf:
- RedHat Enterprise Linux 7, 8, 9 und 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 und Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-lua
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-lua
Aktivieren Sie das Modul, indem Sie Folgendes an den Anfang von /etc/nginx/nginx.conf hinzufügen:
load_module modules/ngx_http_lua_module.so;
Dieses Dokument beschreibt nginx-module-lua v0.10.31 veröffentlicht am 29. Mai 2026.
-
YouTube-Video "Hello World HTTP Example with OpenResty/Lua"
-
YouTube-Video "Write Your Own Lua Modules in OpenResty/Nginx Applications"
-
YouTube-Video "OpenResty's resty Command-Line Utility Demo"
-
YouTube-Video "Measure Execution Time of Lua Code Correctly in OpenResty"
-
YouTube-Video "Precompile Lua Modules into LuaJIT Bytecode to Speedup OpenResty Startup"
Sie sind herzlich eingeladen, unseren offiziellen YouTube-Kanal, OpenResty zu abonnieren.
Zusammenfassung
# setze Suchpfade für reine Lua externe Bibliotheken (';;' ist der Standardpfad):
# setze Suchpfade für Lua externe Bibliotheken, die in C geschrieben sind (kann auch ';;' verwenden):
server {
location /lua_content {
# MIME-Typ wird durch default_type bestimmt:
default_type 'text/plain';
content_by_lua_block {
ngx.say('Hallo, Welt!')
}
}
location /nginx_var {
# MIME-Typ wird durch default_type bestimmt:
default_type 'text/plain';
# versuche Zugriff auf /nginx_var?a=hello,world
content_by_lua_block {
ngx.say(ngx.var.arg_a)
}
}
location = /request_body {
client_max_body_size 50k;
client_body_buffer_size 50k;
content_by_lua_block {
ngx.req.read_body() -- explizit den Anforderungsinhalt lesen
local data = ngx.req.get_body_data()
if data then
ngx.say("Körperdaten:")
ngx.print(data)
return
end
-- Der Körper kann in einer temporären Datei gepuffert werden:
local file = ngx.req.get_body_file()
if file then
ngx.say("Körper ist in Datei ", file)
else
ngx.say("Kein Körper gefunden")
end
}
}
# transparentes, nicht blockierendes I/O in Lua über Subrequests
# (eine bessere Möglichkeit ist die Verwendung von Cosockets)
location = /lua {
# MIME-Typ wird durch default_type bestimmt:
default_type 'text/plain';
content_by_lua_block {
local res = ngx.location.capture("/some_other_location")
if res then
ngx.say("Status: ", res.status)
ngx.say("Körper:")
ngx.print(res.body)
end
}
}
location = /foo {
rewrite_by_lua_block {
res = ngx.location.capture("/memc",
{ args = { cmd = "incr", key = ngx.var.uri } }
)
}
proxy_pass http://blah.blah.com;
}
location = /mixed {
rewrite_by_lua_file /path/to/rewrite.lua;
access_by_lua_file /path/to/access.lua;
content_by_lua_file /path/to/content.lua;
}
# verwende nginx-Var in Code-Pfad
# VORSICHT: Inhalte in nginx-Var müssen sorgfältig gefiltert werden,
# andernfalls besteht ein großes Sicherheitsrisiko!
location ~ ^/app/([-_a-zA-Z0-9/]+) {
set $path $1;
content_by_lua_file /path/to/lua/app/root/$path.lua;
}
location / {
client_max_body_size 100k;
client_body_buffer_size 100k;
access_by_lua_block {
-- überprüfe, ob die Client-IP-Adresse auf unserer schwarzen Liste steht
if ngx.var.remote_addr == "132.5.72.3" then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
-- überprüfe, ob die URI böse Wörter enthält
if ngx.var.uri and
string.match(ngx.var.request_body, "evil")
then
return ngx.redirect("/terms_of_use.html")
end
-- Tests bestanden
}
# proxy_pass/fastcgi_pass/etc. Einstellungen
}
}
Beschreibung
Dieses Modul bettet LuaJIT 2.0/2.1 in NGINX ein. Es ist ein Kernbestandteil von OpenResty. Wenn Sie dieses Modul verwenden, verwenden Sie im Wesentlichen OpenResty.
Seit Version v0.10.16 dieses Moduls wird der Standard-Lua-Interpreter (auch bekannt als "PUC-Rio Lua") nicht mehr unterstützt. Dieses Dokument verwendet die Begriffe "Lua" und "LuaJIT" austauschbar, um auf den LuaJIT-Interpreter zu verweisen.
Durch die Nutzung von NGINX-Subrequests ermöglicht dieses Modul die Integration der leistungsstarken Lua-Threads (bekannt als Lua "Kollaborationen") in das NGINX-Ereignismodell.
Im Gegensatz zu Apache's mod_lua und Lighttpd's mod_magnet kann Lua-Code, der mit diesem Modul ausgeführt wird, 100% nicht blockierend bei Netzwerkverkehr sein, solange die Nginx API für Lua, die von diesem Modul bereitgestellt wird, verwendet wird, um Anfragen an Upstream-Dienste wie MySQL, PostgreSQL, Memcached, Redis oder Upstream-HTTP-Webdienste zu verarbeiten.
Mindestens die folgenden Lua-Bibliotheken und NGINX-Module können mit diesem Modul verwendet werden:
- lua-resty-memcached
- lua-resty-mysql
- lua-resty-redis
- lua-resty-dns
- lua-resty-upload
- lua-resty-websocket
- lua-resty-lock
- lua-resty-logger-socket
- lua-resty-lrucache
- lua-resty-string
- ngx_memc
- ngx_postgres
- ngx_redis2
- ngx_redis
- ngx_proxy
- ngx_fastcgi
Fast alle NGINX-Module können mit diesem ngx_lua-Modul durch ngx.location.capture oder ngx.location.capture_multi verwendet werden, aber es wird empfohlen, diese lua-resty-*-Bibliotheken zu verwenden, anstatt Subrequests zu erstellen, um auf die NGINX-Upstream-Module zuzugreifen, da erstere in der Regel viel flexibler und speichereffizienter sind.
Der Lua-Interpreter (auch bekannt als "Lua State" oder "LuaJIT VM-Instanz") wird über alle Anfragen in einem einzelnen NGINX-Worker-Prozess geteilt, um den Speicherverbrauch zu minimieren. Anforderungskontexte werden mithilfe von leichten Lua-Kollaborationen segregiert.
Geladene Lua-Module bestehen im NGINX-Worker-Prozess, was zu einem kleinen Speicherbedarf in Lua führt, selbst bei hoher Last.
Dieses Modul ist in das "http"-Subsystem von NGINX integriert, sodass es nur mit Kommunikationsprotokollen im HTTP-Bereich (HTTP 0.9/1.0/1.1/2.0, WebSockets usw.) kommunizieren kann. Wenn Sie generische TCP-Kommunikationen mit den nachgelagerten Clients durchführen möchten, sollten Sie stattdessen das ngx_stream_lua Modul verwenden, das eine kompatible Lua-API bietet.
Typische Verwendungen
Um nur einige zu nennen:
- Mashup und Verarbeitung von Ausgaben verschiedener NGINX-Upstream-Ausgaben (Proxy, Drizzle, Postgres, Redis, Memcached usw.) in Lua,
- Durchführung beliebig komplexer Zugriffssteuerungen und Sicherheitsprüfungen in Lua, bevor Anfragen tatsächlich die Upstream-Backends erreichen,
- Manipulation von Antwort-Headern auf beliebige Weise (durch Lua)
- Abrufen von Backend-Informationen aus externen Speicherbackends (wie Redis, Memcached, MySQL, PostgreSQL) und Verwendung dieser Informationen, um zu entscheiden, auf welches Upstream-Backend dynamisch zugegriffen werden soll,
- Codierung beliebig komplexer Webanwendungen in einem Inhalts-Handler unter Verwendung von synchronem, aber dennoch nicht blockierendem Zugriff auf die Datenbank-Backends und andere Speicher,
- Durchführung sehr komplexer URL-Dispatches in Lua in der Rewrite-Phase,
- Verwendung von Lua zur Implementierung fortschrittlicher Caching-Mechanismen für NGINX-Subrequests und beliebige Standorte.
Die Möglichkeiten sind unbegrenzt, da das Modul es ermöglicht, verschiedene Elemente innerhalb von NGINX zusammenzubringen und gleichzeitig die Leistungsfähigkeit der Lua-Sprache dem Benutzer zugänglich zu machen. Das Modul bietet die volle Flexibilität des Skriptens und bietet gleichzeitig Leistungsniveaus, die mit nativen C-Programmen sowohl in Bezug auf CPU-Zeit als auch auf Speicherbedarf vergleichbar sind, dank LuaJIT 2.x.
Andere Implementierungen von Skriptsprachen haben typischerweise Schwierigkeiten, dieses Leistungsniveau zu erreichen.
NGINX-Kompatibilität
Die neueste Version dieses Moduls ist mit den folgenden Versionen von NGINX kompatibel:
- 1.29.x (zuletzt getestet: 1.29.8)
- 1.29.x (zuletzt getestet: 1.29.2)
- 1.27.x (zuletzt getestet: 1.27.1)
- 1.25.x (zuletzt getestet: 1.25.1)
- 1.21.x (zuletzt getestet: 1.21.4)
- 1.19.x (zuletzt getestet: 1.19.3)
- 1.17.x (zuletzt getestet: 1.17.8)
- 1.15.x (zuletzt getestet: 1.15.8)
- 1.14.x
- 1.13.x (zuletzt getestet: 1.13.6)
- 1.12.x
- 1.11.x (zuletzt getestet: 1.11.2)
- 1.10.x
- 1.9.x (zuletzt getestet: 1.9.15)
- 1.8.x
- 1.7.x (zuletzt getestet: 1.7.10)
- 1.6.x
NGINX-Kerne, die älter als 1.6.0 sind (exklusiv), werden nicht unterstützt.
Code-Repository
Das Code-Repository dieses Projekts wird auf GitHub unter openresty/lua-nginx-module gehostet.
LuaJIT-Bytecode-Unterstützung
Sehen Sie sich das YouTube-Video "Measure Execution Time of Lua Code Correctly in OpenResty" an.
Seit der Veröffentlichung von v0.5.0rc32 unterstützen alle *_by_lua_file Konfigurationsdirektiven (wie content_by_lua_file) das direkte Laden von LuaJIT 2.0/2.1 Roh-Bytecode-Dateien:
/path/to/luajit/bin/luajit -b /path/to/input_file.lua /path/to/output_file.ljbc
Die Option -bg kann verwendet werden, um Debug-Informationen in die LuaJIT-Bytecode-Datei einzufügen:
/path/to/luajit/bin/luajit -bg /path/to/input_file.lua /path/to/output_file.ljbc
Bitte beziehen Sie sich auf die offizielle LuaJIT-Dokumentation zur -b-Option für weitere Details:
https://luajit.org/running.html#opt_b
Bitte beachten Sie, dass die von LuaJIT 2.1 generierten Bytecode-Dateien nicht mit LuaJIT 2.0 kompatibel sind und umgekehrt. Die Unterstützung für LuaJIT 2.1-Bytecode wurde erstmals in ngx_lua v0.9.3 hinzugefügt.
Versuche, Standard-Lua 5.1-Bytecode-Dateien in ngx_lua-Instanzen zu laden, die mit LuaJIT 2.0/2.1 (oder umgekehrt) verknüpft sind, führen zu einer NGINX-Fehlermeldung wie der folgenden:
[error] 13909#0: *1 konnte Lua-inlined Code nicht laden: schlechter Bytecode-Header in /path/to/test_file.luac
Das Laden von Bytecode-Dateien über die Lua-Primitiven wie require und dofile sollte immer wie erwartet funktionieren.
Unterstützung für Systemumgebungsvariablen
Wenn Sie in Lua auf die Systemumgebungsvariable foo über die Standard-Lua-API os.getenv zugreifen möchten, sollten Sie auch diesen Umgebungsvariablennamen in Ihrer nginx.conf-Datei über die env-Direktive auflisten. Zum Beispiel,
env foo;
HTTP 1.0 Unterstützung
Das HTTP 1.0-Protokoll unterstützt keine chunked Ausgabe und erfordert einen expliziten Content-Length-Header, wenn der Antwortkörper nicht leer ist, um das HTTP 1.0 Keep-Alive zu unterstützen. Wenn also eine HTTP 1.0-Anfrage gestellt wird und die lua_http10_buffering Direktive auf on gesetzt ist, puffert ngx_lua die Ausgabe von ngx.say und ngx.print Aufrufen und verschiebt auch das Senden von Antwort-Headern, bis alle Antwortkörperausgaben empfangen sind. Zu diesem Zeitpunkt kann ngx_lua die Gesamtlänge des Körpers berechnen und einen ordnungsgemäßen Content-Length-Header zurückgeben, um ihn an den HTTP 1.0-Client zurückzugeben. Wenn der Content-Length-Antwortheader jedoch im laufenden Lua-Code gesetzt wird, wird dieses Puffern deaktiviert, selbst wenn die lua_http10_buffering Direktive auf on gesetzt ist.
Für große Streaming-Ausgaben ist es wichtig, die lua_http10_buffering Direktive zu deaktivieren, um den Speicherverbrauch zu minimieren.
Bitte beachten Sie, dass gängige HTTP-Benchmark-Tools wie ab und http_load standardmäßig HTTP 1.0-Anfragen stellen. Um curl zu zwingen, HTTP 1.0-Anfragen zu senden, verwenden Sie die -0-Option.
Statisches Verlinken reiner Lua-Module
Mit LuaJIT 2.x ist es möglich, den Bytecode reiner Lua-Module in die NGINX-Ausführungsdatei statisch zu verlinken.
Sie können das luajit-Executable verwenden, um .lua-Lua-Moduldateien in .o-Objektdateien zu kompilieren, die die exportierten Bytecode-Daten enthalten, und dann die .o-Dateien direkt in Ihrem NGINX-Build zu verlinken.
Im Folgenden finden Sie ein triviales Beispiel zur Veranschaulichung. Angenommen, wir haben die folgende .lua-Datei namens foo.lua:
-- foo.lua
local _M = {}
function _M.go()
print("Hallo von foo")
end
return _M
Und dann kompilieren wir diese .lua-Datei in die foo.o-Datei:
/path/to/luajit/bin/luajit -bg foo.lua foo.o
Wichtig ist der Name der .lua-Datei, der bestimmt, wie Sie dieses Modul später im Lua-Bereich verwenden. Der Dateiname foo.o spielt keine Rolle, außer der .o-Dateierweiterung (die luajit sagt, welches Ausgabeformat verwendet wird). Wenn Sie die Lua-Debug-Informationen aus dem resultierenden Bytecode entfernen möchten, können Sie einfach die -b-Option oben anstelle von -bg angeben.
Dann, beim Erstellen von NGINX oder OpenResty, übergeben Sie die --with-ld-opt="foo.o"-Option an das ./configure-Skript:
./configure --with-ld-opt="/path/to/foo.o" ...
Schließlich können Sie einfach Folgendes in jedem Lua-Code tun, der von ngx_lua ausgeführt wird:
local foo = require "foo"
foo.go()
Und dieser Code hängt nicht mehr von der externen foo.lua-Datei ab, da sie bereits in die nginx-Ausführungsdatei kompiliert wurde.
Wenn Sie einen Punkt im Lua-Modulnamen verwenden möchten, wenn Sie require aufrufen, wie in
local foo = require "resty.foo"
müssen Sie die foo.lua-Datei in resty_foo.lua umbenennen, bevor Sie sie mit dem luajit-Befehlszeilenprogramm in eine .o-Datei kompilieren.
Es ist wichtig, genau die gleiche Version von LuaJIT zu verwenden, wenn Sie .lua-Dateien in .o-Dateien kompilieren, wie beim Erstellen von nginx + ngx_lua. Dies liegt daran, dass das LuaJIT-Bytecodeformat zwischen verschiedenen LuaJIT-Versionen inkompatibel sein kann. Wenn das Bytecodeformat inkompatibel ist, erhalten Sie zur Laufzeit einen Lua-Fehler, der besagt, dass das Lua-Modul nicht gefunden wurde.
Wenn Sie mehrere .lua-Dateien kompilieren und verlinken möchten, geben Sie einfach deren .o-Dateien gleichzeitig im Wert der --with-ld-opt-Option an. Zum Beispiel:
./configure --with-ld-opt="/path/to/foo.o /path/to/bar.o" ...
Wenn Sie zu viele .o-Dateien haben, ist es möglicherweise nicht praktikabel, sie alle in einem einzigen Befehl zu benennen. In diesem Fall können Sie eine statische Bibliothek (oder ein Archiv) für Ihre .o-Dateien erstellen, wie folgt:
ar rcus libmyluafiles.a *.o
Dann können Sie das myluafiles-Archiv als Ganzes mit Ihrer NGINX-Ausführungsdatei verlinken:
./configure \
--with-ld-opt="-L/path/to/lib -Wl,--whole-archive -lmyluafiles -Wl,--no-whole-archive"
wobei /path/to/lib der Pfad des Verzeichnisses ist, das die libmyluafiles.a-Datei enthält. Es sollte beachtet werden, dass die Linker-Option --whole-archive hier erforderlich ist, da unser Archiv sonst übersprungen wird, da keine Symbole in unserem Archiv in den Hauptteilen der NGINX-Ausführungsdatei erwähnt werden.
Datenaustausch innerhalb eines NGINX-Workers
Um Daten global zwischen allen Anfragen, die von demselben NGINX-Worker-Prozess verarbeitet werden, zu teilen, kapseln Sie die gemeinsamen Daten in ein Lua-Modul, verwenden Sie die Lua require-Built-in, um das Modul zu importieren, und manipulieren Sie dann die gemeinsamen Daten in Lua. Dies funktioniert, weil erforderliche Lua-Module nur einmal geladen werden und alle Kollaborationen die gleiche Kopie des Moduls (sowohl dessen Code als auch Daten) teilen.
Bitte beachten Sie, dass die Verwendung globaler Lua-Variablen stark abgeraten wird, da dies zu unerwarteten Wettlaufbedingungen zwischen konkurrierenden Anfragen führen kann.
Hier ist ein kleines Beispiel zum Teilen von Daten innerhalb eines NGINX-Workers über ein Lua-Modul:
-- mydata.lua
local _M = {}
local data = {
dog = 3,
cat = 4,
pig = 5,
}
function _M.get_age(name)
return data[name]
end
return _M
und dann der Zugriff darauf von nginx.conf:
location /lua {
content_by_lua_block {
local mydata = require "mydata"
ngx.say(mydata.get_age("dog"))
}
}
Das mydata-Modul in diesem Beispiel wird nur bei der ersten Anfrage an den Standort /lua geladen und ausgeführt, und alle nachfolgenden Anfragen an denselben NGINX-Worker-Prozess verwenden die neu geladene Instanz des Moduls sowie die gleiche Kopie der darin enthaltenen Daten, bis ein HUP-Signal an den NGINX-Master-Prozess gesendet wird, um ein Neuladen zu erzwingen. Diese Datenaustauschtechnik ist entscheidend für leistungsstarke Lua-Anwendungen, die auf diesem Modul basieren.
Bitte beachten Sie, dass dieser Datenaustausch auf pro Worker-Basis und nicht auf pro Server-Basis erfolgt. Das heißt, wenn es mehrere NGINX-Worker-Prozesse unter einem NGINX-Master gibt, kann der Datenaustausch die Prozessgrenze zwischen diesen Workern nicht überschreiten.
Es wird normalerweise empfohlen, auf diese Weise nur schreibgeschützte Daten zu teilen. Sie können auch veränderbare Daten zwischen allen gleichzeitigen Anfragen jedes NGINX-Worker-Prozesses teilen, solange es keine nicht blockierenden I/O-Operationen (einschließlich ngx.sleep) in der Mitte Ihrer Berechnungen gibt. Solange Sie die Kontrolle nicht an die NGINX-Ereignisschleife und den leichten Thread-Planer von ngx_lua (auch nicht implizit) zurückgeben, kann es niemals zu Wettlaufbedingungen kommen. Aus diesem Grund sollten Sie immer sehr vorsichtig sein, wenn Sie veränderbare Daten auf der Worker-Ebene teilen möchten. Fehlerhafte Optimierungen können leicht zu schwer zu behebenden Wettlaufbedingungen unter Last führen.
Wenn serverweites Datenaustausch erforderlich ist, verwenden Sie eine oder mehrere der folgenden Methoden:
- Verwenden Sie die ngx.shared.DICT API, die von diesem Modul bereitgestellt wird.
- Verwenden Sie nur einen einzigen NGINX-Worker und einen einzigen Server (dies wird jedoch nicht empfohlen, wenn es eine Mehrkern-CPU oder mehrere CPUs in einer einzelnen Maschine gibt).
- Verwenden Sie Datenspeichermechanismen wie
memcached,redis,MySQLoderPostgreSQL. Die offiziellen OpenResty-Versionen werden mit einer Reihe von Begleit-NGINX-Modulen und Lua-Bibliotheken geliefert, die Schnittstellen zu diesen Datenspeichermechanismen bereitstellen.
Bekannte Probleme
Probleme mit der TCP-Socket-Verbindungsoperation
Die tcpsock:connect Methode kann success anzeigen, obwohl Verbindungsfehler wie Connection Refused auftreten.
Spätere Versuche, das Cosocket-Objekt zu manipulieren, schlagen jedoch fehl und geben die tatsächliche Fehlermeldung zurück, die durch den fehlgeschlagenen Verbindungsversuch erzeugt wurde.
Dieses Problem ist auf Einschränkungen im NGINX-Ereignismodell zurückzuführen und tritt nur unter Mac OS X auf.
Lua-Kollaboration Yielding/Wiederaufnahme
- Da die
dofile- undrequire-Built-ins von Lua derzeit als C-Funktionen in LuaJIT 2.0/2.1 implementiert sind, wird ein Lua-Fehler "Versuch, über die C-Aufrufgrenze hinweg zu yielden" ausgelöst, wenn die Lua-Datei, die vondofileoderrequiregeladen wird, ngx.location.capture*, ngx.exec, ngx.exit oder andere API-Funktionen aufruft, die im Top-Level-Bereich der Lua-Datei yielden müssen. Um dies zu vermeiden, sollten Sie diese Aufrufe, die ein Yielding erfordern, in Ihre eigenen Lua-Funktionen in der Lua-Datei anstelle des Top-Level-Bereichs der Datei setzen.
Lua-Variablenbereich
Es muss darauf geachtet werden, Module zu importieren, und diese Form sollte verwendet werden:
local xxx = require('xxx')
anstatt der alten, veralteten Form:
require('xxx')
Hier ist der Grund: Das globale Umfeld hat absichtlich genau die gleiche Lebensdauer wie der NGINX-Anforderungs-Handler, der damit verbunden ist. Jeder Anforderungs-Handler hat seine eigene Menge an Lua-Globalvariablen, und das ist die Idee der Anforderungsisolierung. Das Lua-Modul wird tatsächlich vom ersten NGINX-Anforderungs-Handler geladen und wird vom require()-Built-in im package.loaded-Tabelle für spätere Referenz zwischengespeichert, und das module()-Built-in, das von einigen Lua-Modulen verwendet wird, hat den Nebeneffekt, eine globale Variable auf die geladene Modultabelle zu setzen. Diese globale Variable wird jedoch am Ende des Anforderungs-Handlers gelöscht, und jeder nachfolgende Anforderungs-Handler hat sein eigenes (sauberes) globales Umfeld. Daher wird eine Lua-Ausnahme ausgelöst, wenn auf den nil-Wert zugegriffen wird.
Die Verwendung globaler Lua-Variablen wird im ngx_lua-Kontext im Allgemeinen nicht empfohlen, da:
- Der Missbrauch von Lua-Globals hat nachteilige Nebeneffekte auf konkurrierende Anfragen, wenn solche Variablen stattdessen lokal im Geltungsbereich sein sollten,
- Lua-Globale Variablen erfordern Lua-Tabellen-Lookups im globalen Umfeld, was rechenintensiv ist, und
- Einige Verweise auf Lua-Globale Variablen können Tippfehler enthalten, die schwer zu debuggen sind.
Es wird daher dringend empfohlen, solche immer innerhalb eines geeigneten lokalen Geltungsbereichs zu deklarieren.
-- Vermeiden
foo = 123
-- Empfohlen
local foo = 123
-- Vermeiden
function foo() return 123 end
-- Empfohlen
local function foo() return 123 end
Um alle Instanzen von Lua-Globalvariablen in Ihrem Lua-Code zu finden, führen Sie das lua-releng-Tool über alle .lua-Quell-Dateien aus:
$ lua-releng
Überprüfen der Verwendung von Lua-Globalvariablen in der Datei lib/foo/bar.lua ...
1 [1489] SETGLOBAL 7 -1 ; enthält
55 [1506] GETGLOBAL 7 -3 ; setvar
3 [1545] GETGLOBAL 3 -4 ; varexpand
Die Ausgabe sagt, dass die Zeile 1489 der Datei lib/foo/bar.lua in eine globale Variable namens contains schreibt, die Zeile 1506 von der globalen Variable setvar liest und die Zeile 1545 die globale varexpand liest.
Dieses Tool stellt sicher, dass lokale Variablen in den Lua-Modulfunktionen alle mit dem local-Schlüsselwort deklariert sind, andernfalls wird eine Laufzeitausnahme ausgelöst. Es verhindert unerwünschte Wettlaufbedingungen beim Zugriff auf solche Variablen. Siehe Datenaustausch innerhalb eines NGINX-Workers für die Gründe dahinter.
Standorte, die durch Subrequest-Direktiven anderer Module konfiguriert sind
Die ngx.location.capture und ngx.location.capture_multi Direktiven können Standorte nicht erfassen, die die add_before_body, add_after_body, auth_request, echo_location, echo_location_async, echo_subrequest oder echo_subrequest_async Direktiven enthalten.
location /foo {
content_by_lua_block {
res = ngx.location.capture("/bar")
}
}
location /bar {
echo_location /blah;
}
location /blah {
echo "Erfolg!";
}
$ curl -i http://example.com/foo
wird nicht wie erwartet funktionieren.
Cosockets nicht überall verfügbar
Aufgrund interner Einschränkungen im NGINX-Kern ist die Cosocket-API in den folgenden Kontexten deaktiviert: set_by_lua*, log_by_lua*, header_filter_by_lua*, und body_filter_by_lua.
Die Cosockets sind derzeit auch in den Kontexten init_by_lua* und init_worker_by_lua* deaktiviert, aber wir könnten in Zukunft Unterstützung für diese Kontexte hinzufügen, da es keine Einschränkung im NGINX-Kern gibt (oder die Einschränkung könnte umgangen werden).
Es gibt jedoch einen Workaround, wenn der ursprüngliche Kontext nicht auf die Cosocket-Ergebnisse warten muss. Das heißt, ein Timer mit null Verzögerung über die ngx.timer.at API zu erstellen und die Cosocket-Ergebnisse im Timer-Handler zu verarbeiten, der asynchron zum ursprünglichen Kontext, der den Timer erstellt hat, läuft.
Besondere Escape-Sequenzen
HINWEIS Nach der Veröffentlichung von v0.9.17 kann diese Falle vermieden werden, indem die *_by_lua_block {} Konfigurationsdirektiven verwendet werden.
PCRE-Sequenzen wie \d, \s oder \w erfordern besondere Aufmerksamkeit, da im Stringliteral der Backslash-Zeichen \ sowohl vom Lua-Sprachparser als auch vom NGINX-Konfigurationsdateiparser entfernt wird, bevor sie verarbeitet werden, wenn sie sich nicht innerhalb einer *_by_lua_block {}-Direktive befinden. Daher wird der folgende Snippet nicht wie erwartet funktionieren:
# nginx.conf
? location /test {
? content_by_lua '
? local regex = "\d+" -- DAS IST FALSCH AUSSERHALB EINER *_by_lua_block-DIREKTIVE
? local m = ngx.re.match("hallo, 1234", regex)
? if m then ngx.say(m[0]) else ngx.say("nicht übereingestimmt!") end
? ';
? }
# wertet zu "nicht übereingestimmt!"
Um dies zu vermeiden, doppelt den Backslash zu escapen:
# nginx.conf
location /test {
content_by_lua '
local regex = "\\\\d+"
local m = ngx.re.match("hallo, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("nicht übereingestimmt!") end
';
}
# wertet zu "1234"
Hier wird \\\\d+ vom NGINX-Konfigurationsdateiparser auf \\d+ reduziert und dann vom Lua-Sprachparser vor der Ausführung korrekt verarbeitet.
Alternativ kann das Regex-Muster als langgebracketed Lua-Stringliteral dargestellt werden, indem es in "langen Klammern" [[...]] eingeschlossen wird, in diesem Fall müssen die Backslashes nur einmal für den NGINX-Konfigurationsdateiparser escaped werden.
# nginx.conf
location /test {
content_by_lua '
local regex = [[\\d+]]
local m = ngx.re.match("hallo, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("nicht übereingestimmt!") end
';
}
# wertet zu "1234"
Hier wird [[\\d+]] vom NGINX-Konfigurationsdateiparser auf [[\d+]] reduziert und korrekt verarbeitet.
Bitte beachten Sie, dass eine längere Form der langen Klammer [=[...]=] erforderlich sein kann, wenn das Regex-Muster [...]-Sequenzen enthält. Die [=[...]=]-Form kann als Standardform verwendet werden, wenn gewünscht.
# nginx.conf
location /test {
content_by_lua '
local regex = [=[[0-9]+]=]
local m = ngx.re.match("hallo, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("nicht übereingestimmt!") end
';
}
# wertet zu "1234"
Ein alternativer Ansatz zum Escapen von PCRE-Sequenzen besteht darin, sicherzustellen, dass Lua-Code in externen Skriptdateien platziert wird und mit den verschiedenen *_by_lua_file-Direktiven ausgeführt wird. Mit diesem Ansatz werden die Backslashes nur vom Lua-Sprachparser entfernt und müssen daher jeweils nur einmal escaped werden.
-- test.lua
local regex = "\\d+"
local m = ngx.re.match("hallo, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("nicht übereingestimmt!") end
-- wertet zu "1234"
Innerhalb externer Skriptdateien erfordern PCRE-Sequenzen, die als langgebracketed Lua-Stringliterale dargestellt werden, keine Modifikation.
-- test.lua
local regex = [[\d+]]
local m = ngx.re.match("hallo, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("nicht übereingestimmt!") end
-- wertet zu "1234"
Wie bereits erwähnt, erfordern PCRE-Sequenzen, die innerhalb von *_by_lua_block {}-Direktiven (verfügbar nach der Veröffentlichung von v0.9.17) dargestellt werden, keine Modifikation.
# nginx.conf
location /test {
content_by_lua_block {
local regex = [[\d+]]
local m = ngx.re.match("hallo, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("nicht übereingestimmt!") end
}
}
# wertet zu "1234"
HINWEIS Es wird empfohlen, by_lua_file zu verwenden, wenn der Lua-Code sehr lang ist.
SSI-Mischung nicht unterstützt
Die Mischung von SSI mit ngx_lua in derselben NGINX-Anfrage wird überhaupt nicht unterstützt. Verwenden Sie einfach ngx_lua ausschließlich. Alles, was Sie mit SSI tun können, kann ohnehin über ngx_lua erledigt werden, und es kann effizienter sein, wenn Sie ngx_lua verwenden.
SPDY-Modus nicht vollständig unterstützt
Bestimmte Lua-APIs, die von ngx_lua bereitgestellt werden, funktionieren im SPDY-Modus von NGINX noch nicht: ngx.location.capture, ngx.location.capture_multi und ngx.req.socket.
Fehlende Daten bei kurzschlüssigen Anfragen
NGINX kann eine Anfrage vorzeitig mit (mindestens) beenden:
- 400 (Bad Request)
- 405 (Not Allowed)
- 408 (Request Timeout)
- 413 (Request Entity Too Large)
- 414 (Request URI Too Large)
- 494 (Request Headers Too Large)
- 499 (Client Closed Request)
- 500 (Internal Server Error)
- 501 (Not Implemented)
Das bedeutet, dass Phasen, die normalerweise ausgeführt werden, übersprungen werden, wie die Rewrite- oder Zugriffsphase. Das bedeutet auch, dass spätere Phasen, die unabhängig davon ausgeführt werden, z. B. log_by_lua, keinen Zugriff auf Informationen haben, die normalerweise in diesen Phasen festgelegt werden.
Änderungen
Die Änderungen, die in jeder Veröffentlichung dieses Moduls vorgenommen wurden, sind in den Änderungsprotokollen des OpenResty-Bundles aufgeführt:
https://openresty.org/#Changes
Siehe auch
Blog-Beiträge:
- Einführung in Lua-Land CPU Flame Graphs
- Wie OpenResty und NGINX Speicher zuweisen und verwalten
- Wie OpenResty und NGINX Shared Memory Zones RAM verbrauchen
- Speicherfragmentierung in OpenResty und NGINX's Shared Memory Zones
Andere verwandte Module und Bibliotheken:
- ngx_stream_lua_module für einen offiziellen Port dieses Moduls für das NGINX "Stream"-Subsystem (durchführen generische nachgelagerte TCP-Kommunikationen).
- lua-resty-memcached Bibliothek basierend auf ngx_lua-Cosocket.
- lua-resty-redis Bibliothek basierend auf ngx_lua-Cosocket.
- lua-resty-mysql Bibliothek basierend auf ngx_lua-Cosocket.
- lua-resty-upload Bibliothek basierend auf ngx_lua-Cosocket.
- lua-resty-dns Bibliothek basierend auf ngx_lua-Cosocket.
- lua-resty-websocket Bibliothek für sowohl WebSocket-Server als auch -Client, basierend auf ngx_lua-Cosocket.
- lua-resty-string Bibliothek basierend auf LuaJIT FFI.
- lua-resty-lock Bibliothek für eine nicht blockierende einfache Lock-API.
- lua-resty-cookie Bibliothek zur Manipulation von HTTP-Cookies.
- Routing-Anfragen zu verschiedenen MySQL-Abfragen basierend auf URI-Argumenten
- Dynamisches Routing basierend auf Redis und Lua
- Verwendung von LuaRocks mit ngx_lua
- Einführung in ngx_lua
- ngx_devel_kit
- echo-nginx-module
- drizzle-nginx-module
- postgres-nginx-module
- memc-nginx-module
- Das OpenResty-Bundle
- Nginx Systemtap Toolkit
Direktiven
- lua_load_resty_core
- lua_capture_error_log
- lua_use_default_type
- lua_malloc_trim
- lua_code_cache
- lua_thread_cache_max_entries
- lua_regex_cache_max_entries
- lua_regex_match_limit
- lua_package_path
- lua_package_cpath
- init_by_lua
- init_by_lua_block
- init_by_lua_file
- init_worker_by_lua
- init_worker_by_lua_block
- init_worker_by_lua_file
- exit_worker_by_lua_block
- exit_worker_by_lua_file
- set_by_lua
- set_by_lua_block
- set_by_lua_file
- precontent_by_lua_block
- precontent_by_lua_file
- content_by_lua
- content_by_lua_block
- content_by_lua_file
- server_rewrite_by_lua_block
- server_rewrite_by_lua_file
- rewrite_by_lua
- rewrite_by_lua_block
- rewrite_by_lua_file
- access_by_lua
- access_by_lua_block
- access_by_lua_file
- header_filter_by_lua
- header_filter_by_lua_block
- header_filter_by_lua_file
- body_filter_by_lua
- body_filter_by_lua_block
- body_filter_by_lua_file
- log_by_lua
- log_by_lua_block
- log_by_lua_file
- balancer_by_lua_block
- balancer_by_lua_file
- balancer_keepalive
- lua_need_request_body
- ssl_client_hello_by_lua_block
- ssl_client_hello_by_lua_file
- ssl_certificate_by_lua_block
- ssl_certificate_by_lua_file
- ssl_session_fetch_by_lua_block
- ssl_session_fetch_by_lua_file
- ssl_session_store_by_lua_block
- ssl_session_store_by_lua_file
- proxy_ssl_certificate_by_lua_block
- proxy_ssl_certificate_by_lua_file
- proxy_ssl_verify_by_lua_block
- proxy_ssl_verify_by_lua_file
- lua_shared_dict
- lua_socket_connect_timeout
- lua_socket_send_timeout
- lua_socket_send_lowat
- lua_socket_read_timeout
- lua_socket_buffer_size
- lua_socket_pool_size
- lua_socket_keepalive_timeout
- lua_socket_log_errors
- lua_ssl_ciphers
- lua_ssl_crl
- lua_ssl_protocols
- lua_ssl_certificate
- lua_ssl_certificate_key
- lua_ssl_trusted_certificate
- lua_ssl_verify_depth
- lua_ssl_key_log
- lua_ssl_conf_command
- lua_upstream_skip_openssl_default_verify
- lua_http10_buffering
- rewrite_by_lua_no_postpone
- access_by_lua_no_postpone
- precontent_by_lua_no_postpone
- lua_transform_underscores_in_response_headers
- lua_check_client_abort
- lua_max_pending_timers
- lua_max_running_timers
- lua_sa_restart
- lua_worker_thread_vm_pool_size
Die grundlegenden Bausteine des Skriptens von NGINX mit Lua sind Direktiven. Direktiven werden verwendet, um anzugeben, wann der Benutzer-Lua-Code ausgeführt wird und wie das Ergebnis verwendet wird. Unten ist ein Diagramm, das die Reihenfolge zeigt, in der die Direktiven ausgeführt werden.

lua_load_resty_core
syntax: lua_load_resty_core on|off
default: lua_load_resty_core on
context: http
Diese Direktive ist seit der Veröffentlichung von v0.10.16 dieses Moduls veraltet. Das resty.core-Modul von lua-resty-core wird jetzt während der Initialisierung der Lua-VM zwingend geladen. Das Angeben dieser Direktive hat keine Auswirkungen.
Diese Direktive wurde erstmals in der Veröffentlichung von v0.10.15 eingeführt und diente dazu, das resty.core-Modul optional zu laden.
lua_capture_error_log
syntax: lua_capture_error_log size
default: none
context: http
Aktiviert einen Puffer der angegebenen size, um alle NGINX-Fehlerprotokollnachrichtendaten (nicht nur die, die von diesem Modul oder dem NGINX-HTTP-Subsystem erzeugt werden, sondern alles) zu erfassen, ohne Dateien oder Festplatten zu berühren.
Sie können Einheiten wie k und m im size-Wert verwenden, wie in
lua_capture_error_log 100k;
Als Faustregel kann ein 4KB-Puffer normalerweise etwa 20 typische Fehlermeldungen im Protokoll halten. Also rechnen Sie nach!
Dieser Puffer wächst nie. Wenn er voll ist, werden neue Fehlermeldungen die ältesten im Puffer ersetzen.
Die Größe des Puffers muss größer sein als die maximale Länge einer einzelnen Fehlermeldung (die in OpenResty 4K und in der Standard-NGINX 2K beträgt).
Sie können die Nachrichten im Puffer im Lua-Bereich über die get_logs() Funktion des ngx.errlog Moduls der lua-resty-core Bibliothek lesen. Diese Lua-API-Funktion gibt die erfassten Fehlermeldungen zurück und entfernt auch diese bereits gelesenen aus dem globalen Erfassungsbuffer, wodurch Platz für neue Fehlermeldungsdaten geschaffen wird. Aus diesem Grund sollte der Benutzer diesen Puffer nicht zu groß konfigurieren, wenn der Benutzer die gepufferten Fehlermeldungsdaten schnell genug liest.
Bitte beachten Sie, dass die im Standard error_log Direktive angegebene Protokollebene tatsächlich Auswirkungen auf diese Erfassungsfunktion hat. Es erfasst nur Protokollnachrichten einer Ebene, die nicht niedriger ist als die in der error_log Direktive angegebene Protokollebene. Der Benutzer kann weiterhin wählen, eine noch höhere Filterprotokollebene zur Laufzeit über die Lua-API-Funktion errlog.set_filter_level festzulegen. Daher ist es flexibler als die statische error_log Direktive.
Es ist erwähnenswert, dass es keine Möglichkeit gibt, die Debug-Protokolle zu erfassen, ohne OpenResty oder NGINX mit der ./configure-Option --with-debug zu erstellen. Und das Aktivieren von Debug-Protokollen wird aufgrund des hohen Overheads in Produktions-Bauten dringend abgeraten.
Diese Direktive wurde erstmals in der Veröffentlichung von v0.10.9 eingeführt.
lua_use_default_type
syntax: lua_use_default_type on | off
default: lua_use_default_type on
context: http, server, location, location if
Gibt an, ob der MIME-Typ, der durch die default_type Direktive angegeben ist, für den Standardwert des Content-Type-Antwortheaders verwendet werden soll. Deaktivieren Sie diese Direktive, wenn kein standardmäßiger Content-Type-Antwortheader für Lua-Anforderungs-Handler gewünscht ist.
Diese Direktive ist standardmäßig aktiviert.
Diese Direktive wurde erstmals in der Veröffentlichung von v0.9.1 eingeführt.
lua_malloc_trim
syntax: lua_malloc_trim <request-count>
default: lua_malloc_trim 1000
context: http
Fordert die zugrunde liegende libc-Laufzeitbibliothek an, ihren zwischengespeicherten freien Speicher alle N Anfragen, die vom NGINX-Kern verarbeitet werden, an das Betriebssystem zurückzugeben. Standardmäßig ist N 1000. Sie können die Anforderungsanzahl konfigurieren, indem Sie Ihre eigenen Zahlen verwenden. Kleinere Zahlen bedeuten häufigere Freigaben, was möglicherweise einen höheren CPU-Zeitverbrauch und einen kleineren Speicherbedarf zur Folge hat, während größere Zahlen normalerweise zu weniger CPU-Zeitaufwand und relativ größerem Speicherbedarf führen. Passen Sie die Zahl für Ihre eigenen Anwendungsfälle an.
Das Konfigurieren des Arguments auf 0 schaltet das periodische Trimmen des Speichers vollständig ab.
lua_malloc_trim 0; # schalte das Trimmen vollständig aus
Die aktuelle Implementierung verwendet einen NGINX-Protokollphasenhandler, um die Anfragen zu zählen. Daher kann das Auftreten der log_subrequest on Direktive in der nginx.conf das Zählen beschleunigen, wenn Subrequests beteiligt sind. Standardmäßig zählen nur "Hauptanfragen".
Bitte beachten Sie, dass diese Direktive nicht den Speicher beeinflusst, der von LuaJITs eigenem Allokator basierend auf dem mmap-Systemaufruf zugewiesen wird.
Diese Direktive wurde erstmals in der Veröffentlichung von v0.10.7 eingeführt.
lua_code_cache
syntax: lua_code_cache on | off
default: lua_code_cache on
context: http, server, location, location if
Aktiviert oder deaktiviert den Lua-Code-Cache für Lua-Code in *_by_lua_file-Direktiven (wie set_by_lua_file und content_by_lua_file) und Lua-Module.
Wenn es deaktiviert ist, wird jede Anfrage, die von ngx_lua bedient wird, in einer separaten Lua-VM-Instanz ausgeführt, beginnend mit der Veröffentlichung von 0.9.3. Daher werden die Lua-Dateien, die in set_by_lua_file, content_by_lua_file, access_by_lua_file usw. referenziert werden, nicht zwischengespeichert, und alle verwendeten Lua-Module werden von Grund auf neu geladen. Damit können Entwickler einen Edit-and-Refresh-Ansatz verfolgen.
Bitte beachten Sie jedoch, dass Lua-Code, der inline in nginx.conf geschrieben ist, wie die durch set_by_lua, content_by_lua, access_by_lua und rewrite_by_lua angegebenen, nicht aktualisiert wird, wenn Sie den inline Lua-Code in Ihrer nginx.conf-Datei bearbeiten, da nur der NGINX-Konfigurationsdateiparser die nginx.conf-Datei korrekt analysieren kann und der einzige Weg darin besteht, die Konfigurationsdatei durch das Senden eines HUP-Signals neu zu laden oder NGINX einfach neu zu starten.
Selbst wenn der Code-Cache aktiviert ist, können Lua-Dateien, die von dofile oder loadfile in *_by_lua_file geladen werden, nicht zwischengespeichert werden (es sei denn, Sie zwischenspeichern die Ergebnisse selbst). Normalerweise können Sie entweder die init_by_lua oder init_by_lua_file Direktiven verwenden, um all diese Dateien zu laden, oder Sie machen diese Lua-Dateien zu echten Lua-Modulen und laden sie über require.
Das ngx_lua-Modul unterstützt nicht den stat-Modus, der mit dem Apache mod_lua-Modul verfügbar ist (noch).
Das Deaktivieren des Lua-Code-Caches wird für die Produktion dringend abgeraten und sollte nur während der Entwicklung verwendet werden, da es erhebliche negative Auswirkungen auf die Gesamtleistung hat. Beispielsweise kann die Leistung eines "Hallo Welt"-Lua-Beispiels um einen Faktor von zehn sinken, nachdem der Lua-Code-Cache deaktiviert wurde.
lua_thread_cache_max_entries
syntax: lua_thread_cache_max_entries <num>
default: lua_thread_cache_max_entries 1024
context: http
Gibt die maximale Anzahl von Einträgen an, die im Cache für Lua-Threadobjekte auf der Ebene des Worker-Prozesses zulässig sind.
Dieser Cache recycelt die Lua-Thread-GC-Objekte zwischen all unseren "leichten Threads".
Ein Wert von <num> gleich Null deaktiviert den Cache.
Bitte beachten Sie, dass diese Funktion OpenRestys LuaJIT mit der neuen C-API lua_resetthread erfordert.
Diese Funktion wurde erstmals in der Version v0.10.9 eingeführt.
lua_regex_cache_max_entries
syntax: lua_regex_cache_max_entries <num>
default: lua_regex_cache_max_entries 1024
context: http
Gibt die maximale Anzahl von Einträgen an, die im Cache für kompilierte Regex auf der Ebene des Worker-Prozesses zulässig sind.
Die regulären Ausdrücke, die in ngx.re.match, ngx.re.gmatch, ngx.re.sub und ngx.re.gsub verwendet werden, werden innerhalb dieses Caches zwischengespeichert, wenn die Regex-Option o (d. h. Compile-Once-Flag) angegeben ist.
Die standardmäßig zulässige Anzahl von Einträgen beträgt 1024, und wenn dieses Limit erreicht wird, werden neue reguläre Ausdrücke nicht zwischengespeichert (als ob die o-Option nicht angegeben wurde), und es wird eine Warnung in der error.log-Datei ausgegeben:
2011/08/27 23:18:26 [warn] 31997#0: *1 lua überschreitet die maximale Anzahl von Regex-Caches (1024), ...
Wenn Sie die ngx.re.*-Implementierung von lua-resty-core verwenden, indem Sie das resty.core.regex-Modul (oder einfach das resty.core-Modul) laden, wird ein LRU-Cache für den hier verwendeten Regex-Cache verwendet.
Aktivieren Sie nicht die o-Option für reguläre Ausdrücke (und/oder replace-Stringargumente für ngx.re.sub und ngx.re.gsub), die on-the-fly generiert werden und unendliche Variationen erzeugen, um zu vermeiden, dass das angegebene Limit erreicht wird.
lua_regex_match_limit
syntax: lua_regex_match_limit <num>
default: lua_regex_match_limit 0
context: http
Gibt das "Match-Limit" an, das von der PCRE-Bibliothek beim Ausführen der ngx.re API verwendet wird. Um die PCRE-Man-Seite zu zitieren: "das Limit ... hat die Wirkung, die Menge an Backtracking zu begrenzen, die stattfinden kann."
Wenn das Limit erreicht wird, gibt die ngx.re API Funktionen den Fehlerstring "pcre_exec() fehlgeschlagen: -8" zurück.
Wenn das Limit auf 0 gesetzt wird, wird der Standardwert "Match-Limit" beim Kompilieren der PCRE-Bibliothek verwendet. Und dies ist der Standardwert dieser Direktive.
Diese Direktive wurde erstmals in der Veröffentlichung von v0.8.5 eingeführt.
lua_package_path
syntax: lua_package_path <lua-style-path-str>
default: Der Inhalt der LUA_PATH-Umgebungsvariable oder die in Lua kompilierten Standardwerte.
context: http
Setzt den Suchpfad für Lua-Module, der von Skripten verwendet wird, die durch set_by_lua, content_by_lua und andere angegeben sind. Der Pfad-String ist in standardmäßiger Lua-Pfadform, und ;; kann verwendet werden, um für die ursprünglichen Suchpfade zu stehen.
Seit der Veröffentlichung von v0.5.0rc29 kann die spezielle Notation $prefix oder ${prefix} im Suchpfad-String verwendet werden, um den Pfad des server prefix anzugeben, der normalerweise durch die -p PATH-Befehlszeilenoption beim Starten des NGINX-Servers bestimmt wird.
lua_package_cpath
syntax: lua_package_cpath <lua-style-cpath-str>
default: Der Inhalt der LUA_CPATH-Umgebungsvariable oder die in Lua kompilierten Standardwerte.
context: http
Setzt den Suchpfad für Lua-C-Module, der von Skripten verwendet wird, die durch set_by_lua, content_by_lua und andere angegeben sind. Der C-Pfad-String ist in standardmäßiger Lua-C-Pfadform, und ;; kann verwendet werden, um für den ursprünglichen C-Pfad zu stehen.
Seit der Veröffentlichung von v0.5.0rc29 kann die spezielle Notation $prefix oder ${prefix} im Suchpfad-String verwendet werden, um den Pfad des server prefix anzugeben, der normalerweise durch die -p PATH-Befehlszeilenoption beim Starten des NGINX-Servers bestimmt wird.
init_by_lua
syntax: init_by_lua <lua-script-str>
context: http
phase: loading-config
HINWEIS Die Verwendung dieser Direktive wird nach der Veröffentlichung von v0.9.17 abgeraten. Verwenden Sie stattdessen die Direktive init_by_lua_block.
Ähnlich wie die init_by_lua_block Direktive, aber akzeptiert den Lua-Quellcode direkt in einem NGINX-Stringliteral (was spezielle Zeichenescapings erfordert).
Zum Beispiel,
init_by_lua '
print("Ich brauche hier keine zusätzliche Escapierung, zum Beispiel: \r\nblah")
'
Diese Direktive wurde erstmals in der Veröffentlichung von v0.5.5 eingeführt.
init_by_lua_block
syntax: init_by_lua_block { lua-script }
context: http
phase: loading-config
Wenn NGINX das HUP-Signal erhält und die Konfigurationsdatei neu lädt, wird die Lua-VM ebenfalls neu erstellt und init_by_lua_block wird erneut auf der neuen Lua-VM ausgeführt. Falls die lua_code_cache Direktive deaktiviert ist (standardmäßig aktiviert), wird der init_by_lua_block-Handler bei jeder Anfrage ausgeführt, da in diesem speziellen Modus immer eine eigenständige Lua-VM für jede Anfrage erstellt wird.
Normalerweise können Sie Lua-Module beim Serverstart über diesen Hook vorladen und die Copy-on-Write (COW)-Optimierung moderner Betriebssysteme nutzen. Hier ist ein Beispiel zum Vorladen von Lua-Modulen:
# dies wird ausgeführt, bevor NGINX-Worker-Prozesse geforkt werden:
init_by_lua_block { require "cjson" }
server {
location = /api {
content_by_lua_block {
-- das folgende require() gibt nur
-- das bereits geladene Modul aus package.loaded zurück:
ngx.say(require "cjson".encode{dog = 5, cat = 6})
}
}
}
Sie können auch den lua_shared_dict shm-Speicher in dieser Phase initialisieren. Hier ist ein Beispiel dafür:
lua_shared_dict dogs 1m;
init_by_lua_block {
local dogs = ngx.shared.dogs
dogs:set("Tom", 56)
}
server {
location = /api {
content_by_lua_block {
local dogs = ngx.shared.dogs
ngx.say(dogs:get("Tom"))
}
}
}
Aber beachten Sie, dass der shm-Speicher des lua_shared_dict durch ein Konfigurationsneuladen (z. B. durch das Senden eines HUP-Signals) nicht gelöscht wird. Wenn Sie also nicht möchten, dass der shm-Speicher in Ihrem init_by_lua_block-Code neu initialisiert wird, müssen Sie einfach ein benutzerdefiniertes Flag im shm-Speicher setzen und immer das Flag in Ihrem init_by_lua_block-Code überprüfen.
Da der Lua-Code in diesem Kontext ausgeführt wird, bevor NGINX seine Worker-Prozesse (falls vorhanden) forked, genießen die hier geladenen Daten oder Codes die Copy-on-Write (COW)-Funktion, die von vielen Betriebssystemen unter allen Worker-Prozessen bereitgestellt wird, wodurch viel Speicher gespart wird.
Setzen Sie nicht Ihre eigenen Lua-Globalvariablen in diesem Kontext, da die Verwendung globaler Lua-Variablen Leistungseinbußen mit sich bringt und zu einer Verschmutzung des globalen Namensraums führen kann (siehe den Abschnitt Lua-Variablenbereich für weitere Details). Der empfohlene Weg ist, geeignete Lua-Modul-Dateien zu verwenden (aber verwenden Sie nicht die Standard-Lua-Funktion module(), um Lua-Module zu definieren, da sie ebenfalls den globalen Namensraum verschmutzen) und rufen Sie require() auf, um Ihre eigenen Moduldateien in init_by_lua_block oder anderen Kontexten zu laden (require() speichert die geladenen Lua-Module im globalen package.loaded-Tabelle im Lua-Register, sodass Ihre Module nur einmal für die gesamte Lua-VM-Instanz geladen werden).
Nur eine kleine Menge der Nginx API für Lua wird in diesem Kontext unterstützt:
- Logging-APIs: ngx.log und print,
- Shared Dictionary API: ngx.shared.DICT.
Weitere NGINX-APIs für Lua können in diesem Kontext auf zukünftige Benutzeranfragen unterstützt werden.
Im Grunde können Sie Lua-Bibliotheken, die blockierendes I/O in diesem speziellen Kontext durchführen, sicher verwenden, da das Blockieren des Masterprozesses während des Serverstarts völlig in Ordnung ist. Selbst der NGINX-Kern führt blockierendes I/O (zumindest beim Auflösen von Upstream-Hostnamen) in der Konfigurationsladephase durch.
Sie sollten sehr vorsichtig bei potenziellen Sicherheitsanfälligkeiten in Ihrem Lua-Code sein, der in diesem Kontext registriert ist, da der NGINX-Masterprozess häufig unter dem root-Konto ausgeführt wird.
Diese Direktive wurde erstmals in der Veröffentlichung von v0.9.17 eingeführt.
Siehe auch die folgenden Blog-Beiträge für weitere Details zu OpenResty und NGINX's Shared Memory Zones:
- [Wie OpenResty und NGINX Shared Memory Zones RAM verbrauchen](https://blog.openresty.com/en/how-nginx-shm-consume-ram




