AppSignal을 사용하는 앱을 실행하는 모든 서버는 30초마다 샘플 및 메트릭 컬렉션을 푸시 API로 보냅니다.
각 요청에는 데이터의 출처를 결정하는 데 사용하는 키가 있습니다. 그렇게 하려면 수신되는 각 요청에 대한 앱을 찾기 위해 데이터베이스를 쿼리해야 합니다. 매월 300억 건의 요청이 있는 우리는 AppSignal을 더 빠르게 만들기 위해 쿼리 수를 줄이는 방법을 끊임없이 찾고 있습니다.
데이터베이스 클러스터의 쿼리 수를 줄이기 위해 캐싱을 구현했습니다. 데이터베이스에서 앱을 가져올 때마다 Memcached에 1분 동안 저장합니다. 이 변경 사항을 프로덕션에 배포한 후 더 많은 작업을 수행하고 있음을 발견했습니다. 이전보다 쿼리. 캐시가 너무 자주 무효화되는 것 같았습니다. 어디서 이런 일이 발생했는지 알아내기 위해 캐시가 부적절하게 무효화된 위치를 찾기 위해 몇 가지 맞춤 측정항목을 추가했습니다.
푸시 처리 시간이 업데이트되거나 새 네임스페이스가 감지되는 경우와 같이 캐시를 무효화하는 몇 가지 위치가 있습니다.
# Update last push processed at time
if app.last_push_processed_at < 5.minutes.ago
app.set(:last_push_processed_at => Time.now)
Rails.cache.delete(cache_key)
end
if namespaces_diff.any?
app.add_to_set(:namespaces => namespaces_diff)
Rails.cache.delete(cache_key)
end
이러한 캐시 무효화 중 어느 것이 범인인지 확인하기 위해 여러 카운터를 추가했습니다. 이 예에서는 app.cache.invalidate
를 증가시킵니다. 총 유효성 검사 횟수를 계산하고 app.cache.invalidate_push_time
과 같은 특정 키를 사용하는 카운터 및 app.cache.invalidate_namespaces
특정 무효화의 경우.
# Update last push processed at at time
if app.last_push_processed_at < 5.minutes.ago
app.set(:last_push_processed_at => Time.now)
Rails.cache.delete(cache_key)
Appsignal.increment_counter('app.cache.invalidate', 1)
Appsignal.increment_counter('app.cache.invalidate_push_time', 1)
end
if namespaces_diff.any?
app.add_to_set(:namespaces => namespaces_diff)
Rails.cache.delete(cache_key)
Appsignal.increment_counter('app.cache.invalidate', 1)
Appsignal.increment_counter('app.cache.invalidate_namespaces', 1)
end
위의 맞춤 측정항목을 추가하여 시간 경과에 따른 캐시 적중률을 그래프로 표시할 수 있었습니다. 어떤 캐시 키가 쿼리 증가를 일으켰는지 즉시 분명해졌습니다. app.cache.invalidate_namespaces
각 요청에 대해 키가 무효화되었습니다.
캐시 가능한 총 요청 수는 app.cache.maybe
로 계산됩니다. .
이 문제에 대한 수정 사항을 배포한 후 앱의 네임스페이스가 업데이트되지 않는 한 무효화 횟수는 0으로 떨어졌습니다.
사용자 지정 측정항목을 추가하면 어디서, 언제, 얼마나 자주 발생하는지 더 쉽게 이해할 수 있습니다. 이 경우 캐시 무효화 횟수를 알고 읽을 수 있는 그래프로 표시하면 문제를 빠르게 찾을 수 있습니다. 특정 값을 증가시키고 대시보드를 생성하려면 몇 줄의 코드만 있으면 됩니다.
사용자 지정 메트릭에 대해 질문이 있거나 애플리케이션에서 설정하는 데 도움이 될 수 있는지 알려주세요. 기꺼이 도와드리겠습니다!