ngx_http_lua_module – Integrieren Sie die Leistungsfähigkeit von Lua in Nginx-HTTP-Server.
Dieses Modul ist eine Kernkomponente von OpenResty. Wenn Sie dieses Modul verwenden, verwenden Sie im Wesentlichen OpenResty :)
Dieses Modul wird nicht mit der Nginx-Quelle verteilt. Siehe Installationsanleitung.
Produktionsbereit.
Dieses Dokument beschreibt ngx_lua v0.10.25, das am 19. Juni 2023 veröffentlicht wurde.
YouTube-Video „Hello World HTTP-Beispiel mit OpenResty/Lua“
YouTube-Video „Schreiben Sie Ihre eigenen Lua-Module in OpenResty/Nginx-Anwendungen“
YouTube-Video „Demo des resty Command-Line Utility von OpenResty“
YouTube-Video „Ausführungszeit von Lua-Code in OpenResty richtig messen“
YouTube-Video „Lua-Module in LuaJIT-Bytecode vorkompilieren, um den Start von OpenResty zu beschleunigen“
Gerne können Sie unseren offiziellen YouTube-Kanal OpenResty abonnieren.
Zurück zum Inhaltsverzeichnis
# set search paths for pure Lua external libraries (';;' is the default path):
lua_package_path '/foo/bar/?.lua;/blah/?.lua;;' ;
# set search paths for Lua external libraries written in C (can also use ';;'):
lua_package_cpath '/bar/baz/?.so;/blah/blah/?.so;;' ;
server {
location /lua_content {
# MIME type determined by default_type:
default_type 'text/plain' ;
content_by_lua_block {
ngx.say('Hello,world!')
}
}
location /nginx_var {
# MIME type determined by default_type:
default_type 'text/plain' ;
# try access /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() -- explicitly read the req body
local data = ngx.req.get_body_data()
if data then
ngx.say(" body data: ")
ngx.print(data)
return
end
-- body may get buffered in a temp file:
local file = ngx.req.get_body_file()
if file then
ngx.say(" body is in file ", file)
else
ngx.say(" no body found ")
end
}
}
# transparent non-blocking I/O in Lua via subrequests
# (well, a better way is to use cosockets)
location = /lua {
# MIME type determined by default_type:
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(" body: ")
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;
}
# use nginx var in code path
# CAUTION: contents in nginx var must be carefully filtered,
# otherwise there'll be great security risk!
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 {
-- check the client IP address is in our black list
if ngx.var.remote_addr == " 132.5.72.3 " then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
-- check if the URI contains bad words
if ngx.var.uri and
string.match(ngx.var.request_body, " evil ")
then
return ngx.redirect(" /terms_of_use.html ")
end
-- tests passed
}
# proxy_pass/fastcgi_pass/etc settings
}
}
Zurück zum Inhaltsverzeichnis
Dieses Modul bettet LuaJIT 2.0/2.1 in Nginx ein. Es ist eine Kernkomponente 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. In diesem Dokument werden die Begriffe „Lua“ und „LuaJIT“ abwechselnd verwendet, um sich auf den LuaJIT-Interpreter zu beziehen.
Durch die Nutzung der Unteranforderungen von Nginx ermöglicht dieses Modul die Integration der leistungsstarken Lua-Threads (bekannt als Lua-„Coroutinen“) in das Nginx-Ereignismodell.
Im Gegensatz zu mod_lua von Apache und mod_magnet von Lighttpd kann Lua-Code, der mit diesem Modul ausgeführt wird, den Netzwerkverkehr zu 100 % nicht blockieren, solange die von diesem Modul bereitgestellte Nginx-API für Lua verwendet wird, um Anfragen an Upstream-Dienste wie MySQL, PostgreSQL, Memcached zu verarbeiten , Redis oder Upstream-HTTP-Webdienste.
Mit diesem Modul können mindestens die folgenden Lua-Bibliotheken und Nginx-Module verwendet werden:
Nahezu alle Nginx-Module können mit diesem ngx_lua-Modul über ngx.location.capture oder ngx.location.capture_multi verwendet werden. Es wird jedoch empfohlen, diese lua-resty-*
-Bibliotheken zu verwenden, anstatt Unteranforderungen für den Zugriff auf die Nginx-Upstream-Module zu erstellen Ersteres ist normalerweise viel flexibler und speichereffizienter.
Der Lua-Interpreter (auch bekannt als „Lua State“ oder „LuaJIT VM-Instanz“) wird von allen Anforderungen in einem einzelnen Nginx-Workerprozess gemeinsam genutzt, um die Speichernutzung zu minimieren. Anforderungskontexte werden mithilfe einfacher Lua-Coroutinen getrennt.
Geladene Lua-Module bleiben auf der Ebene des Nginx-Worker-Prozesses bestehen, was zu einem geringen Speicherbedarf in Lua führt, selbst bei hoher Auslastung.
Dieses Modul ist in das „http“-Subsystem von Nginx eingebunden, sodass es nur Downstream-Kommunikationsprotokolle der HTTP-Familie (HTTP 0.9/1.0/1.1/2.0, WebSockets usw.) sprechen kann. Wenn Sie generische TCP-Kommunikation mit den Downstream-Clients durchführen möchten, sollten Sie stattdessen das Modul ngx_stream_lua verwenden, das eine kompatible Lua-API bietet.
Zurück zum Inhaltsverzeichnis
Um nur einige zu nennen:
Die Möglichkeiten sind unbegrenzt, da das Modul es ermöglicht, verschiedene Elemente innerhalb von Nginx zusammenzuführen und dem Benutzer die Leistungsfähigkeit der Lua-Sprache zugänglich zu machen. Das Modul bietet die volle Flexibilität der Skripterstellung und bietet dank LuaJIT 2.x ein Leistungsniveau, das sowohl hinsichtlich der CPU-Zeit als auch des Speicherbedarfs mit nativen C-Sprachprogrammen vergleichbar ist.
Andere Implementierungen von Skriptsprachen haben normalerweise Schwierigkeiten, dieses Leistungsniveau zu erreichen.
Zurück zum Inhaltsverzeichnis
Die neueste Version dieses Moduls ist mit den folgenden Versionen von Nginx kompatibel:
Nginx-Kerne älter als 1.6.0 (exklusiv) werden nicht unterstützt.
Zurück zum Inhaltsverzeichnis
Es wird dringend empfohlen, OpenResty-Versionen zu verwenden, die Nginx, ngx_lua (dieses Modul), LuaJIT sowie andere leistungsstarke begleitende Nginx-Module und Lua-Bibliotheken bündeln.
Es wird davon abgeraten, dieses Modul selbst mit Nginx zu erstellen, da es schwierig ist, es genau richtig einzurichten.
Beachten Sie, dass die offiziellen Versionen von Nginx, LuaJIT und OpenSSL verschiedene Einschränkungen und seit langem bestehende Fehler aufweisen, die dazu führen können, dass einige Funktionen dieses Moduls deaktiviert sind, nicht ordnungsgemäß funktionieren oder langsamer laufen. Offizielle OpenResty-Versionen werden empfohlen, da sie den optimierten LuaJIT 2.1-Fork von OpenResty und Nginx/OpenSSL-Patches bündeln.
Alternativ kann ngx_lua manuell in Nginx kompiliert werden:
Erstellen Sie die Quelle mit diesem Modul:
wget ' https://openresty.org/download/nginx-1.19.3.tar.gz '
tar -xzvf nginx-1.19.3.tar.gz
cd nginx-1.19.3/
# tell nginx's build system where to find LuaJIT 2.0:
export LUAJIT_LIB=/path/to/luajit/lib
export LUAJIT_INC=/path/to/luajit/include/luajit-2.0
# tell nginx's build system where to find LuaJIT 2.1:
export LUAJIT_LIB=/path/to/luajit/lib
export LUAJIT_INC=/path/to/luajit/include/luajit-2.1
# Here we assume Nginx is to be installed under /opt/nginx/.
./configure --prefix=/opt/nginx
--with-ld-opt= " -Wl,-rpath,/path/to/luajit/lib "
--add-module=/path/to/ngx_devel_kit
--add-module=/path/to/lua-nginx-module
# Note that you may also want to add `./configure` options which are used in your
# current nginx build.
# You can get usually those options using command nginx -V
# you can change the parallelism number 2 below to fit the number of spare CPU cores in your
# machine.
make -j2
make install
# Note that this version of lug-nginx-module not allow to set `lua_load_resty_core off;` any more.
# So, you have to install `lua-resty-core` and `lua-resty-lrucache` manually as below.
cd lua-resty-core
make install PREFIX=/opt/nginx
cd lua-resty-lrucache
make install PREFIX=/opt/nginx
# add necessary `lua_package_path` directive to `nginx.conf`, in the http context
lua_package_path " /opt/nginx/lib/lua/?.lua;; " ;
Zurück zum Inhaltsverzeichnis
Ab NGINX 1.9.11 können Sie dieses Modul auch als dynamisches Modul kompilieren, indem Sie die Option --add-dynamic-module=PATH
anstelle von --add-module=PATH
in der obigen ./configure
verwenden. Und dann können Sie das Modul explizit über die Anweisung „load_module“ in Ihre nginx.conf
laden, zum Beispiel:
load_module /path/to/modules/ndk_http_module.so; # assuming NDK is built as a dynamic module too
load_module /path/to/modules/ngx_http_lua_module.so;
Zurück zum Inhaltsverzeichnis
Während Sie dieses Modul entweder über OpenResty oder mit dem Nginx-Kern erstellen, können Sie die folgenden C-Makros über die C-Compiler-Optionen definieren:
NGX_LUA_USE_ASSERT
Aktiviert bei Definition Assertionen in der ngx_lua-C-Codebasis. Empfohlen zum Debuggen oder Testen von Builds. Wenn es aktiviert ist, kann es zu einem (geringen) Laufzeitaufwand kommen. Dieses Makro wurde erstmals in der Version v0.9.10
eingeführt.NGX_LUA_ABORT_AT_PANIC
Wenn die LuaJIT-VM in Panik gerät, weist ngx_lua den aktuellen Nginx-Workerprozess standardmäßig an, ordnungsgemäß zu beenden. Durch die Angabe dieses C-Makros bricht ngx_lua den aktuellen Nginx-Worker-Prozess (der normalerweise zu einer Core-Dump-Datei führt) sofort ab. Diese Option ist nützlich zum Debuggen von VM-Paniken. Diese Option wurde erstmals in der Version v0.9.8
eingeführt. Um eines oder mehrere dieser Makros zu aktivieren, übergeben Sie einfach zusätzliche C-Compiler-Optionen an das ./configure
von Nginx oder OpenResty. Zum Beispiel,
./configure --with-cc-opt="-DNGX_LUA_USE_ASSERT -DNGX_LUA_ABORT_AT_PANIC"
Zurück zum Inhaltsverzeichnis
Zurück zum Inhaltsverzeichnis
Die Mailingliste openresty-en richtet sich an englischsprachige Personen.
Zurück zum Inhaltsverzeichnis
Die Openresty-Mailingliste richtet sich an Chinesischsprachige.
Zurück zum Inhaltsverzeichnis
Das Code-Repository dieses Projekts wird auf GitHub unter openresty/lua-nginx-module gehostet.
Zurück zum Inhaltsverzeichnis
Bitte senden Sie Fehlerberichte, Wunschlisten oder Patches per
Zurück zum Inhaltsverzeichnis
Sehen Sie sich das YouTube-Video „Messen Sie die Ausführungszeit von Lua-Code korrekt in OpenResty“ an.
Ab der Version v0.5.0rc32
unterstützen alle *_by_lua_file
Konfigurationsanweisungen (z. B. content_by_lua_file) das direkte Laden von LuaJIT 2.0/2.1-Rohbytecodedateien:
/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 aufzunehmen:
/path/to/luajit/bin/luajit -bg /path/to/input_file.lua /path/to/output_file.ljbc
Weitere Informationen finden Sie in der offiziellen LuaJIT-Dokumentation zur Option -b
:
https://luajit.org/running.html#opt_b
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 verknüpft sind (oder umgekehrt), führen zu einer Nginx-Fehlermeldung wie der folgenden:
[error] 13909#0: *1 failed to load Lua inlined code: bad byte-code header in /path/to/test_file.luac
Das Laden von Bytecode-Dateien über die Lua-Grundelemente wie require
und dofile
sollte immer wie erwartet funktionieren.
Zurück zum Inhaltsverzeichnis
Wenn Sie über die Standard-Lua-API os.getenv auf die Systemumgebungsvariable, beispielsweise foo
, in Lua zugreifen möchten, sollten Sie diesen Umgebungsvariablennamen auch über die env-Direktive in Ihrer nginx.conf
Datei auflisten. Zum Beispiel,
env foo;
Zurück zum Inhaltsverzeichnis
Das HTTP 1.0-Protokoll unterstützt keine Chunked-Ausgabe und erfordert einen expliziten Content-Length
Header, wenn der Antworttext nicht leer ist, um das HTTP 1.0-Keep-Alive zu unterstützen. Wenn also eine HTTP 1.0-Anfrage gestellt wird und die Direktive lua_http10_buffering on
ist, puffert ngx_lua die Ausgabe von ngx.say- und ngx.print-Aufrufen und verschiebt außerdem das Senden von Antwortheadern, bis die gesamte Antworttextausgabe empfangen wurde. Zu diesem Zeitpunkt kann ngx_lua die Gesamtlänge des Körpers berechnen und einen geeigneten Content-Length
-Header erstellen, um ihn an den HTTP 1.0-Client zurückzugeben. Wenn der Content-Length
-Antwortheader jedoch im laufenden Lua-Code festgelegt ist, wird diese Pufferung deaktiviert, selbst wenn die Direktive lua_http10_buffering on
ist.
Bei großen Streaming-Ausgabeantworten ist es wichtig, die Direktive lua_http10_buffering zu deaktivieren, um die Speichernutzung zu minimieren.
Beachten Sie, dass gängige HTTP-Benchmark-Tools wie ab
und http_load
standardmäßig HTTP 1.0-Anfragen ausgeben. Um zu erzwingen, dass curl
HTTP 1.0-Anfragen sendet, verwenden Sie die Option -0
.
Zurück zum Inhaltsverzeichnis
Mit LuaJIT 2.x ist es möglich, den Bytecode reiner Lua-Module statisch in die ausführbare Nginx-Datei einzubinden.
Sie können die ausführbare luajit
Datei verwenden, um .lua
-Lua-Moduldateien in .o
Objektdateien mit den exportierten Bytecode-Daten zu kompilieren und die .o
Dateien dann direkt in Ihrem Nginx-Build zu verknüpfen.
Nachfolgend finden Sie ein triviales Beispiel, um dies zu demonstrieren. Bedenken Sie, dass wir die folgende .lua
Datei mit dem Namen foo.lua
haben:
-- foo.lua
local _M = {}
function _M . go ()
print ( " Hello from foo " )
end
return _M
Und dann kompilieren wir diese .lua
Datei in foo.o
Datei:
/path/to/luajit/bin/luajit -bg foo.lua foo.o
Entscheidend ist hier der Name der .lua
Datei, der bestimmt, wie Sie dieses Modul später im Lua-Land nutzen. Der Dateiname foo.o
spielt überhaupt keine Rolle, außer der Dateierweiterung .o
(die luajit
angibt, welches Ausgabeformat verwendet wird). Wenn Sie die Lua-Debug-Informationen aus dem resultierenden Bytecode entfernen möchten, können Sie einfach die Option -b
oben anstelle von -bg
angeben.
Übergeben Sie dann beim Erstellen von Nginx oder OpenResty die Option --with-ld-opt="foo.o"
an das Skript ./configure
:
./configure --with-ld-opt= " /path/to/foo.o " ...
Schließlich können Sie in jedem von ngx_lua ausgeführten Lua-Code einfach Folgendes tun:
local foo = require " foo "
foo . go ()
Und dieser Code ist nicht mehr von der externen foo.lua
-Datei abhängig, da er bereits in die ausführbare nginx
Datei kompiliert wurde.
Wenn Sie beim Aufruf require
einen Punkt im Lua-Modulnamen verwenden möchten, wie in
local foo = require " resty.foo "
Anschließend müssen Sie die Datei foo.lua
in resty_foo.lua
umbenennen, bevor Sie sie mit dem Befehlszeilendienstprogramm luajit
in eine .o
Datei kompilieren.
Es ist wichtig, beim Kompilieren von .lua
-Dateien zu .o
Dateien genau dieselbe Version von LuaJIT zu verwenden wie beim Erstellen von nginx + ngx_lua. Dies liegt daran, dass das LuaJIT-Bytecode-Format zwischen verschiedenen LuaJIT-Versionen möglicherweise nicht kompatibel ist. Wenn das Bytecode-Format nicht kompatibel ist, wird ein Lua-Laufzeitfehler angezeigt, der besagt, dass das Lua-Modul nicht gefunden wurde.
Wenn Sie mehrere .lua
Dateien kompilieren und verknüpfen müssen, geben Sie einfach deren .o
Dateien gleichzeitig im Wert der Option --with-ld-opt
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 möglich, 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 in
ar rcus libmyluafiles.a * .o
Anschließend können Sie das myluafiles
-Archiv als Ganzes mit Ihrer ausführbaren Nginx-Datei verknüpfen:
./configure
--with-ld-opt= " -L/path/to/lib -Wl,--whole-archive -lmyluafiles -Wl,--no-whole-archive "
Dabei ist /path/to/lib
der Pfad des Verzeichnisses, das die Datei libmyluafiles.a
enthält. Es ist zu beachten, dass hier die Linker-Option --whole-archive
erforderlich ist, da sonst unser Archiv übersprungen wird, da in den Hauptteilen der ausführbaren Nginx-Datei keine Symbole in unserem Archiv erwähnt werden.
Zurück zum Inhaltsverzeichnis
Um Daten global für alle vom selben Nginx-Workerprozess verarbeiteten Anforderungen gemeinsam zu nutzen, kapseln Sie die gemeinsam genutzten Daten in ein Lua-Modul, verwenden Sie die integrierte Lua- require
, um das Modul zu importieren, und bearbeiten Sie dann die gemeinsam genutzten Daten in Lua. Dies funktioniert, weil erforderliche Lua-Module nur einmal geladen werden und alle Coroutinen dieselbe Kopie des Moduls (sowohl seines Codes als auch seiner Daten) gemeinsam nutzen.
Beachten Sie, dass von der Verwendung globaler Lua-Variablen dringend abgeraten wird, da dies zu unerwarteten Wettlaufbedingungen zwischen gleichzeitigen Anforderungen 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 über nginx.conf
darauf zugreifen:
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 Speicherort /lua
geladen und ausgeführt, und alle nachfolgenden Anfragen an denselben Nginx-Workerprozess verwenden die neu geladene Instanz des Moduls sowie dieselbe Kopie der Daten in es, bis ein HUP
Signal an den Nginx-Masterprozess gesendet wird, um ein Neuladen zu erzwingen. Diese Datenaustauschtechnik ist für Hochleistungs-Lua-Anwendungen, die auf diesem Modul basieren, unerlässlich.
Beachten Sie, dass diese Datenfreigabe pro Worker und nicht pro Server erfolgt. Das heißt, wenn unter einem Nginx-Master mehrere Nginx-Worker-Prozesse vorhanden sind, kann die Datenfreigabe die Prozessgrenze zwischen diesen Workern nicht überschreiten.
Normalerweise wird empfohlen, schreibgeschützte Daten auf diese Weise freizugeben. Sie können veränderbare Daten auch für alle gleichzeitigen Anforderungen jedes Nginx-Workerprozesses freigeben, solange während Ihrer Berechnungen keine nicht blockierenden E/A-Vorgänge (einschließlich ngx.sleep) stattfinden. Solange Sie die Kontrolle nicht an die Nginx-Ereignisschleife und den Light-Thread-Scheduler von ngx_lua zurückgeben (auch nicht implizit), kann es dazwischen niemals zu Race-Bedingungen kommen. Seien Sie daher immer sehr vorsichtig, wenn Sie veränderbare Daten auf Worker-Ebene teilen möchten. Fehlerhafte Optimierungen können unter Last leicht zu schwer zu debuggenden Rennbedingungen führen.
Wenn eine serverweite Datenfreigabe erforderlich ist, verwenden Sie einen oder mehrere der folgenden Ansätze:
memcached
, redis
, MySQL
oder PostgreSQL
. Die offiziellen OpenResty-Versionen enthalten eine Reihe begleitender Nginx-Module und Lua-Bibliotheken, die Schnittstellen zu diesen Datenspeichermechanismen bereitstellen.Zurück zum Inhaltsverzeichnis
Zurück zum Inhaltsverzeichnis
Die Methode „tcpsock:connect“ kann trotz Verbindungsfehlern success
anzeigen, z. B. bei Connection Refused
-Fehlern.
Spätere Versuche, das Cosocket-Objekt zu manipulieren, schlagen jedoch fehl und geben die tatsächliche Fehlerstatusmeldung zurück, die durch den fehlgeschlagenen Verbindungsvorgang generiert wurde.
Dieses Problem ist auf Einschränkungen im Nginx-Ereignismodell zurückzuführen und scheint nur Mac OS X zu betreffen.
Zurück zum Inhaltsverzeichnis
dofile
und require
Builtins von Lua derzeit als C-Funktionen in LuaJIT 2.0/2.1 implementiert sind, ruft die von dofile
oder require
geladene Lua-Datei ngx.location.capture*, ngx.exec, ngx.exit oder andere API-Funktionen auf, die Yield erfordern im obersten Bereich der Lua-Datei wird dann der Lua-Fehler „Versuch, über die C-Aufruf-Grenze hinaus nachzugeben“ ausgelöst. Um dies zu vermeiden, fügen Sie diese Aufrufe, die eine Nachgabe erfordern, in Ihre eigenen Lua-Funktionen in der Lua-Datei ein und nicht in den Bereich der obersten Ebene der Datei.Zurück zum Inhaltsverzeichnis
Beim Importieren von Modulen ist Vorsicht geboten und dieses Formular sollte verwendet werden:
local xxx = require ( ' xxx ' )
anstelle der alten veralteten Form:
require ( ' xxx ' )
Hier ist der Grund: Die globale Umgebung hat konstruktionsbedingt genau die gleiche Lebensdauer wie der ihr zugeordnete Nginx-Request-Handler. Jeder Anforderungshandler verfügt über einen eigenen Satz globaler Lua-Variablen, und das ist die Idee der Anforderungsisolation. Das Lua-Modul wird tatsächlich vom ersten Nginx-Anforderungshandler geladen und von der in der Tabelle package.loaded
integrierten Funktion require()
zur späteren Referenz zwischengespeichert. Die von einigen Lua-Modulen verwendete integrierte Funktion module()
hat den Nebeneffekt der Einstellung eine globale Variable für die geladene Modultabelle. Diese globale Variable wird jedoch am Ende des Request-Handlers gelöscht, und jeder nachfolgende Request-Handler verfügt über seine eigene (saubere) globale Umgebung. Man erhält also eine Lua-Ausnahme für den Zugriff auf den nil
.
Die Verwendung globaler Lua-Variablen ist im ngx_lua-Kontext generell nicht zu empfehlen, da:
Es wird daher dringend empfohlen, dies stattdessen immer in einem geeigneten lokalen Bereich zu deklarieren.
-- Avoid
foo = 123
-- Recommended
local foo = 123
-- Avoid
function foo () return 123 end
-- Recommended
local function foo () return 123 end
Um alle Instanzen globaler Lua-Variablen in Ihrem Lua-Code zu finden, führen Sie das Tool lua-releng für alle .lua
Quelldateien aus:
$ lua-releng
Checking use of Lua global variables in file lib/foo/bar.lua ...
1 [1489] SETGLOBAL 7 -1 ; contains
55 [1506] GETGLOBAL 7 -3 ; setvar
3 [1545] GETGLOBAL 3 -4 ; varexpand
Die Ausgabe besagt, dass Zeile 1489 der Datei lib/foo/bar.lua
in eine globale Variable mit dem Namen contains
schreibt, Zeile 1506 aus der globalen Variablen „ setvar
liest und Zeile 1545 die globale varexpand
liest.
Dieses Tool stellt sicher, dass alle lokalen Variablen in den Funktionen des Lua-Moduls mit dem Schlüsselwort local
deklariert werden, andernfalls wird eine Laufzeitausnahme ausgelöst. Es verhindert unerwünschte Race Conditions beim Zugriff auf solche Variablen. Die Gründe dafür finden Sie unter Datenfreigabe innerhalb eines Nginx-Workers.
Zurück zum Inhaltsverzeichnis
Die Anweisungen ngx.location.capture und ngx.location.capture_multi können keine Standorte erfassen, die die Anweisungen add_before_body, add_after_body, auth_request, echo_location, echo_location_async, echo_subrequest oder echo_subrequest_async enthalten.
location /foo {
content_by_lua_block {
res = ngx.location.capture( "/bar" )
}
}
location /bar {
echo_location /blah;
}
location /blah {
echo "Success!" ;
}
$ curl -i http://example.com/foo
wird nicht wie erwartet funktionieren.
Zurück zum Inhaltsverzeichnis
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 Direktivenkontexten init_by_lua* und init_worker_by_lua* deaktiviert, aber wir werden möglicherweise in Zukunft Unterstützung für diese Kontexte hinzufügen, da es keine Einschränkung im Nginx-Kern gibt (oder die Einschränkung möglicherweise umgangen wird).
Es gibt jedoch eine Problemumgehung, wenn der ursprüngliche Kontext nicht auf die Cosocket-Ergebnisse warten muss. Das heißt, das Erstellen eines Null-Verzögerungs-Timers über die ngx.timer.at-API und die Ausführung des Cosockets führt zum Timer-Handler, der asynchron zum ursprünglichen Kontext läuft, der den Timer erstellt.
Zurück zum Inhaltsverzeichnis
HINWEIS Nach der Veröffentlichung v0.9.17
kann diese Gefahr durch die Verwendung der Konfigurationsanweisungen *_by_lua_block {}
vermieden werden.
PCRE-Sequenzen wie d
, s
oder w
erfordern besondere Aufmerksamkeit, da in Zeichenfolgenliteralen das Backslash-Zeichen vor der Verarbeitung sowohl vom Lua-Sprachparser als auch vom Nginx-Konfigurationsdateiparser entfernt wird, wenn es nicht innerhalb von a liegt
*_by_lua_block {}
-Direktive. Daher wird das folgende Snippet nicht wie erwartet funktionieren:
# nginx.conf
? location /test {
? content_by_lua '
? local regex = "d+" -- THIS IS WRONG OUTSIDE OF A *_by_lua_block DIRECTIVE
? local m = ngx.re.match("hello, 1234", regex)
? if m then ngx.say(m[0]) else ngx.say("not matched!") end
? ' ;
? }
# evaluates to "not matched!"
Um dies zu vermeiden, maskieren Sie den Backslash doppelt :
# nginx.conf
location /test {
content_by_lua '
local regex = "\\d+"
local m = ngx.re.match("hello, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("not matched!") end
' ;
}
# evaluates to "1234"
Hier wird \\d+
vom Parser der Nginx-Konfigurationsdatei auf \d+
reduziert, und dies wird vor der Ausführung vom Parser der Lua-Sprache weiter auf d+
reduziert.
Alternativ kann das Regex-Muster als Lua-String-Literal in langen Klammern dargestellt werden, indem es in „lange Klammern“ [[...]]
eingeschlossen wird. In diesem Fall müssen Backslashes für den Nginx-Konfigurationsdatei-Parser nur einmal maskiert werden.
# nginx.conf
location /test {
content_by_lua '
local regex = [[\d+]]
local m = ngx.re.match("hello, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("not matched!") end
' ;
}
# evaluates to "1234"
Hier wird [[\d+]]
vom Parser der Nginx-Konfigurationsdatei auf [[d+]]
reduziert und dies wird korrekt verarbeitet.
Beachten Sie, dass ein längeres from der langen Klammer, [=[...]=]
, erforderlich sein kann, wenn das Regex-Muster [...]
Sequenzen enthält. Das Formular [=[...]=]
kann bei Bedarf als Standardformular verwendet werden.
# nginx.conf
location /test {
content_by_lua '
local regex = [=[[0-9]+]=]
local m = ngx.re.match("hello, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("not matched!") end
' ;
}
# evaluates to "1234"
Ein alternativer Ansatz zum Escapen von PCRE-Sequenzen besteht darin, sicherzustellen, dass Lua-Code in externen Skriptdateien platziert und mithilfe der verschiedenen *_by_lua_file
-Direktiven ausgeführt wird. Bei diesem Ansatz werden die Backslashes nur vom Parser der Lua-Sprache entfernt und müssen daher jeweils nur einmal mit Escapezeichen versehen werden.
-- test.lua
local regex = " \ d+ "
local m = ngx . re . match ( " hello, 1234 " , regex )
if m then ngx . say ( m [ 0 ]) else ngx . say ( " not matched! " ) end
-- evaluates to "1234"
In externen Skriptdateien müssen PCRE-Sequenzen, die als Lua-String-Literale in langen Klammern dargestellt werden, nicht geändert werden.
-- test.lua
local regex = [[ d+ ]]
local m = ngx . re . match ( " hello, 1234 " , regex )
if m then ngx . say ( m [ 0 ]) else ngx . say ( " not matched! " ) end
-- evaluates to "1234"
Wie bereits erwähnt, müssen PCRE-Sequenzen, die in *_by_lua_block {}
-Direktiven (verfügbar nach der Version v0.9.17
) dargestellt werden, nicht geändert werden.
# nginx.conf
location /test {
content_by_lua_block {
local regex = [[d+]]
local m = ngx.re.match( "hello, 1234" , regex)
if m then ngx.say(m[0]) else ngx.say( "not matched!" ) end
}
}
# evaluates to "1234"
HINWEIS Es wird empfohlen, by_lua_file
zu verwenden, wenn der Lua-Code sehr lang ist.
Zurück zum Inhaltsverzeichnis
Das Mischen von SSI mit ngx_lua in derselben Nginx-Anfrage wird überhaupt nicht unterstützt. Verwenden Sie einfach ausschließlich ngx_lua. Alles, was Sie mit SSI tun können, kann ohnehin auf ngx_lua erledigt werden, und es kann effizienter sein, wenn Sie ngx_lua verwenden.
Zurück zum Inhaltsverzeichnis
Bestimmte von ngx_lua bereitgestellte Lua-APIs funktionieren noch nicht im SPDY-Modus von Nginx: ngx.location.capture, ngx.location.capture_multi und ngx.req.socket.
Zurück zum Inhaltsverzeichnis
Nginx kann eine Anfrage vorzeitig beenden mit (mindestens):
Dies bedeutet, dass Phasen, die normalerweise ablaufen, übersprungen werden, beispielsweise die Rewrite- oder Zugriffsphase. Dies 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.
Zurück zum Inhaltsverzeichnis
bsdrecv
-Methode überprüfen und zusammenführen.ngx_hash_t
um den integrierten Header-Suchprozess für ngx.req.set_header usw. zu optimieren.ignore_resp_headers
, ignore_resp_body
und ignore_resp
zu den Methoden ngx.location.capture und ngx.location.capture_multi hinzu, um eine Mikroleistungsoptimierung auf Benutzerseite zu ermöglichen.stat
Modus ähnlich wie mod_lua hinzufügen.Zurück zum Inhaltsverzeichnis
Die in jeder Version dieses Moduls vorgenommenen Änderungen sind in den Änderungsprotokollen des OpenResty-Bundles aufgeführt:
https://openresty.org/#Changes
Zurück zum Inhaltsverzeichnis
Zum Ausführen der Testsuite sind die folgenden Abhängigkeiten erforderlich:
Nginx-Version >= 1.4.2
Perl-Module:
Nginx-Module:
Die Reihenfolge, in der diese Module während der Konfiguration hinzugefügt werden, ist wichtig, da beispielsweise die Position eines Filtermoduls in der Filterkette die endgültige Ausgabe bestimmt. Die richtige Reihenfolge beim Hinzufügen ist oben dargestellt.
Lua-Bibliotheken von Drittanbietern:
Anwendungen: