관리자가 일괄 생성할 때 RateLimiter를 일시적으로 끄는 방법이 있나요?

제가 겪고 있는 문제를 설명드리겠습니다. 플러그인 관리자 액션을 통해 Discourse 프로덕션 인스턴스에 약 200개의 게시물을 한 번에 시드(seed)하는 기능이 필요합니다. 이 게시물들은 10명의 일반 사용자 중 한 명에 의해 ‘생성된’ 것으로 표시되어야 합니다. 이 기능이 플러그인 액션인 이유는, 해당 인스턴스의 사용자들이 훈련시킬 모더레이터 팀이 있기 때문이며, 훈련용 테스트 게시물이 필요하고 필요할 때마다 추가 시드할 수 있는 기능을 원했기 때문입니다.

PostCreator.new에 skip_validations: true를 전달하는 방식으로 이 기능을 정상적으로 구현했습니다. 그러나 이제 생성된 게시물 중 일부가 플래그(flag) 처리되어야 한다는 새로운 요구사항이 생겼습니다.

일부 게시물에 플래그를 걸기 위해 PostActionCreator.create를 사용하고 있는데, 현재 다음과 같은 위치의 레이트 리미터(rate limiter)에 막히고 있습니다: discourse/lib/post_action_creator.rb at ad7a13921f2af8c792530c84386b64911c8e7ea2 · discourse/discourse · GitHub

처음에는 RateLimiter를 비활성화하는 방법을 시도했는데, 이는 결국 서버 프로세스를 크래시 시켰습니다. 아마도 다시 활성화하려고 할 때 발생했을 가능성이 높으며, 나중에 생각해보니 원래부터 좋은 아이디어가 아니었습니다.

따라서 제 질문은, 임의의 코드를 실행할 때 레이트 리미터를 우회하는 더 나은 방법이 있는지입니다. 예를 들어 다음과 같은 것 말이죠:

RateLimiter.bypass do
# 레이트 리미터의 영향을 받지 않는 코드 실행
end

아니면, PostActionCreator가 수행하는 대부분의 로직을 복사하되 문제의 줄만 제외하는 방식으로 처리해야 하는 건가요?

도움 주시면 감사하겠습니다! 아직 Discourse 코드를 많이 흡수하는 중이라, 이 문제를 훨씬 쉽게 해결할 수 있는 것을 놓치고 있을 수 있다는 것을 잘 알고 있습니다.

내가 할 가능성이 높은 일은 Rails 콘솔에서 스크립트를 실행하는 것입니다. Available settings for global rate limits and throttling 링크를 확인해 보셨나요? 해당 링크에 따르면 그 레이트 리밋을 변경할 수 있는 것으로 보입니다.

이건 제가 원하지 않는 방향입니다. 콘솔에서 스크립트를 실행하는 것을 제가 대신 해주어야 하는 대신, 사용자가 직접 시작할 수 있도록 하고 싶으니까요.

레이트 리밋 변경에 관한 링크를 확인해 보셨나요?

해결하셨나요? yaml 파일을 수정하는 것은 재빌드가 필요하기 때문에 이상적인 방법이 아닙니다. rails/discourse에 충분히 익숙하지 않아서 콘솔에서 이를 일시적으로 비활성화하는 방법을 알아내지 못했습니다.

당신의 사용 사례는 무엇인가요? 레이트 리밋으로 인해 해결하지 못하고 있는 문제는 무엇인가요?

재빌드 없이 API를 통해 6만 명의 사용자를 최대한 빠르게 가져오려고 합니다. 테스트 설치 환경에서 YAML을 통해 관리자 API 한도를 상향 조정해 보았지만, 작동하지 않는 것 같았습니다. 다만 제가 잘못했을 수도 있습니다. (컨테이너에서 가져오기를 실행 중이므로 HTTP 스로틀링은 적용되지 않아야 합니다).

별로 도움이 되지는 않지만, 내 방식이라면 API를 통해 생성하는 대신 rails에서 직접 사용자를 생성하겠습니다. discourse/script/import_scripts/csv_importer.rb at main · discourse/discourse · GitHub 파일을 시작점으로 삼을 수 있습니다.

컨테이너에 진입하여 /var/www/discourse/config/discourse.conf 파일을 편집하고 해당 변수를 설정한 뒤, sv restart unicorn(또는 sv reload unicorn)을 실행하면 됩니다. 편집기를 사용하기 위해 apt-get update; apt-get install -y vim과 같은 명령을 실행할 필요가 있을 것입니다.

이상하네요. 설정 파일을 확인해 보니 새 제한 값이 이미 설정되어 있습니다. 즉, YAML 업데이트는 정상적으로 적용되었네요:

max_admin_api_reqs_per_key_per_minute = '6000'

하지만 실제로는 작동하지 않는 것 같습니다. 여전히 분당 60회 제한이 적용되고 있습니다. 요청을 분당 60회로 제한하면 대부분은 통과하지만, 지터(jitter)로 인해 일부 요청은 여전히 레이트 리미터를 트리거합니다:

{'success': True, 'active': True, 'message': 'Your account is activated and ready to use.', 'user_id': 3596}
{'success': False, 'message': ' New registrations are not allowed from your IP address (maximum limit reached). Contact a staff member.', 'errors': {'ip_address': ['New registrations are not allowed from your IP address (maximum limit reached). Contact a staff member.']}, 'values': {'name': None, 'username': 'asdfd', 'email': 'user@domain.com'}, 'is_developer': False}
{'success': True, 'active': True, 'message': 'Your account is activated and ready to use.', 'user_id': 3597}

따옴표 때문에 문제가 생기는 건 아닌지 궁금하네요.

SiteSettings.max_admin_api_reqs_per_key_per_minute가 정수인지 확인해 보세요.

in default_current_user_provider.rb (이 값을 참조하는 것으로 보이는 유일한 파일인데, 여기에는 다음과 같은 코드가 있습니다:

limit = GlobalSetting.max_admin_api_reqs_per_minute.to_i

따라서 변환을 수행하는 것 같습니다. 코드에서 숫자로 직접 대체해서 시도해 보기도 했습니다.)

아니, 그거 걱정했거든.

다른 한도와 관련이 있다고 생각합니다. IP당 최대 등록 횟수 한도에 도달한 것 같은데, 이 한도에 도달한 후에도 영구적으로 차단되지 않는 이유를 이해할 수 없습니다. 이 스팸 제한 기능의 버그일 수도 있습니다.

그 사용자들의 IP가 모두 동일하다면, 당신의 말이 맞을 것 같습니다. 해결책은 해당 설정을 변경하거나, 127.0.0.x 같은 가짜 IP 주소를 부여하는 것일 겁니다. (혹은 더 쉽게 하려면 IPv6을 사용하는 것도 좋겠네요?)

요청이 어디서(호스트 컴퓨터)에서 이루어지는지 감지하는 것 같습니다. 하지만 같은 IP 주소에 TL2 사용자를 추가하거나 IP 한도를 조정하여 우회할 수 있습니다.

다만, 사용자 추가 API는 매우 느립니다.

그래서 저는 레일즈(Rails)로 구현하는 것을 추천합니다. 분당 약 500건을 처리할 수 있을 것입니다.

네, 그렇게 해볼게요. 하지만 스크립트를 어떻게 실행해야 하는지, 어디에 복사해서 넣어야 하는지, 그리고 CSV 파일을 올바른 위치에 배치한 후 어떻게 실행해야 하는지 정확히 모르겠습니다.

나머지는 다른 튜토리얼 주제들을 참고해 보세요. 대부분 작동 방식이 비슷합니다.

스크립트와 Ruby 등을 이해하려는 노력과 예상되는 성능을 고려하여, 다른 방법을 선택했습니다. SQL을 사용하여 데이터베이스에 직접 쓰기 방식을 통해 모든 제한을 우회했습니다. 이렇게 하면 초당 수천 건의 삽입을 수행할 수 있었습니다.

어떤 테이블이 필요한지 묻는 토픽이 있었으나, 현재는 폐쇄되어 있습니다. 따라서 여기서 답변드리면, 사용자를 삽입하기 위해 다음 테이블들을 수정했습니다:

user_avatars
user_emails
user_profiles
user_search_data
user_stats
users