Мы работаем над улучшением производительности нашего приложения rails, размещенного в Heroku (rails 3.2.8 и ruby 1.9.3). Во время этого мы столкнулись с одной тревожной проблемой, для которой источник кажется чрезвычайно трудным для отслеживания. Позвольте мне быстро объяснить, как мы сталкиваемся с проблемой и как мы пытаемся ее изолировать.
-
С июня мы испытали странное отставание от времени до первого байта по всему сайту. Проблемы очевидны из-за использования сайта (иногда приложение не отвечает в течение 10-20 секунд), и оно также присутствует в анализе водопада через webpagetest.org. Мы находимся в Дании, но получаем этот результат от любого хоста.
Чтобы подтвердить проблему, мы выполнили тестовый тест, в котором мы отправляем 300 одинаковых запросов на простую страницу и измеряем время отклика. Если мы отправляем 300 запросов на первую страницу, среднее время отклика составляет менее 1 секунды, что довольно хорошо. Что нас пугает, так это то, что 60 запросов занимают больше двух раз, и 40 из них занимают более 4 секунд. Некоторые запросы занимают до 16 секунд.
Ни один из этих медленных запросов не появляется в New Relic, который мы используем для мониторинга производительности. Нет очереди запросов, и результаты одинаковы независимо от того, насколько высоко мы масштабируем наши веб-процессы. Тем не менее, мы не могли отказаться от проблемы, вызванной кодом приложения, поэтому мы попробовали другой эксперимент, в котором мы ответили на запрос через промежуточное ПО стойки.
Поместив это промежуточное программное обеспечение (TestMiddleware) в начало стека стека, мы вернули запрос, прежде чем он даже попал в приложение, гарантируя, что ни одно из следующего промежуточного программного обеспечения или приложения rails не может вызвать задержку.
Middleware setup:
$ heroku run rake middleware
use Rack::Cache
use ActionDispatch::Static
use TestMiddleware
use Rack::Rewrite
use Rack::Lock
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use Rack::Sendfile
use ActionDispatch::Callbacks
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::DalliStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use ActionDispatch::Head
use Rack::ConditionalGet
use Rack::ETag
use ActionDispatch::BestStandardsSupport
use NewRelic::Rack::BrowserMonitoring
use Rack::RailsExceptional
use OmniAuth::Builder
run AU::Application.routes
Затем мы запустили тот же script для документирования времени ответа и получили почти такой же результат. Среднее время отклика составляло около 130 мс (очевидно, быстрее, потому что оно не попадало в приложение. Но все же 60 запросов заняли более 400 мс, а 25 запросов заняли более 1 секунды. Опять же, с некоторыми запросами так же медленно, как 16 секунд.
Одно объяснение может быть связано с медленными перелетами в сети или настройкой DNS, но результаты traceroute выглядят отлично.
Этот результат был подтвержден при запуске ответа script на другие рельсы 3.2 и приложение ruby 1.9.3, размещенное на Heroku - вообще не странное поведение.
Настройка DNS следует рекомендациям Heroku.
-
Мы смущены, если не сказать больше. Может ли быть что-то подозрительное в маршрутной сети Heroku? Почему, черт возьми, мы видим это странное поведение? Как мы можем избавиться от него? И почему мы не можем увидеть это в Новой Реликвии?