Administrare server open source

Platforma de hosting cu software liber, gratuit, open source.

Pentru multi internetul fara pagini web e de neconceput. Pentru unii servirea paginilor web fara Apache e de asemenea de neconceput. Putem concluziona ca pentru unii internetul fara Apache e de neconceput ๐Ÿ˜€

Din moment ce Apache, pe buna dreptate, e un server atat de indragit trebuie sa luam in considerare modul in care il putem optimiza pentru a servi paginile cat mai repede si, bineinteles, pentru a face asta fara a fi necesare sume mari de investit in hardware.

Optimizarea, ca in cazul oricarui alt server, inseamna in mare parte eliminarea partilor care nu ne intereseaza si gestiunea cererilor intr-un mod cat mai eficient. Pornind de la aceasta premisa, pentru a optimiza serverul web Apache va trebui sa avem in vedere urmatoarele aspecte:

Lista modulelor necesare

Inainte de a instala Apache e bine sa ne gandim de ce module avem nevoie. Fiecare modul instalat consuma memorie si, de obicei, fiecare modul instalat va face o anumita procesare a informatiei fara ca utilizatorul sa aiba ceva de spus in privinta aceasta. In mod logic daca eliminam modulele de care nu avem nevoie Apache va ocupa mai putina memorie si va avea nevoie de mai putin acces la CPU, resurse care pot fi disponibile pentru alte cereri sau pentru alte servicii care ruleaza pe acelasi server.

Daca instalam Apache din surse va trebui sa rulam comanda ./configure inainte de a compila sursa, moment in care putem specifica modulele care ne intereseaza. De exemplu, daca ne intereseaza mod_rewrite vom rula urmatoarea comanda pentru configurare:

[root@lamp ~/apache/]# ./configure --enable-rewrite=shared

Daca nu ne intereseaza un anumit modul tot ce trebuie sa facem e sa fim atenti la ce includem si sa stergem din parametri comenzii ./configure modulele care nu ne intereseaza. Astfel

Compilarea aplicatiei

Inainte de compilare putem seta cateva optiuni care vor determina modul in care Apache se va comporta in timpul compilarii si dupa aceea. Un exemplu foarte bun pentru modul in care compilarea serverului Apache poate influenta randamentul este includerea modulelor. Exista module – cum ar fi actions, alias, deflate, expires etc. – care sunt necesare in procesarea fiecarei cereri deci e nevoie ca acestea sa fie prezente in memorie. Altele – cum ar fi status, info, auth_basic etc. – sunt necesare doar in anumite situatii si nu are sens sa fie prezente tot timpul in memorie.

Bazandu-ne pe acest criteriu, modulele care le consideram importante le putem include direct in binarul Apache folosind compilarea statica. Un modul compilat static va fi intotdeauna mai rapid decat un modul dinamic si vor creste considerabil sansele ca zona de memorie in care e prezent acesta sa fie inclus in cacheul sistemului pentru ca incarcarea sa fie mai rapida si ne va asigura ca aplicatia va continua sa functioneze corect chiar daca modificam sau stergem o anumita librarie de care aceasta depinde. De asemenea modulele compilate static ne ofera un plus de securitate pentru ca nu exista riscul ca vreun modul sa fie inlocuit cu un cod malitios.

Dezavantajul modulelor compilate in mod static e ca pentru eliminarea lor sau pentru adaugarea altor module e necesara recompilarea intregii aplicatii.

Pentru a compila in mod static un modul vom specifica la pasul de configurare, ca parametrul al comenzii ./configure, si –enable-static-support pentru ca Apache sa fie compilat cu suport pentru module statice si pentru a include in binarul final toate librariile necesare.

Pentru ca un modul sa fie compilat static vom folosi sintaxa obisnuita cu mentiunea ca in loc de shared vom scrie static:

[root@lamp ~/apache/]# ./configure --enable-rewrite=static

Chiar daca nu influenteaza in mod direct rularea serverului web, putem determina compilarea statica si pentru utilitarele care vin odata cu Apachehtpasswd, ab, logresolve etc. – care vor rula mai usor pentru ca toate librariile necesare vor fi incluse in binarul rezultat si nu va fi necesara incarcarea dinamica a acestora. Pentru compilarea statica a utilitarelor vom folosi pentru ./configure parametri –enable-static-ab, –enable-static-checkgid, –enable-static-htpasswd, –enable-static-logresolve, –enable-static-rotatelogs.

Tot la capitolul compilare am putea folosi diferiti parametri pentru compilator. Parametri care dorim sa ii pasam trebuie inclusi in variabila de mediu CFLAGS. Un exemplu ar fi urmatorul:

[root@lamp ~/apache/]# CFLAGS="-O2 -pipe -funroll-loops -mmmx -msse -msse2 -mno-sse3 -mfpmath=sse -fno-strict-aliasing -march=pentium4"
[root@lamp ~/apache/]# ./configure ...

Modulul de procesare a cererilor

In Apache exista un modul, MPM, care determina modul in care cererile vor fi procesate. Cele mai folosite sunt worker si prefork iar alegerea se face in functie de limbajul folosit in aplicatiile web si de modul in care dorim sa izolam scripturile. Diferenta majora dintre cele doua e ca pentru fiecare cerere prefork va folosi o instanta noua a serverului web iar worker va folosi un thread nou. Daca limbajul folosit pentru dezvoltarea siteurilor nu este thread-safe, vom folosi prefork pentru ca acesta izoleaza foarte bine fiecare cerere in parte. Daca limbajul nu apre probleme cu threadurile putem folosi worker.

Din punct de vedere al randamentului, folosind un limbaj thread-safe, putem considera worker ca fiind net superior modulului prefork datorita abordarii. Un thread nou se deschide mai repede si nu consuma la fel de multa memorie cum e in cazul unei instante noi a intregii aplicatii. Cu un consum mai mic de memorie, randamentul worker va ajunge usor la peste 300% raportat la prefork.

Daca optam pentru prefork, pentru a optimiza resursele puse la dispozitie si pentru a evita supraincarcarea serverului vom putea folosi urmatori parametri:

<ifmodule mpm_prefork_module>
    StartServers          5
    MinSpareServers       5
    MaxSpareServers      10
    MaxClients          150
    MaxRequestsPerChild   0
</ifmodule>

Directivele au urmatoarea semnificatie:

  • StartServers – numarul de instante ale serverului web deschise la pornirea acestuia;
  • MinSpareServers – numarul minim de instante libere care asteapta sa serveasca cereri noi;
  • MaxSpareServers – numarul maxim de instante libere care vor fi pastrate active;
  • MaxClients – numarul maxim de cereri concurente;
  • MaxRequestsPerChild – numarul maxim de cereri care le va servi o instanta a serverului web inainte de a fi inchisa (0=infinit).

Daca optam pentru worker abordarea e putin diferita pentru ca vom impune limite la nivel de thread. Un exemplu de inceput ar fi folosirea urmatorilor parametri:

<ifmodule mpm_worker_module>
    StartServers          2
    MaxClients          150
    MinSpareThreads      25
    MaxSpareThreads      75
    ThreadsPerChild      25
    MaxRequestsPerChild   0
</ifmodule>
  • StartServers – numarul de instante ale serverului web (nu threaduri) deschise la pornirea acestuia;
  • MaxClients – numarul maxim de cereri concurente – suma totala a threadurilor din fiecare instanta a serverului;
  • MinSpareThreads – numarul minim de threaduri libere in asteptare de cereri noi;
  • MaxSpareThreads – numarul maxim de threaduri libere care vor fi pastrate active;
  • ThreadsPerChild – numarul maxim de threaduri acceptate pe fiecare instanta a serverului web, numar peste care se va deschide o instanta noua;
  • MaxRequestsPerChild – numarul maxim de cereri care le va servi o instanta a serverului web inainte de a fi inchisa (0=infinit).

Recomandarea ar fi ca oridecate ori aveti nevoie de Apache, puneti worker daca vi se permite. Solutii se gasesc de obicei si pentru limbajele care nu sunt thread-safe. De exemplu, pentru PHP se poate inlocui mod_php cu mod_fcgid care va determina PHP sa ruleze in mod CGI si implicit va izola scriptul de restul proceselor ceea ce il va face thread-safe la nivel de server ceea ce in majoritatea cazurilor se considera ca fiind acceptabil.

Accesarea resurselor

In mod normal pentru a servi un fisier Apache citeste bucati din fisierul cerut care sunt salvate intr-un buffer pentru a fi trimise clientului. Daca sistemul de operare suporta, putem configura Apache sa foloseasca sendfile() pentru servirea continutului static. Folosind sendfile() Apache trimite fisierul in cauza fara a crea un buffer si fara a face doua operatii, citire si scriere, care sunt preluate de sistemul de operare. Activarea sendfile() se face adaugand in fisierul httpd.conf urmatoarea linie:

EnableSendfile On

Pentru a servi parti dintr-un fisier sau in situatiile in care Apache trebuie sa citeasca alte fisiere pentru a procesa un script complex se poate folosi maparea memoriei, care va aduce un plus de randament pentru ca odata ce schema de citire a fisierelor este creata datele se preiau mult mai rapid. Dezavantajul este ca pe unele sisteme de operare maparea nu functioneaza corect sau poate da erori in situatii mai putin intalnite – ex. cand se incearca maparea unui fisier care isi modifica tot timpul continutul. In general e bine sa activati maparea memoriei o perioada si sa vedeti daca va ajuta sau nu. In unele situatii, in mod deosebit in cazul aplicatiilor simple, poate creste considerabil randamentul oferit. Activarea se face adaugand in fisierul httpd.conf urmatoarea linie:

EnableMMAP On

Unele sisteme de operare, cum ar fi FreeBSD, ofera module care permit optimizarea traficului pe un anumit protocol. Filtrele pentru FreeBSD sunt dataready si httpdataready si pot fi activate folosind directiva AcceptFilter adaugand in httpd.conf urmatoarele doua linii:

AcceptFilter http httpready
AcceptFilter https dataready

E important ca inainte de restartarea serverului web sa incarcam modulele aferente in sistemul de operare:

[root@lamp ~]# kldload accf_data.ko
[root@lamp ~]# kldload accf_http.ko

Procesarile secundare

In Apache exista un set de facilitati care sunt utile doar in situatii izolate, facilitati care sunt inutile in utilizarea curenta si care e bine sa fie eliminate.

FileETag creaza un sir de identificare pentru fiecare resursa statica, sir care este folosit pentru ca browserul sa stie daca fisierul a fost modificat de la ultima accesare sau nu. In anumite contexte este o facilitate utila, dar daca folosim mod_expires si mod_headers putem determina browserul sa faca un cache local pentru o perioada determinata, solutie care este de preferat datorita eliminarii operatiilor I/O necesarii calcularii codului ETag la fiecare cerere. Pentru a elimina aceasta facilitate adaugam in httpd.conf urmatoarea linie:

FileETag None

ServerSignature e directiva cu ajutorul careia putem determina serverul web sa isi prezinte detaliile in cadrul headerelor sau nu. Aceasta informatie e de obicei inutila pentru client, deci putem dezactiva aceasta facilitate adaugand in httpd.conf urmatoarea linie:

ServerSignature Off

Daca nu putem elimina ServerSignature e bine totusi sa oferim cat mai putine informatii. Folosind directiva ServerTokens putem spune serverului Apache cat sa dezvaluie din identitatea proprie adaugand in httpd.conf urmatoarea linie:

ServerTokens ProductOnly

TRACE este un tip de cerere trimisa serverului web, ca in cazul GET sau POST, cu mentiunea ca nu e folosita decat in cazuri izolate de care nu va loviti decat foarte rar. Acest tip de cerere e bine sa fie blocat pe de-o parte pentru a mai salva cateva resurse iar pe de alta parte pentru a evita unele probleme care pot sa apara datorita scanerelor de vulnerabilitati. TRACE se poate dezactiva folosind directiva TraceEnable dupa cum urmeaza:

TraceEnable off

Folosind HostnameLookups putem determina serverul web sa nu rezolve IP-ul vizitatorului intr-un hostname, operatiune care necesita foarte multe resurse si implica un delay mare datorat operatiilor I/O. Putem suprima rezolvarea IP-urilor in hostname adaugand in httpd.conf urmatoarea linie:

HostnameLookups off

Mentinerea conexiunii

Crearea unei instante noi, indiferent daca e vorba de un thread sau un child-server, este o operatie costisitoare. Ca sa scadem drastic consumul de CPU e bine sa activam pastrarea proceselor prin functionalitatea KeepAlive. Daca avem KeepAlive, instanta care serveste o anumita cerere nu va fi inchisa decat dupa ce va servi numarul maxim de cereri permise sau daca trece o anumita perioada fara ca din partea clientului sa vina o cerere noua. Astfel pentru fiecare vizitator se va deschide un numar minim de instante care vor servi resursele cerute, ceea ce va duce la o scadere mare a consumului de resurse cerute.

Pentru a activa KeepAlive vom adauga in httpd.conf urmatoarele linii:

KeepAlive On
KeepAliveTimeout 5
MaxKeepAliveRequests 100

Cele trei directive au urmatoarele semnificatii:

  • KeepAlive – activeaza sau dezactiveaza functionalitatea si poate lua ca valori On sau Off;
  • KeepAliveTimeout – reprezinta timpul in secunde dupa care instanta va fi inchisa daca nu primeste o cerere noua;
  • KeepAliveRequests – reprezinta numarul maxim de cereri keep-alive care le poate servi o instanta.

Limitarea consumului de resurse

In anumite situatii consumul de resurse al unui script poate fi scapat de sub control. Pentru astfel de situatii putem folosi RLimitCPU si RLimitMEM pentru a limita timpul maxim de executie respectiv consumul maxim de memorie. Cele doua limite se pot impune adaugand in fisierul httpd.conf urmatoarele doua linii:

RLimitCPU 60
RLimitMEM 33554432

Valoarea pentru RLimitCPU e exprimata in secunde iar cea pentru RLimitMEM in bytes. Ambele valori se refera la instanta de procesare deschisa pentru o cerere si nu afecteaza in mod direct consumul general de memorie sau CPU a serverului web.

Identificarea utilizatorilor

In cazul serverelor pe care sunt gazduite mai multe siteuri, fiecare site pe contul propriu, este bine sa identificam procesele dupa utilizator datorita facilitatilor care vin odata cu aceasta identificare – limitari din sistemul de operare, identificare rapida a spamerilor etc. Pentru asta putem folosi suEXEC, o facilitate Apache asemanatoare utilitarelor su si sudo din Linux. In cadrul directivei VirtualHost putem folosi directiva SuexecUserGroup pentru a mentiona utilizatorul si grupul sub care vom rula scripturile corespunzatoare dupa cum urmeaza:

SuexecUserGroup lamp www

Trebuie retinut ca suEXEC functioneaza doar pentru CGI si FastCGI. Daca dorim sa folosim suEXEC pentru PHP va trebui sa il configuram sa ruleze in mod FastCGI. PHP rulat ca DSO cu mod_php va fi interpretat ca nobody, indiferent de directiva SuexecUserGroup.

Pentru a folosi suEXEC trebuie sa il activam in timpul compilarii pasand parametri potriviti pentru ./configure:

  • –enable-suexec – activeaza suEXEC;
  • –with-suexec-caller=UID – mentioneaza UID-ul implicit pentru serverul web (de obicei 80);
  • –with-suexec-userdir=DIR – mentioneaza subdirectorul userului in care suEXEC va fi activ (de obicei public_html);
  • –with-suexec-docroot=DIR – directorul in care trebuie sa se gaseasca directoarele si subdirectoarele utilizatorilor pentru a se folosi de suEXEC (de obicei /home);
  • –with-suexec-uidmin=UID – cel mai mic UID al unui utilizator pentru a se folosi suEXEC;
  • –with-suexec-gidmin=GID – cel mai mic GID al unui utilizator pentru a se folosi suEXEC;
  • –with-suexec-logfile=FISIER – fisierul in care se va salva logul utilizarii suEXEC;

E bine de avut in vedere ca odata ce se activeaza suEXEC, scriptul va avea permisiunile utilizatorul respectiv. Adica, scriptul va avea drept de scriere in toate directoarele care au ca proprietar userul in cauza chiar daca permisiunile nu sunt 777 cum e in cazul rularii PHP ca DSO.

Monitorizarea serverului web

Daca ne intereseaza starea serverului va trebui sa activam modulele info si status care ne ofera in timp real informatii despre numarul de procese deschise, inregistrarile VirtualHost in cadrul carora se proceseaza cereri, numarul de threaduri libere etc.

Pentru a ne folosi de aceasta facilitate va trebui sa adaugam in httpd.conf urmatoarele linii:

ExtendedStatus On
 
<location /server-status>
    SetHandler server-status
    Order deny,allow
    Deny from all
    Allow from 127.0.0.1
</location>
 
<location /server-info>
    SetHandler server-info
    Order deny,allow
    Deny from all
    Allow from 127.0.0.1
</location>

Statusul serverului va fi verificat in mod implicit pe IP-ul principal urmat de una din cele doua locatii – ex. http://127.0.0.1/server-status.

Optimizarea generala a serverului poate fi extinsa prin diferite module si poate fi personalizata pentru fiecare caz in parte, dar indiferent de limbajul care predomina in aplicatiile de pe un server web pasii de mai sus se mentin si pot fi intotdeauna considerati ca puncte de pornire in optimizare cand observati ca serverul incepe sa se miste greu.

Apache

8 Responses so far.

  1. vim says:

    Entity tags sunt mult mai flexibile decat headerele last-modified, de exemplu la forum-uri. La setarea unui header de expirare a unei resurse, aceea resursa nu va mai fi actualizata pana cand nu trece timpul setat ; daca in decursul acestei perioade, respectiva resursa a fost modificata, clientului ii va fi afisat tot versiunea din cache si nu cea actualizata a resursei.

    Cu entity tags este mai flexibil, pentru ca la modificarea resursei, este modificat si tag-ul, iar browser-ul va sti ca este necesar sa descarce din nou aceea resursa.

    Oricum, este mult de discutat pe marginea acestui subiect si nu este nimic general valabil.

    Bun articol. Keep up!

  2. Sergiu Tot says:

    Salut si merci de apreciere!

    Da, FileETag iti ofera multa flexibilitate, dar la implementare depinde de fiecare situatie in parte. Eu obisnuiesc sa fac modificari offline iar apoi sa le uploadez, deci informatia care e urcata pe site e pusa acolo sa stea pentru o perioada indelungata. In cazul asta cel mai bine e sa folosesc mod_headers si mod_expires. Scutesc sistemul de cateva operatii I/O care, in cazul siteurilor cu trafic mare, sunt simtite.

    Pe de alta parte, dupa cum spuneai, exista situatii in care e de preferat verificarea cu FileETag. Daca dezvoltarea siteului se face pe versiunea din productie, cum e cazul siteurilor mici, sau daca e vorba de un server folosit pentru dezvoltare cacheul local nu face altceva decat sa incurce ๐Ÿ™‚

    In general cand vine vorba de optimizare fiecare aspect trebuie judecat dupa situatia data. E greu sa facem afirmatii universal valabile pentru ca in cazul asta nu s-ar mai chema optimizare ๐Ÿ˜›

  3. Joculete Online says:

    Brovo pentru tutorial dar tin sa fac o specificatie pentru persoanele corora nu le place sa foloseasca Apache si in acela-si timp sa recomand o aplicatie mai simpla pentru pesoanele care lucreaza pe localhost. Este vorba despre programul EasyPhp care vine cu toate necesitatile instalate iar instalarea lui este foarte simpla precum si usurinta de lucrare cu el.

  4. vim says:

    @Joculete Online: Si pachetul EasyPHP ce server web are inclus in el ?
    Asta a fost un comentariu doar pentru link ?

  5. Gazduire Web says:

    Multumesc pentru articol si pentru link-ul din nume. ๐Ÿ™‚

  6. mihai says:

    sectiunea „Modulul de procesare a cererilor” tot in httpd.conf se pun?

  7. mihai says:

    este posibil ca serverul apache sa se restarteze atunci cand este atinsa o limita de incarcare a procesorului sau a memoriei? spre ex daca serverul ajunge sa consume 6g din cei 8 pe care-i are computerul serverul sa se reseteze.

  8. Sergiu Tot says:

    Mihai, scuze de raspunsul intarziat. Da, tot in httpd.conf se adauga/modifica directivele din „Modulul de procesare a cererilor”.

    Cand se depasesc resursele nu se reseteaza serverul. Se opreste. Dar e posibil sa se reporneasca daca folosesti cPanel sau un sistem asemanator care monitorizeaza serviciile si le reporneste.