Programming

Lua로 APISIX 흐름 가로채기 구현 팁

ipxy 2025. 4. 12. 13:04
728x90

 

✅ Lua로 APISIX 흐름 가로채기 구현  팁

항목 설명 예시
1. 요청 바디 읽기 ngx.req.get_body_data() 사용 local body = ngx.req.get_body_data()
2. 비동기 작업 처리 ngx.timer.at(0, function) 사용 (non-blocking) ngx.timer.at(0, send_to_kafka, body)
3. 외부 HTTP 호출 resty.http 모듈 사용 local http = require("resty.http")
4. HTTP POST 호출 httpc:request_uri 로 외부 서버 호출 httpc:request_uri("http://server", {method="POST", body=...})
5. JSON 직렬화 (Encoding) Lua 테이블을 JSON 문자열로 변환해야 함 cjson.encode({key="value"})
6. JSON 역직렬화 (Decoding) JSON 문자열을 Lua 테이블로 변환 가능 cjson.decode(json_str)
7. 에러 핸들링 HTTP 호출 실패 대비 필요 if not res then ngx.log(ngx.ERR, err)
8. phase 흐름 주의 access phase에서 처리하는 게 일반적 (serverless-pre-function 사용 시 기본 적용)

✨ 세부 설명 

1. 요청 바디 읽기

ngx.req.read_body()
local body = ngx.req.get_body_data()
  • read_body()로 먼저 읽어야 합니다.
  • 그 다음 get_body_data()로 바디 내용을 가져옵니다.

2. 비동기 처리 (non-blocking)

ngx.timer.at(0, function()
    -- 비동기 처리 코드
end)
  • 0초 후 (즉시) 별도 스레드처럼 비동기로 실행.
  • APISIX 전체 요청 흐름을 지연시키지 않음.

3. 외부 HTTP 요청 (resty.http)

local http = require("resty.http")
local httpc = http.new()

local res, err = httpc:request_uri("http://target-server", {
    method = "POST",
    body = "payload",
    headers = {
        ["Content-Type"] = "application/json",
    }
})
  • Lua 안에서 HTTP POST 요청을 날릴 수 있습니다.

4. JSON 변환 (cjson 모듈)

Lua Table → JSON 문자열 (encode)

local cjson = require("cjson")
local data = {
    action = "create",
    id = 123,
    name = "John Doe"
}
local json_str = cjson.encode(data)

JSON 문자열 → Lua Table (decode)

local decoded = cjson.decode('{"action":"create","id":123,"name":"John Doe"}')
  • Lua는 기본적으로 JSON 타입을 지원하지 않기 때문에
  • cjson 모듈을 써야 합니다.
  • openresty (APISIX 기본)에는 cjson이 기본 내장되어 있습니다.

5. 에러 핸들링 (optional)

if not res then
    ngx.log(ngx.ERR, "Failed to request: ", err)
end
  • 외부 호출이 실패해도 로그만 남기고, 전체 서비스에는 영향 안 줘야 합니다.

📄 전체 Lua 예시 코드 (종합본)

local cjson = require("cjson")
local http = require("resty.http")

local function send_to_kafka(body)
    local httpc = http.new()
    httpc:request_uri("http://kafka-producer-proxy/send", {
        method = "POST",
        body = body,
        headers = {
            ["Content-Type"] = "application/json",
        }
    })
end

local function send_to_external_api(body)
    local httpc = http.new()
    httpc:request_uri("http://external-api-server/notify", {
        method = "POST",
        body = body,
        headers = {
            ["Content-Type"] = "application/json",
        }
    })
end

return function()
    ngx.req.read_body()
    local body_data = ngx.req.get_body_data()

    -- 필요한 경우 JSON 변환
    local body_json = cjson.encode({
        timestamp = ngx.time(),
        payload = cjson.decode(body_data)
    })

    -- 비동기 전송
    ngx.timer.at(0, function() send_to_kafka(body_json) end)
    ngx.timer.at(0, function() send_to_external_api(body_json) end)

    -- 원래 요청은 Backend로 정상 흐름 유지
end

🚀 실무 팁 

설명
ngx.timer.at 안 쓰고 바로 HTTP 요청하면 전체 요청 흐름이 느려질 수 있음 (timeout 발생)
cjson.encode/decode 오류 발생 시 입력 JSON 데이터 구조 다시 확인해야 함
HTTP timeout 설정 httpc:set_timeout(3000) 식으로 3초 설정 추천
Lua 에러 나면 APISIX 로그 (/usr/local/apisix/logs/error.log)에서 확인 가능

 

728x90