Вузьке місце в сервері чи в застосунку: як це виміряти
Час до першого байта на кожному стрибку, лічильники запасу на хості та slow log з ключем за блокуючим кадром розміщують повільний сайт в одному шарі до того, як будь-що зміниться.
У цій статті 7 розділів
- Вимірюйте час до першого байта на кожному стрибку: через edge, напряму до origin і на localhost. Найбільший розрив між двома сусідніми числами є шаром, якому належить latency.
- Читайте запас хоста, поки він повільний: простій CPU і steal, доступна пам'ять, await диска й глибина черги. Запас усюди під повільним сайтом означає, що обмеження розташоване вище за обладнання.
- Усередині шару застосунку агрегуйте: запити за URL, повільні запити за їхнім блокуючим кадром, запити до бази за digest. Кожне з цього згортає тисячі рядків у короткий ранжований список з одним-двома іменами нагорі.
Час до першого байта на кожному стрибку
Теорії про повільний сайт легко сформувати і важко довести. Три вимірювання їх вирішують. Зніміть час до першого байта через публічний edge, ще раз напряму до origin в обхід edge, і ще раз на хості застосунку до localhost. Різниця між двома сусідніми показаннями є вартістю цього шару.
# through the edge
curl -s -o /dev/null -w 'dns=%{time_namelookup} tls=%{time_appconnect} ttfb=%{time_starttransfer}\n' https://site.example/
# direct to the origin, edge bypassed
curl -s -o /dev/null -w 'ttfb=%{time_starttransfer}\n' --resolve site.example:443:ORIGIN_IP https://site.example/
# on the host, nothing in front of the application
curl -s -o /dev/null -w 'ttfb=%{time_starttransfer}\n' http://127.0.0.1/Усе, що залишається на localhost, є застосунком і сервісами, які він викликає. Шар з найбільшим розривом є тим, куди йде решта роботи.
Запас, поки болить
Читайте лічильники під час повільного періоду, а не після нього.
vmstat 1 5 # r (run queue), wa (I/O wait), st (steal), id (idle)
iostat -x 1 5 # await and aqu-sz per device
free -m # the available column, not usedДовга черга виконання з низьким простоєм є хостом, обмеженим CPU. Високий I/O wait з високим await на пристрої є сховищем. Steal є сусідом на спільному гіпервізорі, який забирає цикли, яких хотів гість. Вільний CPU, доступна пам'ять і пристрої з низьким await під повільним сайтом означають, що хост чекає на щось, що хосту не належить: зовнішній виклик, блокування, запит, повільний з причин, не пов'язаних з обладнанням. Додавання обладнання в цей момент дає більш вільну машину, яка досі повільна.
Між цими двома є третя категорія, і вона поширена: пул. Сторінка статусу PHP-FPM показує чергу listen; черга запитів, що чекають, при вільному CPU означає, що кожен worker зайнятий, зазвичай заблокований на тому самому повільному виклику, і сайт повільний через стелю конфігурації, а не стелю ресурсів. Та сама форма проявляється як насичений пул з'єднань бази даних або повна черга backend у HAProxy. Хост невинний, а код ще не засуджений; розмір пулу і виклик, на який він чекає, є двома наступними показаннями.
Прочитайте трафік перед кодом
Журнал доступу каже, що це за проблема. Спочатку знайдіть журнал окремого vhost; типовий журнал може нести малу частку реального трафіку, і підрахунок над неправильним файлом дає впевнену неправильну відповідь.
tail -n 100000 access.log | awk -F'"' '{print $2}' | sort | uniq -c | sort -rn | headКілька URL, повторених тисячі разів, означають, що сайт викликає сам себе, і виправленням є кеш перед цими URL. Запити, що крокують у порядку sitemap, є краулером, і виправленням є обмеження частоти. Широке рівномірне зростання по багатьох URL є попитом, і виправленням є потужність.
Згорніть slow log і журнал запитів
Slow log є купою stack trace, доки йому не задано ключ. Увімкніть slow log PHP-FPM з порогом, який ловить запити, на які скаржаться користувачі, потім задайте кожному трейсу ключ за кадром, у якому він був заблокований, листком, і порахуйте. Ранжований список короткий, а нагорі зазвичай один зовнішній виклик або один запит до бази.
На боці бази даних ранжуйте за digest, а не за планом. Непослідовна параметризація розбиває один логічний запит на багато планів, кожен з яких виглядає нешкідливим; підсумовані за digest, вони збираються назад в один рядок, справжнього власника часу бази даних.
-- MySQL and Percona: by statement digest
SELECT digest_text, count_star, sum_timer_wait
FROM performance_schema.events_statements_summary_by_digest
ORDER BY sum_timer_wait DESC
LIMIT 10;
-- SQL Server: by query hash
SELECT query_hash, COUNT(*) AS plans, SUM(total_worker_time) AS cpu
FROM sys.dm_exec_query_stats
GROUP BY query_hash
ORDER BY cpu DESC;Перш ніж писати будь-який індекс, перевірте реальну кількість рядків і індекси, які вже існують. Індекс на таблиці, якій він не потрібен, є повільнішим шляхом запису.
Читайте першоджерело, а не правдоподібну історію
| Історія | Джерело, яке її вирішує |
|---|---|
| Воно впало, йому забракло пам'яті | dmesg, journalctl --list-boots, last -x reboot: чи воно перезавантажилося і чому |
| База даних пошкоджена | власний журнал помилок бази даних, з пошуком повідомлень про crash і corruption |
| Процес-утікач з'їдає CPU | ps --forest і /proc/<pid>/cmdline: його справжня ідентичність і батько, а не правдоподібне ім'я |
| Ми бачимо помилки цілісності | ethtool -S на інтерфейсі: нуль помилок на дроті означає, що проблема вище за дріт |
| SELinux це блокує | ausearch -m avc -ts recent через audit2why: відмова, названа, з модулем політики, який її виправляє |
Кожен рядок замінює теорію показанням. Останній важить на системі в режимі enforcing: журнал аудиту відповідає на питання, не змінюючи стану безпеки, щоб його поставити.
Доведіть, потім перевірте тим самим вимірюванням
Кореляція дає підозрюваного. Мале оборотне збурення його засуджує: зупиніть підозрілі запити на кілька секунд і дивіться, чи знову наповнюється навантаження. Якщо наповнюється одразу, рушієм є живий трафік, і виправлення належить до edge, перед запитами, які взагалі не мали б доходити до бази даних. Доки причина невідома, система лише для читання. Коли виправлення застосоване, воно перевіряється вимірюванням, яке знайшло проблему: якщо час до першого байта на стрибок її локалізував, час до першого байта на стрибок підтверджує, що вона зникла.
Що ми виправляємо і що повертаємо вам
| На edge, того ж дня | У вашому коді, з точною зміною |
|---|---|
| Мікрокешування зі згортанням запитів перед гарячими URL | Перенести синхронний виклик третьої сторони у фонове завдання з таймаутом і запасним варіантом |
| Пули workers і буферів, розміри яких задані за виміряним навантаженням | Прибрати цикл рендерингу або цикл повторів |
| Покривний індекс, доданий online | Очищувати дані застосунку, що зростають без меж |
| Налаштовані повтори й таймаути HAProxy, виправлений контекст SELinux | Зменшити корисне навантаження і скрипти, що відправляються в браузер |
Ми не змінюємо ваш код. Ми називаємо рядок, показуємо вимірювання, яке на нього вказує, і тримаємо сайт у роботі, поки ви його виправляєте.
Прямі відповіді
Як зрозуміти, повільний у мене сервер чи застосунок?+
Читайте запас під час повільного періоду: простій CPU і steal, доступна пам'ять, await диска. Якщо всі три мають запас, обмеження розташоване вище за обладнання, у застосунку або в сервісі, який він викликає. Час до першого байта на localhost у порівнянні з edge підтверджує, який шар.
Як знайти повільний запит до бази даних?+
Ранжуйте за digest, а не за дескриптором плану, щоб один логічний запит з багатьма параметризаціями показував свою загальну вартість в одному рядку. Потім перевірте кількість рядків і наявні індекси, перш ніж писати будь-який DDL.
Чи можете ви відрізнити бота від справжнього сплеску трафіку?+
З журналу доступу, за частотою URL. Жменя URL, повторених тисячі разів, є сайтом, що викликає сам себе, порядок sitemap є краулером, широке зростання є попитом. Кожне отримує інше виправлення.
Чи змінюєте ви мій код?+
Ні. Усе на боці інфраструктури ми виправляємо на edge того ж дня, оборотно. Усе у вашому коді ми повертаємо вам як точну зміну, з вимірюванням, яке її обґрунтовує.
Ваш сайт повільний, і ніхто не погоджується чому.
Поговоріть з інженером, який вимірює кожен стрибок, перш ніж будь-чого торкатися.
Поговоріть з інженеромВи дійшли до кінця.
Застосуйте прочитане на практиці
Що ви запускаєте?
Розкажіть нам про навантаження, трафік і вимоги до відновлення. Почніть з конструктора сервера або обговоріть деталі з інженером.
Написано інженерами, які будують і експлуатують інфраструктуру, про яку йдеться.Поговоріть з інженером
