ngx_http_lua_module - Nginx HTTP 서버에 Lua의 강력한 기능을 내장합니다.
이 모듈은 OpenResty의 핵심 구성 요소입니다. 이 모듈을 사용하고 있다면 본질적으로 OpenResty를 사용하고 있는 것입니다. :)
이 모듈은 Nginx 소스와 함께 배포되지 않습니다. 설치 지침을 참조하세요.
생산 준비 완료.
이 문서에서는 2023년 6월 19일에 출시된 ngx_lua v0.10.25에 대해 설명합니다.
YouTube 동영상 "OpenResty/Lua를 사용한 Hello World HTTP 예제"
YouTube 비디오 "OpenResty/Nginx 애플리케이션에서 나만의 Lua 모듈 작성"
YouTube 비디오 "OpenResty의 Resty 명령줄 유틸리티 데모"
YouTube 비디오 "OpenResty에서 Lua 코드의 실행 시간을 올바르게 측정"
YouTube 비디오 "OpenResty 시작 속도를 높이기 위해 Lua 모듈을 LuaJIT 바이트코드로 사전 컴파일"
공식 YouTube 채널인 OpenResty를 구독하실 수 있습니다.
목차로 돌아가기
# 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
}
}
목차로 돌아가기
이 모듈은 LuaJIT 2.0/2.1을 Nginx에 포함합니다. OpenResty의 핵심 구성 요소입니다. 이 모듈을 사용하고 있다면 기본적으로 OpenResty를 사용하고 있는 것입니다.
이 모듈의 버전 v0.10.16
부터 표준 Lua 인터프리터("PUC-Rio Lua"라고도 함)는 더 이상 지원되지 않습니다. 이 문서에서는 LuaJIT 인터프리터를 지칭하기 위해 "Lua"와 "LuaJIT"라는 용어를 같은 의미로 사용합니다.
Nginx의 하위 요청을 활용하여 이 모듈을 사용하면 강력한 Lua 스레드(Lua "코루틴"이라고도 함)를 Nginx 이벤트 모델에 통합할 수 있습니다.
Apache의 mod_lua 및 Lighttpd의 mod_magnet과 달리 이 모듈을 사용하여 실행된 Lua 코드는 이 모듈에서 제공하는 Nginx API for Lua가 MySQL, PostgreSQL, Memcached와 같은 업스트림 서비스에 대한 요청을 처리하는 데 사용되는 한 네트워크 트래픽에서 100% 비차단이 될 수 있습니다 . , Redis 또는 업스트림 HTTP 웹 서비스.
최소한 다음 Lua 라이브러리와 Nginx 모듈을 이 모듈과 함께 사용할 수 있습니다.
거의 모든 Nginx 모듈은 ngx.location.capture 또는 ngx.location.capture_multi를 통해 이 ngx_lua 모듈과 함께 사용할 수 있지만 Nginx 업스트림 모듈에 액세스하기 위한 하위 요청을 생성하는 대신 이러한 lua-resty-*
라이브러리를 사용하는 것이 좋습니다. 전자는 일반적으로 훨씬 더 유연하고 메모리 효율적입니다.
Lua 인터프리터("Lua 상태" 또는 "LuaJIT VM 인스턴스"라고도 함)는 메모리 사용을 최소화하기 위해 단일 Nginx 작업자 프로세스의 모든 요청에서 공유됩니다. 요청 컨텍스트는 경량 Lua 코루틴을 사용하여 분리됩니다.
로드된 Lua 모듈은 Nginx 작업자 프로세스 수준에서 유지되므로 로드가 많은 경우에도 Lua의 메모리 공간이 작습니다.
이 모듈은 Nginx의 "http" 하위 시스템에 연결되므로 HTTP 계열(HTTP 0.9/1.0/1.1/2.0, WebSockets 등)의 다운스트림 통신 프로토콜만 말할 수 있습니다. 다운스트림 클라이언트와 일반 TCP 통신을 수행하려면 대신 호환되는 Lua API를 제공하는 ngx_stream_lua 모듈을 사용해야 합니다.
목차로 돌아가기
몇 가지만 언급하자면 다음과 같습니다.
이 모듈을 사용하면 Nginx 내에서 다양한 요소를 통합하고 Lua 언어의 강력한 기능을 사용자에게 노출할 수 있으므로 가능성은 무한합니다. 이 모듈은 LuaJIT 2.x 덕분에 CPU 시간과 메모리 공간 측면에서 네이티브 C 언어 프로그램과 비교할 수 있는 성능 수준을 제공하는 동시에 스크립팅의 완전한 유연성을 제공합니다.
다른 스크립팅 언어 구현은 일반적으로 이 성능 수준을 맞추는 데 어려움을 겪습니다.
목차로 돌아가기
이 모듈의 최신 버전은 다음 버전의 Nginx와 호환됩니다.
1.6.0(독점) 이전의 Nginx 코어는 지원되지 않습니다 .
목차로 돌아가기
Nginx, ngx_lua(이 모듈), LuaJIT는 물론 기타 강력한 동반 Nginx 모듈 및 Lua 라이브러리를 번들로 제공하는 OpenResty 릴리스를 사용하는 것이 좋습니다 .
Nginx로 이 모듈을 직접 빌드하는 것은 정확하게 설정하는 것이 까다롭기 때문에 권장되지 않습니다.
Nginx, LuaJIT 및 OpenSSL 공식 릴리스에는 이 모듈의 일부 기능이 비활성화되거나 제대로 작동하지 않거나 느리게 실행될 수 있는 다양한 제한 사항과 오래된 버그가 있습니다. 공식 OpenResty 릴리스는 OpenResty의 최적화된 LuaJIT 2.1 포크 및 Nginx/OpenSSL 패치를 번들로 제공하므로 권장됩니다.
또는 ngx_lua를 Nginx로 수동으로 컴파일할 수 있습니다.
이 모듈을 사용하여 소스를 빌드하십시오.
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;; " ;
목차로 돌아가기
NGINX 1.9.11부터 위의 ./configure
명령줄에서 --add-module=PATH
대신 --add-dynamic-module=PATH
옵션을 사용하여 이 모듈을 동적 모듈로 컴파일할 수도 있습니다. 그런 다음 load_module 지시문을 통해 nginx.conf
에 모듈을 명시적으로 로드할 수 있습니다. 예를 들면 다음과 같습니다.
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;
목차로 돌아가기
OpenResty 또는 Nginx 코어를 통해 이 모듈을 빌드하는 동안 C 컴파일러 옵션을 통해 다음 C 매크로를 정의할 수 있습니다.
NGX_LUA_USE_ASSERT
정의되면 ngx_lua C 코드 베이스에서 어설션이 활성화됩니다. 빌드 디버깅 또는 테스트에 권장됩니다. 활성화되면 약간의 (작은) 런타임 오버헤드가 발생할 수 있습니다. 이 매크로는 v0.9.10
릴리스에서 처음 도입되었습니다.NGX_LUA_ABORT_AT_PANIC
LuaJIT VM에 패닉이 발생하면 ngx_lua는 기본적으로 현재 nginx 작업자 프로세스를 정상적으로 종료하도록 지시합니다. 이 C 매크로를 지정하면 ngx_lua는 현재 nginx 작업자 프로세스(일반적으로 코어 덤프 파일 생성)를 즉시 중단합니다. 이 옵션은 VM 패닉을 디버깅하는 데 유용합니다. 이 옵션은 v0.9.8
릴리스에서 처음 도입되었습니다. 이러한 매크로 중 하나 이상을 활성화하려면 추가 C 컴파일러 옵션을 Nginx 또는 OpenResty의 ./configure
스크립트에 전달하면 됩니다. 예를 들어,
./configure --with-cc-opt="-DNGX_LUA_USE_ASSERT -DNGX_LUA_ABORT_AT_PANIC"
목차로 돌아가기
목차로 돌아가기
openresty-en 메일링 리스트는 영어 사용자를 위한 것입니다.
목차로 돌아가기
openresty 메일링 리스트는 중국어 사용자를 위한 것입니다.
목차로 돌아가기
이 프로젝트의 코드 저장소는 GitHub의 openresty/lua-nginx-module에서 호스팅됩니다.
목차로 돌아가기
다음으로 버그 보고서, 위시리스트 또는 패치를 제출해 주세요.
목차로 돌아가기
YouTube 비디오 "OpenResty에서 Lua 코드의 실행 시간을 올바르게 측정" 보기
v0.5.0rc32
릴리스부터 모든 *_by_lua_file
구성 지시문(예: content_by_lua_file)은 LuaJIT 2.0/2.1 원시 바이트코드 파일 직접 로드를 지원합니다.
/path/to/luajit/bin/luajit -b /path/to/input_file.lua /path/to/output_file.ljbc
-bg
옵션을 사용하면 LuaJIT 바이트코드 파일에 디버그 정보를 포함할 수 있습니다.
/path/to/luajit/bin/luajit -bg /path/to/input_file.lua /path/to/output_file.ljbc
자세한 내용은 -b
옵션에 대한 공식 LuaJIT 문서를 참조하세요.
https://luajit.org/running.html#opt_b
LuaJIT 2.1에서 생성된 바이트코드 파일은 LuaJIT 2.0과 호환되지 않으며 그 반대의 경우도 마찬가지입니다. LuaJIT 2.1 바이트코드에 대한 지원은 ngx_lua v0.9.3에 처음 추가되었습니다.
LuaJIT 2.0/2.1에 연결된 ngx_lua 인스턴스에 표준 Lua 5.1 바이트코드 파일을 로드하려고 하면(또는 그 반대) 아래와 같은 Nginx 오류 메시지가 표시됩니다.
[error] 13909#0: *1 failed to load Lua inlined code: bad byte-code header in /path/to/test_file.luac
require
및 dofile
과 같은 Lua 기본 요소를 통해 바이트코드 파일을 로드하는 것은 항상 예상대로 작동해야 합니다.
목차로 돌아가기
표준 Lua API os.getenv를 통해 Lua에서 시스템 환경 변수(예: foo
)에 액세스하려면 env 지시어를 통해 nginx.conf
파일에 이 환경 변수 이름을 나열해야 합니다. 예를 들어,
env foo;
목차로 돌아가기
HTTP 1.0 프로토콜은 청크 출력을 지원하지 않으며 HTTP 1.0 연결 유지를 지원하기 위해 응답 본문이 비어 있지 않은 경우 명시적인 Content-Length
헤더가 필요합니다. 따라서 HTTP 1.0 요청이 이루어지고 lua_http10_buffering 지시어가 on
있으면 ngx_lua는 ngx.say 및 ngx.print 호출의 출력을 버퍼링하고 모든 응답 본문 출력이 수신될 때까지 응답 헤더 전송을 연기합니다. 이때 ngx_lua는 본문의 전체 길이를 계산하고 적절한 Content-Length
헤더를 구성하여 HTTP 1.0 클라이언트에 반환할 수 있습니다. 그러나 실행 중인 Lua 코드에 Content-Length
응답 헤더가 설정되어 있으면 lua_http10_buffering 지시문이 on
있어도 이 버퍼링이 비활성화됩니다.
대규모 스트리밍 출력 응답의 경우 lua_http10_buffering 지시문을 비활성화하여 메모리 사용량을 최소화하는 것이 중요합니다.
ab
및 http_load
와 같은 일반적인 HTTP 벤치마크 도구는 기본적으로 HTTP 1.0 요청을 발행합니다. curl
HTTP 1.0 요청을 보내도록 하려면 -0
옵션을 사용하십시오.
목차로 돌아가기
LuaJIT 2.x를 사용하면 순수 Lua 모듈의 바이트코드를 Nginx 실행 파일에 정적으로 연결할 수 있습니다.
luajit
실행 파일을 사용하여 .lua
Lua 모듈 파일을 내보낸 바이트 코드 데이터가 포함된 .o
개체 파일로 컴파일한 다음 Nginx 빌드에서 .o
파일을 직접 연결할 수 있습니다.
아래는 이를 보여주는 간단한 예입니다. foo.lua
라는 이름의 다음 .lua
파일이 있다고 가정해 보세요.
-- foo.lua
local _M = {}
function _M . go ()
print ( " Hello from foo " )
end
return _M
그런 다음 이 .lua
파일을 foo.o
파일로 컴파일합니다.
/path/to/luajit/bin/luajit -bg foo.lua foo.o
여기서 중요한 것은 나중에 Lua 영역에서 이 모듈을 사용하는 방법을 결정하는 .lua
파일의 이름입니다. 파일 이름 foo.o
.o
파일 확장자( luajit
어떤 출력 형식이 사용되는지 알려주는)를 제외하고는 전혀 중요하지 않습니다. 결과 바이트코드에서 Lua 디버그 정보를 제거하려면 -bg
대신 위에서 -b
옵션을 지정하면 됩니다.
그런 다음 Nginx 또는 OpenResty를 빌드할 때 --with-ld-opt="foo.o"
옵션을 ./configure
스크립트에 전달하세요.
./configure --with-ld-opt= " /path/to/foo.o " ...
마지막으로 ngx_lua가 실행하는 Lua 코드에서 다음을 수행할 수 있습니다.
local foo = require " foo "
foo . go ()
그리고 이 코드 조각은 이미 nginx
실행 파일로 컴파일되었기 때문에 더 이상 외부 foo.lua
파일에 의존하지 않습니다.
require
호출할 때 Lua 모듈 이름에 점을 사용하려면 다음과 같이 하세요.
local foo = require " resty.foo "
그런 다음 luajit
명령줄 유틸리티를 사용하여 .o
파일로 컴파일하기 전에 foo.lua
파일의 이름을 resty_foo.lua
로 바꿔야 합니다.
.lua
파일을 .o
파일로 컴파일할 때 nginx + ngx_lua를 빌드할 때와 정확히 동일한 버전의 LuaJIT를 사용하는 것이 중요합니다. 이는 LuaJIT 바이트코드 형식이 서로 다른 LuaJIT 버전 간에 호환되지 않을 수 있기 때문입니다. 바이트코드 형식이 호환되지 않으면 Lua 모듈을 찾을 수 없다는 Lua 런타임 오류가 표시됩니다.
컴파일하고 링크할 .lua
파일이 여러 개 있는 경우 --with-ld-opt
옵션 값에 해당 .o
파일을 동시에 지정하기만 하면 됩니다. 예를 들어,
./configure --with-ld-opt= " /path/to/foo.o /path/to/bar.o " ...
.o
파일이 너무 많으면 단일 명령으로 모든 파일의 이름을 지정하는 것이 불가능할 수 있습니다. 이 경우 다음과 같이 .o
파일에 대한 정적 라이브러리(또는 아카이브)를 구축할 수 있습니다.
ar rcus libmyluafiles.a * .o
그런 다음 myluafiles
아카이브 전체를 nginx 실행 파일에 연결할 수 있습니다.
./configure
--with-ld-opt= " -L/path/to/lib -Wl,--whole-archive -lmyluafiles -Wl,--no-whole-archive "
여기서 /path/to/lib
는 libmyluafiles.a
파일이 포함된 디렉터리의 경로입니다. 여기에서는 링커 옵션 --whole-archive
필요하다는 점에 유의해야 합니다. 그렇지 않으면 nginx 실행 파일의 주요 부분에 언급된 아카이브의 기호가 없기 때문에 아카이브를 건너뛰기 때문입니다.
목차로 돌아가기
동일한 Nginx 작업자 프로세스에서 처리하는 모든 요청 간에 데이터를 전역적으로 공유하려면 공유 데이터를 Lua 모듈로 캡슐화하고 Lua require
내장 기능을 사용하여 모듈을 가져온 다음 Lua에서 공유 데이터를 조작합니다. 이는 필수 Lua 모듈이 한 번만 로드되고 모든 코루틴이 동일한 모듈 복사본(코드와 데이터 모두)을 공유하기 때문에 작동합니다.
전역 Lua 변수의 사용은 동시 요청 간에 예상치 못한 경쟁 조건을 초래할 수 있으므로 사용하지 않는 것이 좋습니다.
다음은 Lua 모듈을 통해 Nginx 작업자 내에서 데이터를 공유하는 간단한 예입니다.
-- mydata.lua
local _M = {}
local data = {
dog = 3 ,
cat = 4 ,
pig = 5 ,
}
function _M . get_age ( name )
return data [ name ]
end
return _M
그런 다음 nginx.conf
에서 액세스합니다.
location /lua {
content_by_lua_block {
local mydata = require "mydata"
ngx.say(mydata.get_age("dog"))
}
}
이 예제의 mydata
모듈은 /lua
위치에 대한 첫 번째 요청에서만 로드 및 실행되며, 동일한 Nginx 작업자 프로세스에 대한 모든 후속 요청은 모듈의 다시 로드된 인스턴스와 동일한 데이터 복사본을 사용합니다. 강제로 다시 로드하기 위해 HUP
신호가 Nginx 마스터 프로세스로 전송될 때까지 계속됩니다. 이 데이터 공유 기술은 이 모듈을 기반으로 하는 고성능 Lua 애플리케이션에 필수적입니다.
이 데이터 공유는 서버 단위가 아닌 작업자 단위로 이루어집니다. 즉, Nginx 마스터 아래에 여러 Nginx 작업자 프로세스가 있는 경우 데이터 공유는 이러한 작업자 간의 프로세스 경계를 넘을 수 없습니다.
일반적으로 이러한 방식으로 읽기 전용 데이터를 공유하는 것이 좋습니다. 계산 중에 비차단 I/O 작업(ngx.sleep 포함)이 없는 한 각 Nginx 작업자 프로세스의 모든 동시 요청 간에 변경 가능한 데이터를 공유할 수도 있습니다. Nginx 이벤트 루프와 ngx_lua의 가벼운 스레드 스케줄러에 제어권을 다시 부여하지 않는 한(암묵적으로라도), 그 사이에는 경쟁 조건이 있을 수 없습니다. 이러한 이유로 작업자 수준에서 변경 가능한 데이터를 공유하려는 경우 항상 주의해야 합니다. 버그가 있는 최적화는 로드 시 디버그하기 어려운 경쟁 조건을 쉽게 초래할 수 있습니다.
서버 전체 데이터 공유가 필요한 경우 다음 접근 방식 중 하나 이상을 사용하십시오.
memcached
, redis
, MySQL
또는 PostgreSQL
과 같은 데이터 저장 메커니즘을 사용합니다. OpenResty 공식 릴리스에는 이러한 데이터 저장 메커니즘과 인터페이스를 제공하는 Nginx 모듈 및 Lua 라이브러리 세트가 함께 제공됩니다.목차로 돌아가기
목차로 돌아가기
tcpsock:connect 메소드는 Connection Refused
오류와 같은 연결 실패에도 불구하고 success
나타낼 수 있습니다.
그러나 나중에 cosocket 객체를 조작하려는 시도는 실패하고 실패한 연결 작업으로 생성된 실제 오류 상태 메시지를 반환합니다.
이 문제는 Nginx 이벤트 모델의 제한으로 인해 발생하며 Mac OS X에만 영향을 미치는 것으로 보입니다.
목차로 돌아가기
dofile
및 require
내장 기능은 현재 LuaJIT 2.0/2.1에서 C 함수로 구현되어 있으므로 dofile
또는 require
에 의해 로드되는 Lua 파일이 ngx.location.capture*, ngx.exec, ngx.exit 또는 양보가 필요한 기타 API 함수를 호출하는 경우 Lua 파일의 최상위 범위에서 Lua 오류 "C 호출 경계를 넘어서는 시도"가 발생합니다. 이를 방지하려면 파일의 최상위 범위 대신 Lua 파일의 자체 Lua 함수에 양보가 필요한 이러한 호출을 넣으세요.목차로 돌아가기
모듈을 가져올 때는 주의해야 하며 다음 형식을 사용해야 합니다.
local xxx = require ( ' xxx ' )
더 이상 사용되지 않는 이전 형식 대신:
require ( ' xxx ' )
그 이유는 다음과 같습니다. 설계상 전역 환경은 이와 관련된 Nginx 요청 처리기와 정확히 동일한 수명을 갖습니다. 각 요청 핸들러에는 자체 Lua 전역 변수 세트가 있으며 이것이 요청 격리의 개념입니다. Lua 모듈은 실제로 첫 번째 Nginx 요청 핸들러에 의해 로드되고 나중에 참조할 수 있도록 package.loaded
테이블에 내장된 require()
에 의해 캐시되며 일부 Lua 모듈에서 사용되는 module()
내장에는 설정의 부작용이 있습니다. 로드된 모듈 테이블에 대한 전역 변수. 그러나 이 전역 변수는 요청 핸들러가 끝나면 지워지며 모든 후속 요청 핸들러는 모두 고유한 (깨끗한) 전역 환경을 갖습니다. 따라서 nil
값에 액세스하면 Lua 예외가 발생합니다.
Lua 전역 변수를 사용하는 것은 일반적으로 다음과 같이 ngx_lua 컨텍스트에서 권장되지 않습니다.
따라서 항상 적절한 로컬 범위 내에서 선언하는 것이 좋습니다 .
-- Avoid
foo = 123
-- Recommended
local foo = 123
-- Avoid
function foo () return 123 end
-- Recommended
local function foo () return 123 end
Lua 코드에서 Lua 전역 변수의 모든 인스턴스를 찾으려면 모든 .lua
소스 파일에서 lua-releng 도구를 실행하세요.
$ 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
출력 결과에 따르면 lib/foo/bar.lua
파일의 1489행은 contains
이라는 전역 변수에 쓰고, 1506행은 전역 변수 setvar
에서 읽고, 1545행은 전역 varexpand
읽습니다.
이 도구는 Lua 모듈 함수의 지역 변수가 모두 local
키워드로 선언되도록 보장합니다. 그렇지 않으면 런타임 예외가 발생합니다. 이러한 변수에 액세스하는 동안 바람직하지 않은 경쟁 조건을 방지합니다. 이에 대한 이유는 Nginx 작업자 내 데이터 공유를 참조하세요.
목차로 돌아가기
ngx.location.capture 및 ngx.location.capture_multi 지시문은 add_before_body, add_after_body, auth_request, echo_location, echo_location_async, echo_subrequest 또는 echo_subrequest_async 지시문을 포함하는 위치를 캡처할 수 없습니다.
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
예상대로 작동하지 않습니다.
목차로 돌아가기
Nginx 코어의 내부 제한으로 인해 cosocket API는 set_by_lua*, log_by_lua*, header_filter_by_lua* 및 body_filter_by_lua 컨텍스트에서 비활성화됩니다.
코소켓은 현재 init_by_lua* 및 init_worker_by_lua* 지시어 컨텍스트에서도 비활성화되어 있지만 Nginx 코어에는 제한이 없기 때문에(또는 제한이 해결될 수 있으므로) 향후 이러한 컨텍스트에 대한 지원을 추가할 수 있습니다.
그러나 원래 컨텍스트가 코소켓 결과를 기다릴 필요가 없는 경우 해결 방법이 있습니다. 즉, ngx.timer.at API를 통해 지연 없는 타이머를 생성하고 cosocket을 수행하면 타이머를 생성하는 원래 컨텍스트에 대해 비동기적으로 실행되는 타이머 핸들러가 생성됩니다.
목차로 돌아가기
참고 v0.9.17
릴리스 이후에는 *_by_lua_block {}
구성 지시문을 사용하여 이 함정을 피할 수 있습니다.
d
, s
또는 w
와 같은 PCRE 시퀀스는 문자열 리터럴에서 백슬래시 문자 가 처리 전에 Lua 언어 파서와 Nginx 구성 파일 파서에 의해 제거되기 때문에 특별한 주의가 필요합니다.
*_by_lua_block {}
지시어. 따라서 다음 스니펫은 예상대로 작동하지 않습니다.
# 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!"
이를 방지하려면 백슬래시를 두 번 이스케이프 처리하세요.
# 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"
여기서 \\d+
Nginx 구성 파일 파서에 의해 \d+
로 제거되고 실행 전에 Lua 언어 파서에 의해 d+
로 추가로 제거됩니다.
또는 정규식 패턴을 "긴 괄호" [[...]]
로 묶어 긴 괄호로 묶인 Lua 문자열 리터럴로 표시할 수 있습니다. 이 경우 백슬래시는 Nginx 구성 파일 파서에 대해 한 번만 이스케이프하면 됩니다.
# 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"
여기서 [[\d+]]
Nginx 구성 파일 파서에 의해 [[d+]]
로 제거되어 올바르게 처리됩니다.
정규식 패턴에 [...]
시퀀스가 포함된 경우 긴 대괄호 [=[...]=]
중 더 긴 괄호가 필요할 수 있습니다. 원하는 경우 [=[...]=]
형식을 기본 형식으로 사용할 수 있습니다.
# 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"
PCRE 시퀀스를 이스케이프하는 또 다른 접근 방식은 Lua 코드가 외부 스크립트 파일에 배치되고 다양한 *_by_lua_file
지시어를 사용하여 실행되도록 하는 것입니다. 이 접근 방식을 사용하면 백슬래시는 Lua 언어 파서에 의해서만 제거되므로 각각 한 번만 이스케이프하면 됩니다.
-- 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"
외부 스크립트 파일 내에서 긴 괄호로 묶인 Lua 문자열 리터럴로 표시되는 PCRE 시퀀스는 수정이 필요하지 않습니다.
-- 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"
앞서 언급했듯이 *_by_lua_block {}
지시문( v0.9.17
릴리스 이후 사용 가능) 내에 제시된 PCRE 시퀀스에는 수정이 필요하지 않습니다.
# 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"
참고 Lua 코드가 매우 긴 경우 by_lua_file
사용하는 것이 좋습니다.
목차로 돌아가기
동일한 Nginx 요청에서 SSI와 ngx_lua를 혼합하는 것은 전혀 지원되지 않습니다. ngx_lua만 사용하세요. SSI로 할 수 있는 모든 작업은 어쨌든 ngx_lua 위에서 수행할 수 있으며 ngx_lua를 사용하면 더 효율적일 수 있습니다.
목차로 돌아가기
ngx_lua에서 제공하는 특정 Lua API(ngx.location.capture, ngx.location.capture_multi 및 ngx.req.socket)는 아직 Nginx의 SPDY 모드에서 작동하지 않습니다.
목차로 돌아가기
Nginx는 (적어도) 다음을 사용하여 요청을 조기에 종료할 수 있습니다.
즉, 다시 쓰기 또는 액세스 단계와 같이 일반적으로 실행되는 단계를 건너뜁니다. 이는 또한 log_by_lua와 같이 상관없이 실행되는 이후 단계가 일반적으로 해당 단계에 설정된 정보에 액세스할 수 없음을 의미합니다.
목차로 돌아가기
bsdrecv
메소드를 추가하기 위한 aviramc의 패치를 검토하고 병합합니다.ngx_hash_t
사용하여 ngx.req.set_header 등에 대한 내장 헤더 조회 프로세스를 최적화합니다.ignore_resp_headers
, ignore_resp_body
및 ignore_resp
옵션을 추가하여 사용자 측에서 미세 성능 조정을 허용합니다.stat
모드를 추가합니다.목차로 돌아가기
이 모듈의 모든 릴리스에서 변경된 사항은 OpenResty 번들의 변경 로그에 나열됩니다.
https://openresty.org/#Changes
목차로 돌아가기
테스트 스위트를 실행하려면 다음 종속성이 필요합니다.
Nginx 버전 >= 1.4.2
펄 모듈:
Nginx 모듈:
예를 들어 필터링 체인의 필터 모듈 위치가 최종 출력을 결정하기 때문에 구성 중에 이러한 모듈이 추가되는 순서가 중요합니다. 올바른 추가 순서는 위에 나와 있습니다.
타사 Lua 라이브러리:
신청: