Apache APISIX Serverless 플러그인을 활용한 Event Hooks
February 15, 2023
Apache APISIX는 Nginx 위에 구축된 오픈 소스 고성능 API 게이트웨이입니다. 그 중 강력한 기능 중 하나는 Apache APISIX의 기능을 확장할 수 있는 작고 상태를 유지하지 않는 프로그램인 서버리스 함수를 생성할 수 있는 능력입니다. 이 글에서는 Apache APISIX 서버리스 플러그인의 기본 사항과 이벤트에 대한 응답으로 서버리스 함수를 트리거하는 방법에 대해 다룰 것입니다.
학습 목표
이 글을 통해 다음을 배우게 됩니다:
- Apache APISIX 서버리스 플러그인이란 무엇인가?
- 서버리스 플러그인이 어떻게 작동하고 사용하는 방법은?
- 서버리스 플러그인의 사용 사례.
- 서버리스 플러그인을 사용하여 웹훅과 통합하는 방법.
Apache APISIX 서버리스 플러그인이란?
Apache APISIX 서버리스 플러그인은 이벤트 훅을 위해 서버리스 함수를 작성하고 이를 API 게이트웨이에 통합할 수 있게 해줍니다. 이 플러그인은 이벤트에 대한 응답으로 사용자 정의 코드를 실행할 수 있는 간단하고 유연한 방법을 제공하며, 기본 인프라를 관리할 필요가 없습니다.
서버리스 플러그인은 이벤트 처리 로직을 별도의 서버리스 함수로 분리하여 API 아키텍처를 단순화하고 관리하기 쉽게 만듭니다. Apache APISIX는 Azure Functions, AWS Lambda와 같은 주요 클라우드 벤더의 서버리스 프레임워크를 지원합니다.
서버리스 플러그인 사용 방법
Apache APISIX 서버리스 플러그인을 사용하려면, 이벤트에 대한 응답으로 실행하려는 로직을 구현한 Lua 프로그래밍 언어로 서버리스 함수 코드를 작성하고, 선택한 요청-응답 주기의 단계에 따라 serverless-pre-function
또는 serverless-post-function
플러그인을 활성화해야 합니다.
현재 APISIX는 Lua만 함수 코드 작성으로 지원합니다. 다른 프로그래밍 언어를 선호한다면, 플러그인 러너를 사용하여 새로운 사용자 정의 플러그인을 처음부터 만들 수 있습니다.
서버리스 플러그인 사용 사례
다음은 Apache APISIX 서버리스 플러그인의 몇 가지 사용 사례입니다:
-
동적 라우팅: 서버리스 플러그인은 요청 메서드, URL 경로 또는 헤더 값과 같은 특정 기준에 따라 들어오는 API 요청을 동적으로 라우팅하는 데 사용할 수 있습니다. 이를 통해 기본 Apache APISIX 구성을 수정하지 않고도 복잡한 라우팅 시나리오를 쉽게 구현할 수 있습니다.
-
인증 및 권한 부여: 서버리스 플러그인을 사용하여 API에 대한 인증 및 권한 부여 검사를 구현할 수 있습니다. 예를 들어, 요청 헤더에 유효한 API 키가 있는지 확인하는 서버리스 함수를 작성하여 요청이 계속되도록 할 수 있습니다. 또는 forward-auth 플러그인과 함께 외부 권한 부여 서비스로 사용할 수 있습니다.
-
요청 변환: 서버리스 플러그인은 백엔드 서비스에서 처리되기 전에 들어오는 API 요청을 변환하는 데 사용할 수 있습니다. 예를 들어, 백엔드 서비스가 예상하는 형식과 일치하도록 요청 헤더나 본문을 수정하는 서버리스 함수를 작성할 수 있습니다.
-
응답 변환: 서버리스 플러그인을 사용하여 백엔드 서비스의 응답을 클라이언트에게 보내기 전에 변환할 수도 있습니다. 예를 들어, 클라이언트가 예상하는 형식과 일치하도록 응답 헤더나 본문을 수정하는 서버리스 함수를 작성할 수 있습니다.
-
로깅 및 모니터링: 서버리스 플러그인을 사용하여 API에 대한 로깅 및 모니터링을 구현할 수 있습니다. 예를 들어, 각 API 요청에 대한 요청 메서드, URL, 헤더 및 본문과 같은 상세 정보를 기록하는 서버리스 함수를 작성하여 나중에 분석할 수 있습니다.
Apache APISIX와 웹훅 통합 (데모)
Apache APISIX를 웹훅과 통합하려면, URL 엔드포인트로 들어오는 POST 요청을 수신하고, 요청 메서드가 POST인지 확인하며, 새 메시지가 게시될 때마다 제3자 서비스에 웹훅 알림을 보내는 서버리스 함수를 생성해야 합니다.
서버리스 함수는 또한 웹훅의 응답을 반환해야 하므로, 웹훅의 상태와 문제가 발생한 경우 오류 메시지를 확인할 수 있습니다. 두 경우 모두 APISIX는 대상 서비스와 통신하여 해당 이벤트에 대한 정보를 제공된 URL로 호출하여 이벤트가 트리거되었음을 알릴 수 있습니다.
사전 요구 사항
프로젝트 설정
먼저 GitHub에서 apisix-docker 프로젝트 저장소를 복제합니다:
git clone https://github.com/apache/apisix-docker.git
프로젝트 폴더를 선호하는 코드 편집기에서 엽니다. 이 튜토리얼은 VS Code를 사용합니다.
Apache APISIX 설치 및 실행
Apache APISIX를 실행하려면 다음 단계를 따릅니다:
새 터미널 창을 열고 프로젝트의 루트 폴더에서 docker compose up
명령을 실행합니다:
docker compose up -d
위 명령은 Docker와 함께 Apache APISIX와 etcd를 실행합니다.
이 데모에서는 Docker를 사용하여 APISIX를 설치했습니다. 그러나 설치 가이드에 따라 다른 방법으로 설치할 수도 있습니다.
Apache APISIX에서 서버리스 함수 구성
Apache APISIX에서 서버리스 함수를 설정하려면, 엔드포인트에 대한 새로운 route를 생성하고 Lua로 작성한 사용자 정의 함수 코드와 함께 서버리스 플러그인을 구성해야 합니다.
다음은 엔드포인트로 들어오는 POST 요청을 수신하고 웹훅 알림을 보내는 Lua로 작성된 서버리스 함수의 예입니다:
function webhook(conf, ctx)
-- 필요한 라이브러리 가져오기
local http = require("resty.http")
local core = require("apisix.core")
-- 요청 메서드가 POST인 경우에만 웹훅 알림을 보내고, 그렇지 않으면 업스트림으로 보냄
if core.request.get_method() == "POST" then
-- 지정된 URL로 웹훅 알림 보내기
local httpc = http.new()
local res, err = httpc:request_uri("http://webhook.site/9db3d3a0-ab64-4142-a39f-d4852ca50f8d", {
method = "POST",
headers = {
["Content-Type"] = "application/json"
},
body = core.request.get_body(),
})
-- 웹훅의 응답 확인
if not res then
core.log.error("Failed to send webhook: ", err)
return 500, err
end
end
-- 업스트림 서비스의 응답 반환
return conf.status, conf.body
end
위의 샘플 웹훅 함수 코드에서 볼 수 있듯이, 클라이언트에서 API 게이트웨이로의 요청 본문을 페이로드로 제공된 URL에 JSON POST 요청을 보냅니다. 테스트 웹훅 웹사이트는 웹훅 엔드포인트를 모의로 사용합니다: https://webhook.site.
웹훅 엔드포인트를 생성하고 설정하려면:
- 웹 브라우저에서 https://webhook.site로 이동하여 URL을 생성합니다.
- Your unique URL 옆에 있는 Copy to clipboard를 선택합니다.
- 함수 코드의 HTTP 요청의 request_uri 메서드에 붙여넣습니다.
또한, POST를 포함한 모든 요청은 업스트림 서비스로 전달됩니다. 다음 단계에서 라우트와 업스트림을 구성합니다.
라우트 및 업스트림 구성
이제 서버리스 함수 플러그인이 활성화된 새로운 라우트와 백엔드 서비스 역할을 하는 업스트림을 생성합니다.
curl -X PUT 'http://127.0.0.1:9180/apisix/admin/routes/1' \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' \
-H 'Content-Type: application/json' \
-d '{
"uri": "/post",
"plugins": {
"serverless-pre-function": {
"phase": "rewrite",
"functions" : ["
return function(conf, ctx)
-- 필요한 라이브러리 가져오기
local http = require(\"resty.http\")
local core = require(\"apisix.core\")
-- 요청 메서드가 POST인 경우에만 웹훅 알림을 보내고, 그렇지 않으면 업스트림으로 보냄
if core.request.get_method() == \"POST\" then
-- 지정된 URL로 웹훅 알림 보내기
local httpc = http.new()
local res, err = httpc:request_uri(\"http://webhook.site/9db3d3a0-ab64-4142-a39f-d4852ca50f8d\", {
method = \"POST\",
headers = {
[\"Content-Type\"] = \"application/json\"
},
body = core.request.get_body(),
})
-- 웹훅의 응답 확인
if not res then
core.log.error(\"Failed to send webhook: \", err)
return 500, err
end
end
-- 업스트림 서비스의 응답 반환
return conf.status, conf.body
end"]
}
},
"upstream": {
"nodes": {
"httpbin.org:80": 1
},
"type": "roundrobin"
}
}'
앞의 라우트 구성 예제에서, APISIX Admin API에 curl
요청을 보내 첫 번째 라우트를 생성했습니다. 라우트 요청 본문에서, /post
경로로의 모든 요청이 서버리스 함수 코드를 트리거하고 나중에 대상 httpbin.org
로 전달될 것임을 지정했습니다. 이는 요청 메서드가 POST인지 확인하고 이벤트를 제3자 서비스 웹훅 엔드포인트로 보내야 하는지 여부를 확인한 후 요청이 httpbin.org/post
엔드포인트로 라우팅됨을 의미합니다. 백엔드 서비스는 사용자의 백엔드 서비스로 대체할 수 있습니다.
또한 Json 객체의 serverless-pre-function
의 functions
속성에 함수 코드를 추가한 것을 알 수 있습니다.
구성 테스트
마지막으로, /post
API 게이트웨이 엔드포인트를 호출하여 모든 것이 예상대로 작동하는지 테스트하고, POST 이벤트가 웹훅 웹사이트로 전송되는지 확인합니다.
curl -i http://127.0.0.1:9080/post -X POST -d \
'{
"message": "A new webhook message"
}'
이후, 이전 단계에서 생성한 웹훅 URL로 이동하면, 이벤트에 대한 웹훅 엔드포인트에 POST 요청이 전송되고 요청 본문이 전송된 것을 볼 수 있습니다.
또한, 모의 업스트림 서비스 httpbin.org
로부터 응답을 받습니다:
HTTP/1.1 200 OK
Content-Type: application/json
{
...
"form": {
"{\n \"message\": \"A new webhook message\"\n}": ""
},
"headers": {
"Accept": "*/*",
"Content-Length": "41",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "127.0.0.1",
"X-Forwarded-Host": "127.0.0.1"
},
"json": null,
"url": "http://127.0.0.1/post"
}
분명히, POST 이외의 다른 HTTP 요청 메서드를 보내면 서버리스 함수 코드가 웹훅 엔드포인트를 트리거하지 않습니다.
이는 Apache APISIX에서 서버리스 함수를 설정하는 기본 예제입니다. 웹훅에 대한 응답으로 다른 함수를 트리거하는 등 더 복잡한 로직을 추가하여 이 기능을 확장할 수 있습니다.
결론
Apache APISIX 서버리스 플러그인은 API 요청 처리 중 발생하는 이벤트에 대한 응답으로 서버리스 함수를 트리거할 수 있는 유연하고 확장 가능한 방법을 제공합니다. 이 플러그인을 사용하면 API 아키텍처를 단순화하고, 서비스의 성능과 신뢰성을 향상시키며, 애플리케이션 인프라 관리 비용을 줄일 수 있습니다.