Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: #BBB-120 알고리즘 과제 할당 및 해결 여부 요청에 Rate Limit과 대기열 시스템 적용 #51

Merged
merged 15 commits into from
Oct 10, 2024

Conversation

platinouss
Copy link
Contributor

@platinouss platinouss commented Aug 5, 2024

작업 개요

  • 알고리즘 스터디 과제 해결 여부 업데이트 API 구현
  • solved.ac API를 호출하여, 특정 유저가 과제로 출제된 문제를 해결했는지 확인 후, 해결 여부를 갱신하는 API 구현
  • 하지만 solved.ac API에는 rate limit이 적용되어 있어서, 요청이 몰리는 경우 과제 해결 여부 갱신에 실패할 수 있음

목표

  1. 유저가 갱신 요청을 하면, 시간이 걸리더라도 반드시 과제 해결 여부를 갱신시켜준다.
  2. 외부 API에 15분에 256개를 넘지않도록 요청 수 제한

적용

  1. 대기열 큐 시스템 적용
  2. token bucket 알고리즘 기반 rate limit 적용

전달 사항

solved.ac API 정보

  • 요청을 위한 특정 헤더 필요 없이 사용 가능
  • 로그인 하지 않았다면 ip 주소 기반 rate limit 적용됨 (로그인 한 상태라면 user id 기반 rate limit)
  • 과도한 요청 시 ban (ip 주소 또는 solved.ac 계정 밴)
  • api 요청 제한
    • 256개의 request / window (window size = 15분) (solved.ac 비로그인 상태인 경우에는 조금 더 널널한 것 같음)
    • query 길이 512자 이하

참고 자료

Redis Streams 자료구조 관련 공식 도큐먼트

https://redis.io/docs/latest/commands
https://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/StreamOperations.html

Token Bucket 알고리즘기반 rate limit (bucket4j)

https://bucket4j.com/8.14.0/toc.html

@platinouss platinouss added the ✨Feat 새로운 기능 추가 label Aug 5, 2024
@platinouss platinouss self-assigned this Aug 5, 2024
@platinouss platinouss marked this pull request as draft August 5, 2024 12:36
@platinouss platinouss force-pushed the feat/check_assignment_problem_solve#BBB-120 branch 2 times, most recently from 00b53ca to 760bc75 Compare August 13, 2024 07:45
@platinouss platinouss force-pushed the feat/check_assignment_problem_solve#BBB-120 branch from 760bc75 to e5a81ae Compare August 31, 2024 07:01
@platinouss platinouss marked this pull request as ready for review September 7, 2024 11:07
@platinouss platinouss force-pushed the feat/check_assignment_problem_solve#BBB-120 branch from 35895a2 to 39a4633 Compare September 7, 2024 12:17
@platinouss platinouss requested a review from msjang4 September 10, 2024 09:41
Copy link
Contributor

@msjang4 msjang4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redis가 진짜 만능이네요 ㄷㄷ.. prod/cons 큐로 kafka를 써볼 수 있는 경험이셨을텐데 redis를 쓰신 이유가 궁금해요.

tokenbucket 라이브러리로 rate limit 구현한 부분이 굉장히 멋있네요, quatzjob + multi thread(concurrent ds) + aop + redis 등 쉽지않은 기술이 다 접목된것 같습니다.
고생하셨습니다. 많이 배웠어요!

  1. 버킷이 in-memory인것처럼 보이는데 그러면 멀티 서버 환경에서 tokenbucket은 적용되지 않는 걸까요?
  2. 만약 in-memory가 맞다면 buckCreationTime도 redis가 아닌 in-memory로 관리해도 되지않나요?

@platinouss platinouss force-pushed the feat/check_assignment_problem_solve#BBB-120 branch from 39a4633 to 800897c Compare October 9, 2024 23:58
@platinouss platinouss changed the title Feat: #BBB-120 알고리즘 스터디 과제 해결 여부 업데이트 API Feat: #BBB-120 알고리즘 과제 할당 및 해결 여부 요청에 Rate Limit과 대기열 큐 시스템 적용 Oct 10, 2024
@platinouss platinouss changed the title Feat: #BBB-120 알고리즘 과제 할당 및 해결 여부 요청에 Rate Limit과 대기열 큐 시스템 적용 Feat: #BBB-120 알고리즘 과제 할당 및 해결 여부 요청에 Rate Limit과 대기열 시스템 적용 Oct 10, 2024
@platinouss
Copy link
Contributor Author

platinouss commented Oct 10, 2024

redis가 진짜 만능이네요 ㄷㄷ.. prod/cons 큐로 kafka를 써볼 수 있는 경험이셨을텐데 redis를 쓰신 이유가 궁금해요.

tokenbucket 라이브러리로 rate limit 구현한 부분이 굉장히 멋있네요, quatzjob + multi thread(concurrent ds) + aop + redis 등 쉽지않은 기술이 다 접목된것 같습니다. 고생하셨습니다. 많이 배웠어요!

  1. 버킷이 in-memory인것처럼 보이는데 그러면 멀티 서버 환경에서 tokenbucket은 적용되지 않는 걸까요?
  2. 만약 in-memory가 맞다면 buckCreationTime도 redis가 아닌 in-memory로 관리해도 되지않나요?

Kafka를 쓰지 않았던 이유는, Kafka의 경우 이벤트를 전달하는 용도로 사용된다고 생각하여 대기열 큐로 어찌저찌 사용될 수도 있겠지만? 적합하지 않다고 생각했어요. 또한 요구 사항이 변경되면(대기 순번을 제공하도록 구현하는 등) Redis의 Sorted set과 같이 다른 자료구조로 변경할 수 있기 때문에 유연성 측면에서도 Redis가 적합하다고 생각했습니다.

현재 구현된 방식은 Redis에서 버킷 내부에 존재하는 토큰 개수 등을 관리하기 때문에 다중화된 서버 환경에서도 동일한 버킷을 바라보게 돼요.
https://bucket4j.com/8.13.1/toc.html#bucket4j-redis
위 공식 문서를 바탕으로 구현을 진행했어요

solved.ac API를 활용하여, 특정 유저의 스터디 과제로 배정된 알고리즘 문제를 실제로 해결했는지 판단합니다. 만약 해결했다면 DB의 과제 해결 history에 기록하고, 해당 유저의 과제 해결 여부 상태를 반환하는 API를 구현했습니다.
문제 해결 여부를 확인하기 위해서 호출해야 하는 API에 rate limit이 적용되어 있었습니다. 따라서 유저의 과제 갱신 요청을 보장하기 위해서는 메시지 큐 시스템을 구성해야 했으며 redis streams 기반으로 적용했습니다.
문제 해결 여부 확인을 위해 호출하는 solved.ac API에 rate limit이 적용되어 있었습니다. 따라서 token bucket algorithm 기반 rate limit을 적용했습니다.
rate limit을 위한 버킷에 토큰이 없을 경우, 토큰이 갱신될 때까지 대기열에 요청이 있는지 확인하는 스케줄링 작업을 중지하도록 설정했으나, 정상적으로 동작하지 않는 문제가 있어 해당 문제를 해결했습니다.
알고리즘 과제 할당 및 해결 여부 갱신 요청에 Rate Limit과 대기열 시스템이 적용되어 있습니다. 해당 요청 처리 흐름을 이해하기 쉽게 Javadoc 형식으로 문서화했습니다.
@platinouss platinouss force-pushed the feat/check_assignment_problem_solve#BBB-120 branch from 059ca53 to 90c5337 Compare October 10, 2024 12:39
@platinouss platinouss merged commit 4a0cf42 into develop Oct 10, 2024
1 check passed
@msjang4 msjang4 deleted the feat/check_assignment_problem_solve#BBB-120 branch October 11, 2024 00:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨Feat 새로운 기능 추가
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

2 participants