Cloudflare 작업자 및 서버리스 Redis를 사용한 에지에서의 속도 제한

이 자습서에서는 Cloudflare Workers 및 Upstash Redis를 사용하여 애플리케이션의 속도를 제한하는 방법을 보여줍니다. Upstash Redis에 데이터를 보관하는 rate limiting SDK을 사용하겠습니다.

레디스 설정



Upstash Console 또는 Upstash CLI 을 사용하여 하나 이상의 Redis 데이터베이스를 만듭니다. 전역을 선택하지 말고 대신 사이트 트래픽이 예상되는 여러 지역에 여러 데이터베이스를 만드십시오. (이유? 나중에 설명하겠습니다.) 다음 단계에서 REST URL과 TOKEN이 필요합니다.

프로젝트 설정



배포에 Wrangler 2를 사용할 것이므로 Wrangler 2을 설치(또는 업그레이드)합니다.

프로젝트용 폴더를 만들고 실행합니다wrangler init. 선택ts:

 ⛅️ wrangler 2.0.7 (update available 2.0.26)
------------------------------------------------------
Using npm as package manager.
✨ Created wrangler.toml
No package.json found. Would you like to create one? (y/n)
✨ Created package.json
Would you like to use TypeScript? (y/n)
✨ Created tsconfig.json
Would you like to create a Worker at src/index.ts? (y/n)
✨ Created src/index.ts


코드



작업자 기능을 아래와 같이 업데이트합니다.

import { Redis } from "@upstash/redis/cloudflare";
import { MultiRegionRatelimit } from "@upstash/ratelimit";

export interface Env {
}

const cache = new Map();

export default {
  async fetch(
    request: Request,
    env: Env,
    _ctx: ExecutionContext,
  ): Promise<Response> {
    if (new URL(request.url).pathname == "/favicon.ico") {
      return new Response(null, { status: 400 });
    }

    const ratelimit = new MultiRegionRatelimit({
      redis: [
        new Redis({
          url: "https://us1-cool-macaque-32148.upstash.io",
          token: "AASQgODM5ZjExZGEtMZDRjOWI4ZmVjNmE3ZDk3NDIxMmEwNmNkYjVmOGVmZTk5Mz",
        }),
        new Redis({
          url: "https://eu2-merry-caribou-31549.upstash.io",
          token: "AXe5ASQgNmM5YmFiYWEtMmV3N2E1ODFiMWExMDc5NNGFiYWEwMzk2ZjE4ZWQ3N2Y",
        })
      ],
      limiter: MultiRegionRatelimit.fixedWindow(5, "5 s"),
      ephermeralCache: cache,
    });

    const userIP: string = request.headers.get('CF-Connecting-IP') || "none";

    const data = await ratelimit.limit(userIP);
    if (data.success) {
      // if you use CF Workers to intercept another site, uncomment below
      // return await fetch(request);
      return new Response(JSON.stringify({ message: "Success, you are not rate limited.", ip: userIP, data }, null, 2), { status: 200 });
    } else {
      // show an error page for rate limited users
      return new Response(JSON.stringify({ message: "You are rate limited, try again later.", ip: userIP,  data }, null, 2), { status: 200 });
    }
  },
};


위의 Redis 인스턴스에 대한 REST_URL 및 TOKEN을 교체하십시오. 트래픽에 따라 다른 지역에 더 많은 Redis 데이터베이스를 추가하거나 단일 지역을 설정할 수 있습니다.

테스트 및 배포


wrangler dev를 사용하여 로컬에서 기능을 테스트할 수 있습니다.

Cloudflare에 함수 배포wrangler publish
함수의 끝점이 인쇄됩니다. 예를 들어 https://cloudflare-workers-rate-limiting.upsdev.workers.dev/ 페이지를 연속으로 5번 새로 고치면 속도 제한이 표시되어야 합니다.

자, 튜토리얼이 끝났습니다(쉬웠죠?) 이제 몇 가지 세부 사항을 살펴보겠습니다.

각 요청에 대해 원격 호출을 수행하는 데 비용이 많이 들지 않습니까?



임시 캐시를 사용하지 않은 경우일 수 있습니다. The ephemeral cache은 핸들러 외부에서 정의된 지도 객체입니다. 속도 제한 SDK는 이를 사용하여 서버리스 기능이 활성(핫)인 동안 식별자를 캐시합니다. 핸들러 외부에서 정의하는 것이 중요하므로 전역 변수가 됩니다. Cloudflare Workers는 서로 다른 호출이 동일한 변수를 사용한다고 보장하지 않지만 최대 트래픽 중에 이를 캐시하는 데 많은 도움이 됩니다.

글로벌 데이터베이스가 아닌 이유는 무엇입니까?



Upstash Global 데이터베이스는 Redis 데이터를 여러 지역에 복제합니다. 많은 엣지 사용 사례에 완벽하게 적합합니다. 그러나 속도 제한의 경우 한 지역의 데이터를 다른 모든 지역으로 복제할 필요가 없습니다. 속도 제한 세션에는 로컬 범위가 있습니다. 우리는 여전히 글로벌 데이터베이스를 사용할 수 있지만 각 업데이트가 전 세계에 복제되므로 불필요하게 비용이 많이 듭니다. 이것이 우리가 the rate-limiting SDK recommends 으로 여러 지역 데이터베이스를 만들기로 선택한 이유입니다.

IP를 식별자로



속도 제한 기능의 식별자로 사용자의 IP를 사용했습니다. 이것은 우리가 단일 사용자에 대한 요금을 제한한다는 것을 의미합니다. 요청에 더 나은 식별자(사용자 이름, 이메일 등)가 있는 경우 이를 사용하십시오. 총 트래픽을 제한하려면 상수 문자열을 설정할 수 있습니다. 또는 지역 또는 국가( request.cf.country )를 식별자로 사용하여 지역별 트래픽을 제한할 수 있습니다.

자체 호스팅 Redis를 사용할 수 있습니까?



Cloudflare Workers는 V8 격리에서 실행되며 TCP 연결을 허용하지 않습니다. 따라서 REST 프록시를 사용하지 않는 한 자체 호스팅된 Redis, Redislabs 또는 Elasticache에 액세스할 수 없습니다. Upstash Redis에는 REST API가 내장되어 있습니다.

기존 웹사이트에 통합



코드를 건드리지 않고 기존 웹 애플리케이션/사이트의 속도를 제한할 수 있습니다. Cloudflare에 사이트를 만들고 이에 따라 도메인의 이름 서버를 설정하기만 하면 됩니다. 따라서 Cloudflare는 웹사이트에 대한 요청을 가로채 작업자 기능을 실행할 수 있습니다. 또한 요청이 속도 제한이 없는 경우 Workers 기능이 요청을 웹 사이트로 전달할 수 있도록 XX 행의 주석 처리를 제거하십시오.

좋은 웹페이지 즐겨찾기