Nginx Lua Module, Shared Memory set 할 때, 순서 바뀌는 문제

Nginx Lua Module을 개발할 때 Shared Memory를 사용했었다. 다음과 같은 함수로 Shared Memory를 다룰 수 있다.

  • ngx.shared.DICT:get
  • ngx.shared.DICT:set
  • ngx.shared.DICT:add

그런데 한 가지 문제가 생겼다. 예를들어 :

이런 결과가 나타나길 기대했지만,

실제로 이런 결과가 나타났다.

순서는 그대로 두고, Shared Memory의 값이나 expires를 변경하고 싶었는데, 그렇게 되지 않았다.

replace라는 메소드가 있어서 확인해봤다.

set과 비슷하지만, 키가 존재할 때 ngx.shared.DICT 딕셔너리에 key-value 쌍을 보관한다. 이미 만료되었거나 딕셔너리에 키가 존재하지 않으면 success 리턴 값은 false가 되고, err 리턴 값은 “not found”가 된다고 했다. 따라서 replace는 해결 방법은 아니다.

모든 메소드를 확인해봤는데, 결국 해결방법을 찾을 수 없었다. 그래서 구조를 다음과 같이 바꿨다.

  • DICT : 만료시간도 주고, 값을 set 할 수 있는 공유 메모리
  • DICT_IDX : add만 하는 공유 메모리. 오직 delete만 할 수 있다.

이렇게 DICT_IDX라고, 새로운 공유 메모리를 추가하는 방식으로 해결했다.

Nginx Lua Module 개발 노트

Nginx Lua Module을 개발하면서 필요한 내용을 정리했다.

기본

nil(Null) 체크

Lua nil은 값이 없다는 것을 의미한다.

타입 변환

타입 구하기

공유 메모리의 키를 가져오는데, 어떤 형태인지 알아보려고 사용했었다.

 

For Loop

공유메모리의 키를 모두 가져와서 For Loop를 돌릴 수 있다.

 

문자열

날짜/시간

Table

Logging

nginx 로그파일에 로그를 단계별로 기록할 수 있다.

 

모듈화

모듈화를 위해서 다음과 같은 형태로 파일을 만들어서 사용할 수 있다.

 

이렇게 작성한 모듈은 다음과 같이 사용할 수 있다.

 

스크립트 경로 가져오기

script_path()를 호출하는 파일의 경로를 구할 수 있다. 해당 파일을 기준으로 다른 파일 경로를 가져올 때 유용하다.

 

동적으로 모듈 호출

Nginx Lua Module 전용

ngx_http_lua_module

Nginx에 Lua 코드를 끼워넣어 사용할 수 있는 모듈로 기본적으로 nginx에서 제공되지 않고, 직접 설치해야 한다.

공식사이트

출력

원하는 단계에 넣으면 중간에 다른 결과를 출력할 수 있다.

 

버전 정보

http 요청

ngx.location.capture는 nginx 워커에서 특정 uri에 추가 요청을 할 수 있다.

 

redirect

특정 페이지로 리다이렉트할 수 있다.

exec는 redirect와 다르게, 내부 리다이렉트를 하고, 새로운 외부 HTTP트래픽과 관련이 없다.

Header 관련

nginx에서 설정한 변수 사용하기

nginx.conf:

 

주소가 설정한 값과 일치하면 그 값을 lua에서 다음과 같이 사용할 수 있다.

 

3rd party module

LIP – ini Parser

LIP는 Lua INI Parser다. ini 파일을 불러오고, 저장할 수 있다.

 

CJSON

CJSON은 LUA에서 JSON을 지원하는 모듈이다.

설치하기

다음 페이지 다른 JSON 모듈을 비교한다.

JSON 모듈 비교

에러

a temporary file while reading upstream

lua에서 다음 에러가 발생한다.

문제 생기는 부분을 확인하니 다음과 같이 이미지를 base64로 출력하는 부분의 사이즈가 설정한 값보다 커서 생긴 문제였다. 이미지 사이즈에 맞게 프록시 버퍼의 크기를 늘려줬다.

nginx 설정을 변경했다.

 

예제 프로그램이라서 base64로 이미지를 출력했지만, 버퍼를 늘리는 것보다 이미지는 static 서버를 통해 제공하는 것이 좋다.