데보션앱 소개페이지 바로가기
로그인 선택

신고하기

CLOSE
신고사유 (대표 사유 1개)
상세내용 (선택)
0/200
  • 신고한 게시글은 더 이상 보이지 않습니다.
  • 이용약관과 운영정책에 따라 신고사유에 해당하는지 검토 후 조치됩니다.
  • 허위 신고인 경우, 신고자의 서비스 이용이 제한될 수 있으니 유의하시어 신중하게 신고해 주세요.
(이 회원이 작성한 모든 댓글과 커뮤니티 게시물이 보이지 않고, 알림도 오지 않습니다.)

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

      카테고리를 선택해주세요.

      DEVOTEE를 활성화 시키면
      지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.

      버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.

      임시저장함에 저장되었습니다. 저장일시 : 2022.5.17 14:29:08

      임시저장함

      제목을 선택하시면 이어서 작성이 가능하며,
      최대 20건까지 저장합니다.
      컨텐츠 유형, 제목, 저장일시, 삭제로 이뤄진 임시저장 목록
      컨텐츠 유형 제목 저장일 삭제

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

      효율적인 데보션 서비스 이용 및
      고객님의 소중한 개인정보보호를 위해
      본인인증을 진행해주세요. 본인인증 미 진행 시 로그인이 제한됩니다.
      본인인증 실패

      본인인증 로그인에 실패하였습니다.
      회원이 아니시거나 본인인증 등록이
      완료되지 않은 사용자입니다.

      회원정보 연결

      파이썬 Async API Call 에 Rate Limit 적용하기

      mihosang 24.06.12
      3,443 6 0
      DEVOTEE 요약
      본 블로그는 파이썬에서 비동기 API 호출 시 Rate Limit을 적용하는 방법을 다룹니다. 주요 내용은 httpx, aiolimiter, aiometer 라이브러리를 활용해 동시성과 초당 요청 수를 제어하여 서버 부하를 줄이는 방법을 설명합니다. 이를 통해 API 호출에 효율성을 높이고 서버 용량을 고려할 수 있습니다.
      DEVOTEE 추천 블로그

      Rate Limit 이란?

      Rate Limit이란 API를 사용할 때 일정 시간 동안에 호출할 수 있는 횟수를 제한하는 것을 말합니다.

      외부 API를 호출할때 Rate Limit을 감안하지 않고 대량의 Request를 보낼 경우 서버에 부하가 걸리거나,

      API 제공자에게 무리한 요청을 보내서 200 OK 가 아닌 에러 Status code를 받을 가능성도 있습니다.

      예외처리로 해결하는 방법도 있겠지만 실패한 요청에 대해서 반복하여 발송하거나 혹시나 DDoS로 오해받아서 계정이나 api key가 block 되는 불상사도 발생할 수 있겠죠.


      파이썬 Async API Call

      파이썬에서 API Call을 하는 가장 간단한 방법은 예제와 튜토리얼에서 많이 등장하는 동기식 requests 라이브러리를 사용하는 방법입니다.

      동기식 API Call의 경우 간단하고 코드를 알아보기 쉽다는 장점이 있지만, API Call을 기다리는 동안 다른 작업을 수행하지 못하고 대기해야 하기 때문에 비효율적입니다.

      최근에는 비동기 프로그래밍이 강조되면서 비동기로 API Call을 하는 aiohttp, httpx 등이 있습니다.

      비동기로 API Call을 하는 경우, API Call을 기다리는 동안 다른 작업을 수행할 수 있기 때문에 효율적입니다.

      하지만, 비동기로 API Call을 하는 경우 Rate Limit을 적용하기가 어렵습니다.

      Rate Limit을 적용하기 위한 방법

      Rate Limit을 적용하기 위한 방법은 여러가지가 있겠지만, 가장 간단한 방법은 Rate Limit을 적용할 API Call을 호출하기 전에 Rate Limit을 확인하고,

      Rate Limit을 초과하지 않는다면 API Call을 수행하고, Rate Limit을 초과한다면 API Call을 대기하는 것입니다.

      이 글에서는 httpx를 이용한 간단한 http client를 만들고 여기에 rate limit을 적용해보는 방법을 알아보겠습니다.

      httpx를 이용한 간단한 http client 만들기

      먼저 필요한 패키지를 설치합니다

      pip install httpx aiolimiter aiometer

      간단한 클라이언트 함수를 작성해보겠습니다.

      cf) httpx는 max_connections 옵션을 통해 동시에 열 수 있는 connection의 수를 제한할 수 있습니다.

      하지만 각 connection 으로 호출하는 API의 응답시간이 각기 다르므로 정교한 Rate Control이 어렵습니다.

      import httpx
      async def fetch(url, limiter):
          async with limiter:
              async with httpx.AsyncClient() as client:
                  response = await client.get(url)
                  return response

      aiolimiter 를 이용한 방법

      aiolimiter는 asyncio를 이용한 Rate Limit을 적용하기 위한 라이브러리입니다.

      aiolimiter를 이용하면 간단하게 Rate Limit을 적용할 수 있습니다. 전체 코드는 다음과 같습니다.

      import asyncio
      import time
      
      import httpx
      from aiolimiter import AsyncLimiter
      
      NUM_OF_TOTAL_URLS = 10
      RATE_LIMIT = 10
      
      
      async def fetch(url, limiter):
          async with limiter:
              async with httpx.AsyncClient() as client:
                  response = await client.get(url)
                  return response
      
      
      async def main(urls, rate_limit=10):
          # Create an AsyncLimiter instance
          limiter = AsyncLimiter(rate_limit, time_period=1)
      
          # Create a list of tasks
          tasks = [fetch(url, limiter) for url in urls]
      
          # Run the tasks concurrently
          results = await asyncio.gather(*tasks)
      
          # Process the results
          for result in results:
              print(result.status_code)
      
      
      # List of URLs to fetch
      urls = ["https://httpbin.org/get"] * NUM_OF_TOTAL_URLS
      # Run the main function
      start_time = time.time()
      asyncio.run(main(urls, RATE_LIMIT))
      end_time = time.time()
      print(f"Total time: {end_time - start_time} seconds")
      
      # Run the main function
      asyncio.run(main(urls))

      전체 URL을 10개, limit을 10개로 적용했을 때 소요 시간은 다음과 같습니다.(실행 환경에 따라 차이는 있습니다)

      Total time: 1.4457590579986572 seconds

      여기서 limit만 2로 변경하면 어떻게 될까요?

      Total time: 4.87471604347229 seconds

      전체적인 호출 개수는 10개로 동일하지만 limit마다 끊어서 호출하기 때문에 소요시간이 더 오래 걸리게 되는 것을 확인할 수 있었습니다.

      aiometer 를 이용한 방법

      aiometer는 aiolimiter와 같이 asyncio를 이용한 Rate Limit을 적용하기 위한 라이브러리입니다. 아직 베타 버전이라 향후 여러 변경사항이 있을 수 있습니다.

      이 글에서 사용한 버전은 0.5.x 입니다

      • max_at_once: 주어진 시간에 동시에 실행되는 작업의 최대 수를 제한하는 데 사용됩니다.

        (100개의 작업이 있고 max_at_once를 10으로 설정하면, aiometer는 동시에 10개 이상 실행되지 않도록 보장합니다.)

      • max_per_second: 초당 생성되는 작업 수를 제한합니다.

      전체 코드를 바로 살펴봅시다.

      import asyncio
      import functools
      import time
      
      import aiometer
      import httpx
      
      NUM_OF_TOTAL_URLS = 10
      MAX_PER_SECOND = 2
      MAX_AT_ONCE = 5
      
      
      async def fetch(url):
          async with httpx.AsyncClient() as client:
              response = await client.get(url)
              return response
      
      
      async def main(urls):
          results = await aiometer.run_all(
              [functools.partial(fetch, url) for url in urls],
              max_per_second=MAX_PER_SECOND,  # Limit to 2 requests per second
              max_at_once=MAX_AT_ONCE,  # Limit to 5 concurrent tasks
          )
          for result in results:
              print(result.status_code)
      
      
      # List of URLs to fetch
      urls = ["https://httpbin.org/get"] * NUM_OF_TOTAL_URLS
      # Run the main function
      start_time = time.time()
      asyncio.run(main(urls))
      end_time = time.time()
      print(f"Total time: {end_time - start_time} seconds")


      Summary (TL;DR)

      • 이 문서는 파이썬에서 비동기 API 호출에 대한 Rate Limit을 적용하는 방법을 설명합니다.

      • httpx와 aiolimiter, aiometer 라이브러리를 사용하여 동시성과 초당 요청 수를 제어하는 다양한 방법을 제시합니다.

      • 이를 통해 과도한 I/O를 방지하고 서버 용량을 고려한 효율적인 API 호출을 가능하게 합니다.

      댓글 0

      DEVOTEE를 활성화 시키면
      지금 작성한 댓글에 AI가 댓글을 달아줍니다.

      mihosang 님의 최신 블로그

      더보기

      DEVOTEE 추천 블로그

      동영상 기고하기