Після введення в лад динамічного веб-сервера на базі Apache + PHP + PostgreSQL (та й на базі інших систем теж, якщо чесно) вебмастер часто виявляє, що продуктивність системи починає з більшою чи меншою активністю прагнути до нуля, часом досягаючи його при напливах відвідувачів. Стандартними діями вебмастера при цьому є гарячковий читання документації, пошук в Інтернеті усіляких корисних порад, спілкування у форумах і інші рухи тіла, типові для "комп'ютерного авралу". При цьому дуже часто знаходяться якісь уривки інформації, відповіді із серії "у мене запрацювало, а чому в тебе не працює - не знаю", суперечливі поради і посилання на мегабайтний исходники, розбір яких загрожує затягнутися на кілька років ...

Тому нижче зроблена спроба в компактному вигляді викласти ті речі, які найбільш значно впливають на продуктивність сервера. Не можна сказати, що цей список є повним і закінченим, але він може послужити непоганою їжею для роздумів. А якщо у вас є якісь свої напрацювання і "ідеї з приводу" - пишіть автору, він постарається врахувати їх в такій редакції цієї статті ...

Настройка PHP

Постійне з'єднання з базою даних дуже помітно знижує завантаження сервераНастройка PHP, по великому рахунку , зводиться до включенняpersistent connectionsі, відповідно, використання pg_pconnect () замість pg_connect () в скриптах. Для цього у файлі php.ini треба вказати
pgsql.allow_persistent = On.

У деяких форумах зустрічалася рекомендація встановити ще і pgsql.auto_reset_persistent = On для визначення "битих" з'єднань, але чи то "биті з'єднання" зустрічаються дуже рідко, чи то вони проявляються якось непомітно ... Словом, цього можна і не робити. Обмежень по кількості з'єднань в PHP можна не встановлювати, залишивши
pgsql.max_persistent = -1
pgsql.max_links = -1

Ефект від переходу на постійні з'єднання дуже помітний, особливо на відвідуваних сайтах. Завантаження відразу падає відсотків на двадцять-тридцять, а то й більше. Тільки не лякайтеся, виявляючи в top'е купу postres'ов в стані sbwait ...

Налаштування PostgreSQL

Налаштування PostgreSQL здійснюється за допомогою редагування файлу postgresql.conf і подальшого перезапуску постмастера. Незважаючи на те, що деякі параметри можна міняти "на льоту", практика показала, що повний перезапуск дозволяє набагато точніше і швидше відстежити вплив тих чи інших змін конфігурації на поведінку системи в цілому, так що має сенс використовувати саме цей метод.

Shared memory дозволяє Postgres'у зберігати дані в пам'яті, а не на діскеНастройкаshared_buffersв Postgres'е дуже важлива. Чим більше пам'яті йому виділено, тим більше даних він зможе використовувати, не звертаючись до диску. Але якщо пам'яті виділити занадто багато, то іншим процесам її може не вистачити, і вони будуть використовувати файл підкачки. Тому з налаштуванням цього параметра доведеться поекспериментувати - крім усього іншого, дуже багато залежить від конкретики вашого сайту - зокрема, від того, наскільки часто запитуються одні й ті ж дані. В якості стартової точки можна спробувати виділити Postgres'у 40% пам'яті, якщо він працює на одній машині з веб-сервером, і 70%, якщо це виділений сервер баз даних. Тільки не забудьте, що до того як вказувати кількість пам'яті у файлі postgresql.conf, вам треба налаштувати операційну систему, щоб вона дозволила цю пам'ять забрати, інакше PostgreSQL просто не запуститься, повідомивши в балці - мовляв, не вдалося отримати необхідну пам'ять. Про те, як налаштувати виділення необхідної пам'яті в різних ОС, докладно написано в документації PostgreSQL. Ця пам'ять виділяється один раз при старті сервера.

Наступний корисний параметр -sort_mem. Ця пам'ять використовується для сортування отриманих наборів даних, і велика її кількість корисно, якщо ваші запити часто використовують SELECT ... ORDER BY ... Але з цим параметром треба бути дуже обережним - мало того що вказане вами кількість пам'яті виділяється кожному процесу, так воно ще й може виділятися кілька разів для складних запитів! Так що з цим параметром теж варто "пограти" - спробуйте змінювати його значення в діапазоні, скажімо, від 1 Мб до 128 кб. Причому іноді результати бувають парадоксальними - зменшення пам'яті веде до підвищення продуктивності - по всій видимості, через створення безлічі маленьких тимчасових файлів, які операційна система успішно кешує у вільній пам'яті.

Відключення fsync дозволяє прискорити роботу, але збільшує ризик втрати даннихЕслі завдання, що виконуються на сервері, не є критичними, і можлива втрата кількох записів при аварії вас не лякає, то варто також скасувати примусову запис на диск результатів кожної транзакції. Робиться це зазначеннямfsync = false. При цьому результати ваших змін будуть зберігатися в пам'яті і записуватися на диск цілими блоками, що дозволить досить помітно збільшити продуктивність. Але, як було зазначено вище, якщо раптом сервер "впаде", то результати декількох останніх оновлень можуть бути загублені.

Індекси дозволяють СУБД швидко знайти потрібну запісьОчень сильно впливає на швидкість роботи грамотнеіндексування таблиць. Про індекси можна писати (і вже написано) багато, але основний принцип - індексувати треба ті поля, які використовується для вибірки даних (перевіряються в WHERE). Складові індекси (в яких використовується кілька полів) працюють, якщо відбір відбувається з умовою AND; якщо ж використовується OR, то треба створювати кілька окремих індексів.

Маленькі таблиці краще не індексіроватьОднако для маленьких таблиць (скажімо, до 500 рядків) перебір майже завжди виявляється швидше, ніж використання індексів. Тут можна застосувати маленьку хитрість: у postgresql.conf вказати enable_seqscan = false (це заборонить перебір для тих таблиць, у яких є індекси) і видалити всі індекси в маленьких таблицях (індекси, автоматично створювані для первинних ключів, можна видалити, використовуючи DROP CONSTRAINT) .

Непоганий виграш в продуктивності може дати іоптимізація самих SQL-запитів, особливо тих, які використовуються найчастіше. Для того щоб їх вирахувати, можна в скриптах перенумерувати всі запити і перед кожним викликом pg_query () записувати в лог (або в таблицю) номер запиту. А потім просто проаналізувати лог ... Для того щоб подивитися, як буде виконуватися запит, можна (і потрібно!) Використовувати команду EXPLAIN. Врахуйте, що в деяких випадках навіть проста зміна порядку проходження умов вибірки в секції WHERE може змінити план виконання запиту!

У деяких випадках може допомогти івикористання уявлень (VIEWS). Справа в тому, що при видачі "звичайного" SQL-запиту сервер його аналізує, створює план виконання і потім виконує. А якщо використовується представлення, то аналіз і складання плану проводиться тільки при його створенні. Якщо запити виконуються часто, то зекономлений час роботи процесора може виявитися досить помітним. Не кажучи вже про те, що запити в скриптах стануть набагато коротше і наочніше ...

Не забувайте запускати VACUUM FULLПрактіческі у всіх довідниках (і в документації PostgreSQL) можна зустріти рекомендаціїрегулярно запускати VACUUM ANALYZEдля стиснення таблиць. Рекомендація правильна і корисна, але недостатня. Практика показала, що без більш-менш регулярних запусків VACUUM FULL ANALYZE продуктивність системи поступово падає, причому чим далі, тим більше. Різниця між VACUUM і VACUUM FULL полягає в тому, що FULL фізично переписує на диску всю таблицю таким чином, щоб у ній не залишалося "дірок" від видалених або оновлених записів. Але у нього є недолік - під час роботи таблиця повністю блокується, що може привести до проблем на популярному сервері - почне накопичуватися черга запитів, які очікують доступу до бази, кожен запит вимагає пам'яті, пам'ять кінчається, починається запис в swap, через відсутність пам'яті сам VACUUM теж починає використовувати swap, і все в підсумку працює дуже-дуже повільно.

Тут можна використовувати наступний трюк - під час роботи VACUUM'а перенаправляти відвідувачів на сторінку з поясненнями, що йде профілактика, і сервер відновить свою роботу через кілька хвилин.

При використанні веб-сервера Apache це легко робиться з помощьюmod_rewrite: ваш оптимізуючий скрипт при запуску створює, а при закінченні роботи видаляє файл/home/site/optimizer.pid, а в Apache включається mod_rewrite і вказується
RewriteCond/home/site/optimizer.pid-f
RewriteRule. */optimization_message.html

Для того щоб зменшити час, протягом якого відвідувачі не можуть дістатися до вашого сайту, можна перенаправляти відвідувачів тільки в той час, коли оптимізуються великі і часто використовувані таблиці , а решта "чистити" паралльно з роботою сайту. Якщо дані в базі оновлюються дуже часто, то можна, скажімо, кожну годину запускати VACUUM ANALYZE, а раз на добу - VACUUM FULL ANALYZE. Як правило, "час недоступності" сервера при такому підході можна скоротити до однієї-двох хвилин навіть на дуже великих сайтах.

Чистити треба не тільки таблиці, але і індексиКроме того, треба врахувати, що VACUUM не оптимізують індекси, тому після відпрацювання VACUUM FULL ANALYZE варто запускати ще йREINDEX.

Зрозуміло, дуже великий вплив на продуктивність робить і структура вашої бази даних, але ця область дуже сильно залежить від конкретного завдання, і в даній статті вона зачіпає не буде.

Настройка Apache

Конфігураційний файл Apache, як правило, знаходиться в/usr/local/apache/conf/httpd.conf, а змусити сервер його перечитати можна за допомогою проргамми/usr/local/apache/bin/apachectl.

Основний метою подальших рекомендацій є визначення і обмеження кількості "апачів", що виконуються в кожен момент часу (передбачається, що сам сервер у вас вже налаштований і працездатний). Справа в тому, що (умовно) на кожного відвідувача сайту "витрачається" процес Apache, і кожен такий процес витрачає пам'ять і процесорний час. Тому якщо у вас буде дуже багато запущених серверів, то оперативної пам'яті не вистачить, а використання swap'а сильно уповільнює роботу сайту. З іншого боку, якщо запущених серверів мало, то при заході користувача буде витрачатися час на створення нового процесу, що знову-таки призводить до затримок і витраті процесорного часу.

З вищесказаного ясно, що, з одного боку, бажано завжди мати деякий запас запущених серверів для обслуговування відвідувачів, а з іншого - треба вбивати зайві сервера, щоб не витрачати занадто вже багато пам'яті. Зрозуміло, що конкретні цифри залежать від відвідуваності вашого сайту і доступних ресурсів, тому що наводяться нижче цифри варто використовувати тільки як основу, коректуючи їх з потреби.

Максимальна кількість "апачів", які можуть бути запущені одночасно, визначається параметромMaxClients. Це число повинне трохи перевищувати максимальну кількість відвідувачів, які можуть в якийсь момент часу опинитися у вас на сайті. У той же час, якщо охочих до вас потрапити багато, а ресурсів сервера для їх обслуговування не вистачає, то зайво високе число запущених серверів тільки загальмує всю роботу. Тому бажано встановити якесь розумне обмеження, скажімо 150 або 200.

Час, протягом якого сервер чекає відгуків від клієнта, визначається параметромTimeout. Обриви зв'язку іноді трапляються, і якщо браузер відвідувача звернувся до вашого сервера, не отримав відповіді і послав повторний запит (скажімо, користувач натиснув reload), то у вас запустяться два "апача", причому один з них буде просто висіти і протягом зазначеного часу чекати, коли відвідувач підтвердить своє бажання подивитися сторіночку. За замовчуванням цей параметр встановлений в 300 секунд, але значно ефективнішим виявилося знизити його до 30.

Включення підтримкиKeepAliveможе помітно полегшити життя. Справа в тому, що в "звичайному" режимі для передачі кожного файлу клієнтові потрібно встановити з'єднання, і якщо у вас на сторіночці, наприклад, є 10 картинок, то доведеться встановлювати і розривати 10 з'єднань для їх передачі. А в режимі KeepAlive сервер після передачі файлу з'єднання не розриває і наступні запити від цього клієнта обробляє, використовуючи вже встановлене з'єднання. Таким чином економиться час на установку і розрив з'єднань, причому для популярних сайтів ця різниця може бути дуже помітна!

Для з'єднань KeepAlive, як і для звичайних, треба встановити timeout за допомогою параметраKeepAliveTimeout. Так як сервер, який встановив з'єднання з клієнтом, недоступний для інших клієнтів до тих пір, поки з'єднання не буде розірвано, занадто велике значення може призвести до появи купи серверів, нічого не роблять і просто чекають, чи не захоче їх клієнт скачати ще що-небудь . Причому в цей же час натовп нових відвідувачів може виявити, що ваш сайт не відповідає, так як досягнуто максимальне число дозволених "апачів" ... Найбільш практичним значенням параметра KeepAliveTimeout є щось між десятьма і двадцятьма секундами.

Як відомо, довгий використання якоїсь програми може призвести до "витокам пам'яті" або якихось інших ресурсів. Щоб уникнути таких проблем, є два параметри:MaxKeepAliveRequestsіMaxRequestsPerChild. Перший параметр відповідає за примусове "убиение" процесу після обробки вказаного числа KeepAlive запитів, а другий - після вказаного числа "звичайних" запитів. В принципі, на абсолютній більшості систем витоків пам'яті бути не повинно, і ці параметри можна зробити досить великими - по кілька тисяч. Але на всяк випадок постежите за поведінкою сервера - не виключено, що "витоку" виявляться в якійсь з бібліотек, які ви використовуєте. Зручніше за все рухатися "знизу вгору" - спочатку встановити значення невеликими, скажімо, 100 і 50, а потім їх збільшувати, спостерігаючи за поведінкою сервера.

Ну, і ще три параметри, які регулюють кількість запущених процесів:StartServers,MinSpareServersіMaxSpareServers. Перший при старті сервера запускає вказане число "апачів". Другий визначає мінімальне число байдикуючих в очікуванні нового клієнта серверів, а третій - їх максимальне число. В якості першого кроку можна спробувати, скажімо, 25, 2 і 10, а далі подивитися на завантаженість сайту ...

Перевірка результатів

Найбільш простим методом швидкої оцінки впливу зроблених вами змін в налаштуваннях є команда top. У верхній частині вікна при її роботі виводиться корисна статистична інформація, приблизно така:
last pid: 40772; load averages: 0.52, 0.50, 0.50 up 23 +17:53:40 9:51:01
233 processes: 1 running, 231 sleeping, 1 zombie
CPU states: 21.2% user, 0.0% nice, 6.4% system, 0.4% interrupt, 72.0% idle
Mem: 367M Active, 239M Inact, 123M Wired, 48M Cache, 112M Buf, 107M Free
Swap: 1024M Total, 13M Used, 1011M Free , 1% Inuse

В першу чергу, треба звертати увагу на load averages - чим вище числа, тим гірше. В ідеалі, в нормальному стані вони не повинні перевищувати одиниці. Наступне, до чого варто придивитися - це використання файлу підкачки. Праворуч від рядка Swap можуть з'являтися повідомлення про записи в swap-файл (Page Out) або про читання з нього (Page In). Чим частіше такі повідомлення з'являються - тим гірше. Дискові операції вже дуже повільні ... Ну і, звичайно, треба стежити за кількістю вільної пам'яті та завантаженням процесора. Втім, якщо ви зумієте домогтися ситуації, коли swap-файл не буде використовуватися, то, швидше за все, все інше швидко прийде в норму ...

Посилання по темі

  • PostgreSQL
  • Apache
  • PHP
  • Маленькі налаштування великого веб-сервера

Статьяполучена: hostinfo.ru

Детальніше »