20201122

nginx 1.18 + OpenResty 사용기

nginx 1.18에 OpenResty 얹어서 인증/리밋 로직을 Lua로 처리하는 게이트웨이 만들어봄. 전에는 express + 미들웨어로 했는데, 단순 체크만 하는 거면 openresty 쪽이 훨씬 빠르고 리소스도 덜 먹는다.

토큰 검증(JWT 간단 버전) 예제.

location /api/ {
    access_by_lua_block {
        local jwt = require "resty.jwt"
        local auth = ngx.var.http_authorization
        if not auth then
            ngx.exit(401)
        end
        local token = string.gsub(auth, "Bearer ", "")
        local verified = jwt:verify("mysecret", token)
        if not verified.verified then
            ngx.status = 401
            ngx.say(verified.reason)
            ngx.exit(401)
        end
        ngx.req.set_header("X-User-Id", verified.payload.sub)
    }
    proxy_pass http://backend;
}

레이트 리밋은 resty.limit.req + shared dict.

http {
    lua_shared_dict req_limit 10m;
}

location /api/ {
    access_by_lua_block {
        local limit = require("resty.limit.req").new("req_limit", 200, 100)
        local delay, err = limit:incoming(ngx.var.binary_remote_addr, true)
        if not delay then
            if err == "rejected" then
                ngx.exit(429)
            end
        end
    }
}

체감 성능. wrk -t4 -c200 기준, 같은 토큰 검증 로직을 node 미들웨어로 할 때 대비 openresty가 약 3.2배 throughput. 근데 복잡한 로직 lua로 짜는 게 유지보수적으로 힘들어서 "라우팅 + 인증 + 레이트리밋" 수준에서만 쓰는 게 답이라고 본다.

lua_shared_dict 크기 잘 잡아야 함. 넘치면 eviction 돌고 결국 정확도 떨어진다. 주요 도메인당 10~20m 추천.

댓글 없음: