최근 PostAlerter 작업이 중단되거나 OOM 발생

https://github.com/discourse/discourse/commit/9cf981f1f15d3a229003f0ca59ac2fdd28d7d4 (이 커밋일 것으로 추정됩니다!) 이후, 막혀 있는 PostAlert 작업으로 인해 Sidekiq 큐가 가득 차거나 OOM(메모리 부족) 오류가 발생하고 있습니다:

이 커밋은 이미 유사한 회귀 문제가 발생했던 적이 있으므로(FIX: error when CategoryList tried to find relevant topics - Pull Request #22339 - discourse/discourse - GitHub) 의심의 여지가 큽니다. 다만, 지금은 해당 커밋 이전으로 다운그레이드를 시도해 보고 결과를 다시 보고하겠습니다.

2개의 좋아요

4f7f9ef87cbcd574144f657dd43b7e705d98ff8e로 내려간 것이 실제로 막혀 있던 PostAlert 사이드킥(Sidekiq) 워커와 OOM 문제를 해결했습니다: 이제 큐에 추가되는 몇 안 되는 PostAlert 작업들은 몇 분 대신 몇 초 만에 완료됩니다.

2개의 좋아요

@kris.kotlarek에게 알림 보내기

1개의 좋아요

방금 FIX: improve performance of post alerter job (#22378) · discourse/discourse@7a204e7 · GitHub 이 push된 것을 확인했습니다 - 이 문제가 수정된 것이라면 나중에 직접 테스트해 보겠습니다.

2개의 좋아요

네, 이 방법으로 해당 문제가 해결되기를 바랍니다. 이 해결책을 3개의 포럼에서 테스트해 봤는데, 새로운 쿼리는 항상 훨씬 빨랐고 서버를 막히게 하지 않았습니다. 이 문제를 보고해 주셔서 감사합니다. 여전히 문제가 발생하면 알려 주세요.

4개의 좋아요

불행히도, 이러한 변경 사항에도 불구하고 PostAlert 작업이 이전보다 훨씬 더 오래 걸리고, 처리하는 동안 Sidekiq 워커가 완전히 멈추는 현상이 여전히 발생하고 있습니다. :frowning:

(우리는 1,000만 개 이상의 사용자 행을 보유하고 있으며, 일부 카테고리는 기본적으로 음소거되어 있어 설정된 음소거가 매우 많습니다!)

한편, 이 작업을 최근에 수정한 세 개의 커밋을 되돌리고 컨테이너를 재시작하면 작업이 정상적으로 완료됩니다.

3개의 좋아요

감사합니다. 다시 한 번 확인해 보겠습니다.

해당 잡의 성능을 개선하기 위한 또 다른 시도를 병합했습니다:

몇몇 인스턴스에서 테스트를 해보았는데 문제는 없었지만, 그 인스턴스들은 당신의 것보다 규모가 작았습니다.

이 커밋을 적용해도 여전히 실패한다면 EXPLAIN ANALYSE 리포트를 제공해 주시겠어요? 생성을 위한 스크립트는 다음과 같습니다:

topic = Topic.last
user_option_sql_fragment =
  if SiteSetting.watched_precedence_over_muted
    <<~SQL
    INTERSECT
    SELECT user_id FROM user_options WHERE user_options.watched_precedence_over_muted IS false
    SQL
  else
    <<~SQL
    EXCEPT
    SELECT user_id FROM user_options WHERE user_options.watched_precedence_over_muted IS true
    SQL
  end
user_ids_sql = <<~SQL
  (
    SELECT user_id FROM category_users WHERE category_id = #{topic.category_id.to_i} AND notification_level = #{CategoryUser.notification_levels[:muted]}
    UNION
    SELECT user_id FROM tag_users tu JOIN topic_tags tt ON tt.tag_id = tu.tag_id AND tt.topic_id = #{topic.id} WHERE tu.notification_level = #{TagUser.notification_levels[:muted]}
    EXCEPT
    SELECT user_id FROM topic_users tus WHERE tus.topic_id = #{topic.id} AND tus.notification_level = #{TopicUser.notification_levels[:watching]}
  )
  #{user_option_sql_fragment}
SQL
sql = User.where("id IN (#{user_ids_sql})").to_sql

sql_with_index = <<SQL
EXPLAIN ANALYZE #{sql};
SQL
result = ActiveRecord::Base.connection.execute("#{sql_with_index}")
puts sql_with_index
result.each do |r|
  puts r.values
end

누락된 인덱스를 찾거나 이 쿼리의 어떤 부분이 그렇게 느린지를 파악하는 데 도움이 될 것입니다.

3개의 좋아요

이 변경 사항으로 인해 PostAlert 작업이 정상적인 소요 시간으로 돌아왔고, Sidekiq 인스턴스가 더 이상 멈추지 않는 것 같습니다. 최고입니다!

3개의 좋아요

이 주제는 3일 후 자동으로 닫혔습니다. 더 이상 새 답변을 작성할 수 없습니다.