Lua 규칙과 NGINX 설정 간에 충돌이 발생하면 어떻게 될까요?

API7.ai

October 13, 2022

OpenResty (NGINX + Lua)

1. OpenResty의 이름과 언어

Q: 지금까지 OpenResty라는 이름의 유래를 이해하지 못했습니다. 또한 OpenResty는 Lua 언어를 통해 성장했는데, 왜 다른 스크립트 언어를 사용하지 않았나요? 예를 들어, Shell 등이 있습니다.

A: OpenResty는 Yahoo!의 기업 프로젝트로 시작되었으며, 2007년 10월에 시작되었습니다. "Open"이라는 이름은 OpenAPI에서 따왔고, "Resty"는 rest API에서 따왔습니다. 처음에 OpenResty는 웹 서버와 개발 플랫폼이 아니라 웹사이트와 같은 애플리케이션으로 의도되었습니다.

OpenResty가 10년 전에 오픈소스로 공개되었을 때, 동기식 논블로킹을 지원하는 언어는 매우 적었습니다. 지금도 OpenResty와 같은 수준의 성능을 달성할 수 있는 백엔드 언어는 많지 않습니다. 현재는 더 많은 개발자들이 API 게이트웨이와 소프트 WAF에서 OpenResty를 사용하고 있으며, 이는 개발자들에게 자연스러운 선택입니다.

언어에 대해 말하자면, OpenResty는 NGINX에 다른 개발 언어를 내장하는 유일한 프로젝트가 아닙니다. 예를 들어, NGINX는 공식적으로 JS를 내장하고 있으며, PHP를 NGINX에 내장하는 오픈소스 프로젝트도 있습니다.

일반적으로 언어 선택은 동시성, JIT, 언어의 인기 등과 같은 요소를 기반으로 합니다. OpenResty의 경우, 2007년 당시 Lua가 실제로 최선의 선택이었습니다. OpenResty는 초기 버전에서 Lua 대신 perl을 선택하며 우회한 적이 있습니다.

2. 설정의 규칙 우선순위

Q: OpenResty의 Lua 규칙과 NGINX 설정 파일이 충돌할 때, 예를 들어 NGINX가 rewrite 규칙을 설정하고 동시에 rewrite_by_lua_file을 참조하는 경우, 이 두 규칙의 우선순위는 어떻게 되나요?

A: 실제로는 NGINX 설정 rewrite 규칙이 어떻게 작성되었는지에 따라 달라집니다. break인지 last인지에 따라 다르며, 이는 OpenResty 공식 문서에 명시되어 있으며, 샘플 코드가 있습니다:

 location /foo {
     rewrite ^ /bar;
     rewrite_by_lua 'ngx.exit(503)';
 }
 location /bar {
     ...
 }

이 샘플 코드의 설정에서 ngx.exit(503)은 실행되지 않습니다.

그러나 다음과 같이 작성하면 ngx.exit(503)이 실행됩니다.

rewrite ^ /bar break.

그러나 저는 NGINX 설정 대신 OpenResty를 사용하여 rewrite를 하는 것을 권장합니다. 이러한 모호함을 피하기 위해, 많은 NGINX 설정은 상대적으로 난해하며 문서를 반복해서 참조해야 이해할 수 있습니다.

3. 내 코드가 왜 오류를 발생시키나요?

Q: LuaJIT 확장의 테이블 함수에서, 왜 다음 두 줄의 코드가 LuaJIT로 실행될 때 "moudule not found" 오류를 발생시키나요? 저는 LuaJIT 버전 2.0.5를 사용하고 있습니다.

local new_tab = require('table.new')
# or
require('table.clear')

# 실행 시 오류 발생
luajit: table_luajit.lua:1: module 'table.new' not found:

A: 이 두 줄의 코드는 LuaJIT 버전 2.1에서 실행되어야 합니다. 여기에 문서화되어 있습니다: https://github.com/LuaJIT/LuaJIT/blob/v2.1/doc/extensions.html#L218, 여기서 확인할 수 있습니다.

우리가 언급한 대로, OpenResty를 사용할 때는 특정 버전의 LuaJIT가 필요하므로 특히 주의해야 합니다. OpenResty는 LuaJIT 2.1 브랜치를 기반으로 하며, LuaJIT에 대한 많은 확장을 추가했습니다.

따라서 이 칼럼의 코드를 실행할 때는 공식 OpenResty 설치를 사용하십시오. NGINX 위에 lua-nginx-module을 추가하여 컴파일하면 여전히 많은 문제에 직면할 수 있습니다!

4. null 값에 대한 혼란

Q: 제가 마주한 혼란스러운 것들 중 하나는 ngx.null, nil, null, ""입니다. 웹을 검색해보니 누군가 nullngx.null의 정의라고 말했습니다. Redis가 반환할 때 종종 반환된 결과가 null인지 여부를 판단하는데, 이때 어떤 값과 비교하나요? 이러한 값들의 사용에 대한 다른 함정이 있나요? 저는 이러한 값들을 명확히 이해하지 못합니다.

A: 제가 질문에 답하기 전에, lua-resty-redis에서 키를 찾기 위해 다음 코드를 사용할 것을 권장합니다.

local res, err = red:get("dog")

이는 Lua의 nil이 테이블의 값으로 사용될 수 없기 때문에, OpenResty는 테이블에서 null 값으로 ngx.null을 도입했습니다.

다음 코드로 ngx.null과 그 타입을 출력할 수 있습니다.

# ngx.null 출력
$ resty -e 'print(ngx.null)'
null
# 타입 출력
$ resty -e 'print(type(ngx.null))'
userdata

보시다시피, ngx.nullnil이 아니며, userdata 타입입니다.

더 나아가, OpenResty에는 cjson.null, cdata:NULL 등과 같은 많은 null 값이 있으며, 이에 대해서는 나중에 논의하겠습니다.

OpenResty에서 유일한 거짓 값은 nilfalse입니다. 따라서 if not res then과 같은 코드를 작성할 때는 주의해야 하며, 명시적으로 if res ~= nil and res ~= false then과 같이 변경하는 것이 좋습니다. 그리고 이에 대한 테스트 케이스 커버리지도 함께 작성해야 합니다.

5. API 게이트웨이는 정확히 무엇인가요?

Q: 글에서 언급된 API 게이트웨이는 무엇인가요? 그리고 NGINX, Tomcat, Apache 등의 웹 서버와는 어떻게 다른가요?

A: API 게이트웨이는 서비스를 통합 관리하기 위한 게이트웨이입니다. 예를 들어, 결제, 사용자 로그인 등은 모두 API 형태로 제공되는 서비스이며, 이들 모두는 통합 보안 및 인증을 수행할 게이트웨이가 필요합니다.

API 게이트웨이는 전통적인 NGINX, Apache를 대체하여 남북 트래픽을 처리할 수 있을 뿐만 아니라, 마이크로서비스 환경에서 동서 트래픽을 처리할 수 있으며, 비즈니스에 더 가까운 미들웨어입니다. 단순한 웹 서버가 아닙니다.

API 게이트웨이에 대한 소개와 구현에 대한 더 많은 정보는 Apache APISIX를 참조하십시오; Apache APISIX는 OpenResty를 기반으로 구현되었습니다.