C, PHP, VB, .NET

Дневникът на Филип Петров


* Оптимизиране на Apache

Публикувано на 14 април 2009 в раздел ОСУП.

Apache е най-популярният http сървър в интернет. Както всеки сървър той също има специфични настройки, които могат значително да повишат производителността на системата. Много от тях са особено важни и за сигурността – например при справянето с DoS атаки.

Файлът за настройки на Apache е с име httpd.conf. Понякога този файл зарежда свои дъщерни (httpd-vhosts.com, httpd-aliases.conf, и т.н.). Обикновено специфичните настройки за оптимизация на сървъра се слагат във файл httpd-default.conf. Подобно на настройките за MySQL, за които споменахме по-рано, и тук всичко се променя изключително лесно с проста промяна на стойност:

1. HostnameLookups Off

Ако HostnameLookups е включен, то за всеки един „hit“ към сървъра се прави DNS lookup, за да се транслира IP адреса на клиента в hostname. Казано по-правилно – всеки път се прави reverse dns lookup. Понякога това е полезно за по-голяма четимост на логовете. На практика обаче това най-вероятно не ви трябва. Често администраторите правят въпросния DNS lookup впоследствие, чрез софтуер за преглеждане на log файлове. Разликата в бързодействието на сървъра, особено при много натоварени машини, е значително в негативна посока ако тази опция е включена.

2. ServerSignature Off

Когато клиента попадне на някоя от стандартните страници на Apache (directory listing, 404, 401, и т.н.), обикновено сървъра изписва името и версията си най-отдолу. Едва ли искаме да даваме тази информация на който и да е. Въпреки, че въобще не е трудно да се познае, че сървъра е Apache, въобще няма нужда да даваме информация за конкретната версия.

3. ServerTokens Prod

Същото, което казахме за ServerSignature важи и за всеки HTTP header, който се изпраща към клиента. Ако тази стойност е FULL се дава информация дори за операционната система. Prod е възможно най-минималната информация за системата, която е нужна, за да може да се функционира нормално.

4. KeepAlive On

Обикновено на една HTML страница има свързани редица обекти (javascript файлове, картинки, флаш анимации, и т.н.). Ако KeepAlive е изключено, за всеки един файл ще бъде правена нова връзка към сървъра. Това естествено води до забавено бързодействие. При натоварени сървъри е задължително да бъде включен KeepAlive – така клиентът изтегля повече от един файл с една връзка.

5. KeepAliveTimeout 3

Колкото и да помага, KeepAlive естествено си има и своите минуси. Най-големия е, че може клиенти да отварят връзки и да не ги приключват. Това се случва често при DoS атаки. Затова е нужен таймер за затваряне на връзката – това се явява KeepAliveTimeout. Стойността 3 секунди е приемлива за съвременните интернет връзки. Въпреки това при клиенти, които имат бавна връзка и са прекалено много отдалечени от сървъра би се получило така, че връзката ще се затвори преди да успеят да направят следваща заявка за файл.

6. MaxKeepAliveRequests 100

Максимална стойност за поискани файлове с една връзка. Например ако имате html страница с 100 снимки, клиентът трябва да свали 101 файла (1 html + 100 jpg), т.е. при „MaxKeepAliveRequests 100“ ще са му нужни две връзки.

7. MaxClients 800

Когато се свърже към сървъра, за него се стартира работен процес. Всеки един от тях обработва по няколко клиентски заявки, след което се изключва. Ако имате много клиенти едновременно е добре да увеличите тази стойност. Тя контролира максималният брой процеси, които се стартират. Добра формула е следната:

RAM памет отделена за Apache = MaxClients * Max child process size.

Във версия 2.4 променливите за настройка са две:

ServerLimit 800
MaxRequestWorkers 800

Там MaxClients е deprecated и е синоним на MaxRequestWorkers.

8. StartServers 10

Тази опция дефинира колко процеса да бъдат стартирани първоначално.

9. MinSpareServers 10

Колко да бъдат максимално свободните процеси (т.е. такива, които не обработват клиентски заявки, а чакат). Добре е да пазим поне 5. Стремежът ни все пак е да не се стартират повече от 4 Apache процеса за една секунда – ако това стане, е добре да увеличаваме тази стойност.

10. MaxSpareServers 30

От друга страна не е добре да имаме прекалено много свободни процеси. Добре е да ги затворим и да дадем оперативна памет на други програми.

11. MinSpareThreads 25

Минималното количество от обработващи нишки, за всеки свободен процес.

12. ThreadsPerChild 25

Константно количество нишки за всеки процес

13. MaxRequestsPerChild 8000

По подразбиране стойността е 0, т.е. „безкрайност“. Важно е обаче да сложим такъв лимит за дъщерните процеси. Ако имаме „утечка на памет“ (memory leak), при достигане на MaxRequestsPerChild тя ще бъде „пресечена“.

14. Timeout 60

Максималното време, което Apache ще отдели за една връзка към него (в секунди). Например при качване на много голям файл през POST показаното в примера може да не е достатъчно. Стойността по подразбиране е 300.

Освен изброените по-горе стандартни настройки, има и редица допълнителни модули за Apache, които са изключително важни. Такива са например mod_deflate (отговорен за компресирането на данни), mod_cache (за кеширане на данни), mod_expires и mod_headers (за кеширане на HTTP headers). Повечето от полезните модули са включени в стандартната инсталация.

Има обаче един модул, на който искаме да обърнем специално внимание – това е известният mod_dosevasive. Чрез него можете да блокирате заявки от дадени клиенти за определено време. Например при flood от едно IP вие не бихте искали всеки път да бъде компилиран PHP файл. Чрез mod_dosevasive модула можете да укажете например, че ако от даден IP адрес се получат повече от 20 заявки за една секунда, да бъде блокиран достъпа му за определено време (например 5-6 секунди). По принцип стойността се слага така, че сървъра да може да обслужи най-голямата си страница за една секунда, без клиента да бъде блокиран. Затова от примера по-горе, при html страница с 100 картинки, бихме сложили стойност на mod_dosevasive над 100. Този модул има изключително положителен ефект при DoS атаки!

Друг много известен модул свързан със сигурността е mod_security. Той действа като firewall за Apache, като следи за известни атаки или съмнителна активност на даден клиент. Силно препоръчваме включването на този модул въпреки, че по принцип намалява бързодействието на сървъра в нормална ситуация (без атака срещу него).

Добавено април 2017 г.

С добавянето на HTTP2 (например чрез nghttp2) се дава една допълнителна възможност за разработчиците на уебсайтове – server push технологията. Ако например имате сайт, във всяка страница на който се зарежда един CSS файл и два JavaScript файла, стандартно вашия браузър ще извърши 4 заявки. Първо ще се зареди html страницата, ще се изчака парсването на нейния код, след което браузъра ще „види“ допълнително нужните файлове и ще направи три паралелни заявки за тях. С HTTP2 и push технологията вие може да изпратите css и javascript файловете директно още с първата заявка. Спестеното време в общи линии е минимално (имайки предвид, че за допълнителните файлове не се прави DNS lookup), но все пак повишение на скоростта винаги ще има – не се чака парсването на файла и не се прави threeway handshake на tcp/ip връзките.

Пускането на server push се извършва чрез изпращане на допълнителен хедър. Това най-лесно става с .htaccess файл по следния начин:

Header add Link "</css/styles.css>; rel=preload; as=style"
Header add Link "</js/script1.js>; rel=preload; as=script"
Header add Link "</js/script2.js>; rel=preload; as=script"

Разбира се може да го правите и динамично чрез php script. Например може да изпратите всички снимки от една фотогалерия накуп. Ето как може да направите push на отделна снимка:

header("Link: /images/image1.jpg; rel=preload; as=image", false);

Параметърът „false“ указва да не се презаписва съществуващ Link хедър, а да се добави като нов. Тоест така може да извикате функцията многократно и да направите push на множество файлове. Единственото, за което трябва да внимавате, е да не изпращате файлове, които няма да се използват при визуализирането на страницата.

Имайте предвид, че server push НЕ елиминира кеша на браузъра. Ако браузъра вече е изтеглил даден файл с предишна заявка, той ще пропусне изтеглянето му дори да е получил push хедър за него (има такава възможност за отмяна на push от страна на клиента като част от протокола). Все пак е възможно да имплементирате схема, с която да следите на кой клиент вече е правена push заявката и според това да пропускате изпращането на допълнителни и ненужни push хедъри. Това най-лесно се получава чрез записване на индикация, че вече е правен push, в browser cookie. Можете да сложите expiration на това cookie точно толкова дълъг, колкото е дълъг и expire хедъра на съответния файл.

 



5 коментара


  1. Bakudan каза:

    Много полезно материалче. Можеш ли да споделиш нещо за nginx, ако си се срещал с него. Забелязах че някой уеб базирани игри и сайтове с найстина много посетители го ползват.

  2. nginx доколкото си спомням го водеха за „най-лекия HTTP сървър“. Най-често съм го виждал в действие в комбинация с Apache – администраторите прехвърлят всички заявки към статични HTML страници към nginx, а всички динамични страници (php) към Apache (т.е. nginx поема заявките и ако е php предава напред към apache, иначе изпълнява).

    С развитието на технологиите обаче тази практика според мен ще отмре. Кога за последно си влизал в чист html сайт? :)

  3. drJeckyll каза:

    това което си написал е верно ако имаше и пред двата (nginx и apache) нещо друго което да прехвърля заявките (като например някое reverse proxy – squiq, varnish…, или пък load balancer) … в повечето случаи се прави просто web сървър за статични обекти (не само html е статичен, всяка картинка, js, css и т.н. също са статични) който да прехвърля заявките към динамичните страници към fast-cgi сървър или както казваш към apache … от друга страна nginx и lighttpd имат механизми за load balance на заявките към динамичните backend-и така, че всички зависи какво натоварване трябва да се понесе :)

  4. Bakudan каза:

    Не знам как стоят точно нещата, но travian-ите, всичките са с nginx. И както писа Jeckyll само картинките, js и css са статични

  5. Аз нямам нищо против – конкуренцията е нещо много полезно :)

Добави коментар

Адресът на електронната поща няма да се публикува


*