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