Neste post vou exemplificar os passos para configurar um Webserver que consome poucos recursos e é extremamente rápido no Debian Lenny.
PHP-FPM: é um gerenciador de processos CGI do php, similar ao Phpcgi, porém com várias vantagens como:
- Gerenciador de Processos muito eficiente, com capacidade de parar e iniciar seus deamons caso necessário
- Possibilidade de Iniciar processos com usuários diferentes e com arquivos php.ini diferentes
- Uploads otimizados
- Capacidade de reinicializar processos caso ocorra algum problema
- Escalabilidade de processos, ele pode criar mais processos de acordo com a demanda
- e muito mais.
XCache: é um gerenciador de cache, que armazena os scripts php em opcode para uso futuro, é extremamente rápido e muito usado no mundo em servidores com alta demanda.
Nginx: Conheci este webserver lendo o blog da boo-box, ele é um Servidor web e proxy reverso extremamente veloz e que vem ganhando mercado nos últimos meses devido a sua facilidade de uso e capacidade de carga.
Para agilizar a configuração, vamos usar alguns pacotes (php5.3, php-fpm) pré compilados e mantidos www.dotdeb.org. os testes que eu realzei usando estes pacotes tiveram um ganho de performance enorme.
Instalação:
Vamos começar adicionado os repositórios do dotdeb no /etc/apt/sources.list:
deb http://php53.dotdeb.org stable all deb-src http://php53.dotdeb.org stable all
Vamos instalar os pacotes e algumas dependências para o nginx:
aptitude update aptitude install php5-fpm php5-xcache php5-gd php5-curl \ php5-mysql php5-pgsql libssl-dev libpcre3-dev build-essential -y
Agora temos o php instalado, vamos compilar o nginx:
cd mkdir src cd src wget http://nginx.org/download/nginx-0.7.64.tar.gz tar -zxvf nginx-0.7.64.tar.gz cd nginx-0.7.64 ./configure --prefix=/usr/local/nginx --user=www-data --group=www-data \ --without-mail_pop3_module --without-mail_imap_module \ --without-mail_smtp_module --with-http_stub_status_module \ --with-http_ssl_module --http-log-path=/var/log/nginx/access.log \ --conf-path=/etc/nginx/nginx.conf --pid-path=/var/run/nginx.pid make make install
Se tudo ocorreu bem, você já tem o nginx instalado, vamos apenas coloca-lo para inicializar automáticamente, crie o arquivo /etc/init.d/nginx e coloque o conteúdo:
#! /bin/sh ### BEGIN INIT INFO # Provides: nginx # Required-Start: $all # Required-Stop: $all # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: starts the nginx web server # Description: starts nginx using start-stop-daemon ### END INIT INFO PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local DAEMON=/usr/local/nginx/sbin/nginx NAME=nginx DESC=nginx test -x $DAEMON || exit 0 # Include nginx defaults if available if [ -f /etc/default/nginx ] ; then . /etc/default/nginx fi set -e case "$1" in start) echo -n "Starting $DESC: " start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \ --exec $DAEMON -- $DAEMON_OPTS || true echo "$NAME." ;; stop) echo -n "Stopping $DESC: " start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid \ --exec $DAEMON || true echo "$NAME." ;; restart|force-reload) echo -n "Restarting $DESC: " start-stop-daemon --stop --quiet --pidfile \ /var/run/$NAME.pid --exec $DAEMON || true sleep 1 start-stop-daemon --start --quiet --pidfile \ /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS || true echo "$NAME." ;; reload) echo -n "Reloading $DESC configuration: " start-stop-daemon --stop --signal HUP --quiet --pidfile /var/run/$NAME.pid \ --exec $DAEMON || true echo "$NAME." ;; configtest) echo -n "Testing $DESC configuration: " if nginx -t > /dev/null >&1 then echo "$NAME." else exit $? fi ;; *) echo "Usage: $NAME {start|stop|restart|reload|force-reload|configtest}" >&2 exit 1 ;; esac exit 0
depois vamos torna-lo executável e atualizar o rc.d:
chmod +x /etc/init.d/nginx update-rc.d nginx defaults
Com isso o processo de instalação está concluído, vamos configurar!
Configuração do XCache
Coloque a seguinte configuração no arquivo /etc/php5/fpm/conf.d/xcache.ini:
; configuration for php xcache module extension=xcache.so [xcache.admin] xcache.admin.user = "secom" ; xcache.admin.pass = md5($your_password) xcache.admin.pass = "" [xcache] ; ini only settings, all the values here is default unless explained ; select low level shm/allocator scheme implemenation xcache.shm_scheme = "mmap" ; to disable: xcache.size=0 ; to enable : xcache.size=64M etc (any size > 0) and your system mmap allows xcache.size = 64M ; set to cpu count (cat /proc/cpuinfo |grep -c processor) xcache.count = 1 ; just a hash hints, you can always store count(items) > slots xcache.slots = 8K ; ttl of the cache item, 0=forever xcache.ttl = 0 ; interval of gc scanning expired items, 0=no scan, other values is in seconds xcache.gc_interval = 0 ; same as aboves but for variable cache xcache.var_size = 64M xcache.var_count = 1 xcache.var_slots = 8K ; default ttl xcache.var_ttl = 0 xcache.var_maxttl = 0 xcache.var_gc_interval = 300 xcache.test = Off ; N/A for /dev/zero xcache.readonly_protection = Off ; for *nix, xcache.mmap_path is a file path, not directory. ; Use something like "/tmp/xcache" if you want to turn on ReadonlyProtection ; 2 group of php won't share the same /tmp/xcache ; for win32, xcache.mmap_path=anonymous map name, not file path xcache.mmap_path = "/dev/zero" ; leave it blank(disabled) or "/tmp/phpcore/" ; make sure it's writable by php (without checking open_basedir) xcache.coredump_directory = "" ; per request settings xcache.cacher = On xcache.stat = On xcache.optimizer = On [xcache.coverager] ; per request settings ; enable coverage data collecting for xcache.coveragedump_directory and xcache_coverager_start/stop/get/clean() functions (will hurt executing performance) xcache.coverager = Off ; ini only settings ; make sure it's readable (care open_basedir) by coverage viewer script ; requires xcache.coverager=On xcache.coveragedump_directory = ""
Configuração do Nginx
Edite o arquivo em /etc/nginx/nginx.conf:
user www-data; #Coloque quantos processos simultaneos, o ideal é um para cada nucleo do sistema: worker_processes 4; error_log /var/log/nginx/error.log; events { # numero de conexões simultaneas por worker worker_connections 1024; } http { include mime.types; default_type application/octet-stream; access_log /var/log/nginx/access.log; sendfile on; # isso é interessante, dá um ganho enorme na navegação, e o nginx aguenta tranquilamente keepalive_timeout 60; tcp_nodelay on; ## Compressão gzip on; gzip_http_version 1.0; gzip_comp_level 2; gzip_proxied any; gzip_min_length 1100; gzip_buffers 16 8k; # mime types para zipar e adicionar header de cache gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript image/gif image/jpeg image/png; # Desabilita compressão em algumas versões do IE6 gzip_disable "MSIE [1-6].(?!.*SV1)"; # Impede que servidores proxy mandem versões em gzip do arquivo para os IE6 gzip_vary on; server { root /var/www/; server_name localhost; listen 80; location / { index index.php index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html error_page 500 502 503 504 /50x.html; location = /50x.html { root /var/www/nginx-default; } # Joga requisições para arquivos .php para o php-fpm location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME /var/www/$fastcgi_script_name; fastcgi_param SERVER_NAME $http_host; fastcgi_ignore_client_abort on; } } }
Configuração do php-fpm
Edite o arquivo: /etc/php5/fpm/php5-fpm.conf e faça os ajustes que você achar interessante, aqui eu só aumento os max_childrens (Numero de clientes CGI) de 5 para 50, esta configuração depende do seu hardware.
Configuração do Logrotate
Vamos configurar agora o logrotate para não enchermos os discos com logs do nginx, edite o arquivo /etc/logrotate.d/nginx:
/var/log/nginx/*.log { daily missingok rotate 7 compress delaycompress notifempty create 640 root adm sharedscripts postrotate [ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.p$ endscript }
Finalizando
Agora que está tudo configurado, vamos reinicalizar os serviços:
/etc/init.d/php5-fpm restart /etc/init.d/nginx restart
crie um arquivo /var/www/index.php e vamos testar o php:
e acesse: http://ip_do_servidor/

Fala ai Carlos,
você fez alguma comparação de performance entre as soluções padrões (like, apache+php)?
Tem algum gráfico de performance ou algum “vmstat 1″ p/ analisarmos?
Mas foi uma ótima dica ! Obrigado!
Também gostei do passo-a-passo. Porém faltou um comparativo como o Erick citou.
Se der tempo vou testar essa solução em breve.
Estou meio “viciado” em otimização de perfomance em servidores web. Ultimamente tudo que vejo sobre o assunto estou lendo e pesquisando.
Obrigado pela contribuição
Olá,
kra, não fiz nenhum teste localmente, mas pesquisei vários no google e por isso decidi implementar…
o que posso dizer, eh que nosso servidor (Do governo do Tocantins) é um Pentium 4, com 1gb de memória… com o apache ele começava a engasgar com 200 conexões… com o nginx já passou de 1000 conexões! e o uso da maquina não passa de 5%
fiz até um post sobre isso: http://ferrari.eti.br/nginx-webserver-proxy-reverso-e-perfeito/ dá uma conferida
Dá uma navegada nos sites:
http://to.gov.br
[]‘s
Salve,
É Carlos só falta um comparativo entre apache2+php e nginx+php. Com configurações “iguais”, se otimiza em 1, faz o mesmo no outro.
Está bem legal o artigo, valeu pela dica.
Thanks you very much for this tutorial, i was stopped by php-fpm install to make a full great install ! (only install nginx with fastCGI)
olá Carlos. excelente post e blog também !
pergunta básica: nada contra a distro Debian, muito pelo contrário, mas como tenho mais contato com Ubuntu, como você vê a possibilidade de implementação desta configuração em um servidor Ubuntu ?
@Henrique Dias
No Ubuntu não vai mudar muita coisa, aliás, acho que não muda nada visto que a base do Ubuntu é o próprio Debian.
Os pacotes possivelmente serão os mesmos.
@Henrique Dias, @Diego
Pode executar os processos sem nenhuma mudança no Ubuntu Server ou Desktop que funciona sem problemas.
[]‘s
Acabei de instalar e testar a solução proposta e estou impressionado.
Configurei o jMeter pra 2000 threads em 60 segundos e nem fez cócegas no servidor (virtual). Tudo bem que o teste foi acessar a página do PHP Info, mas mesmo assim a performance foi muito boa.
Vou configurar outra máquina virtual de testes para replicar o mesmo ambiente, mas dessa vez com Apache e fazer um teste comparativo.
Carlos, você já testou o Webserver Lighthttpd,
pois estou testando e ele está aguentando o tranco, ou o cherokee -> http://www.cherokee-project.com/
Esse ultimo também está muito rápido, mas prefiro o LIghtHTTPD
benchmark:
http://www.rkblog.rk.edu.pl/w/p/lighttpd-and-cherokee-benchmark/
http://www.rkblog.rk.edu.pl/w/p/pylons-benchmark-various-servers/
Tem outro benchmark Legal, mas eu prefiro o LightHTTPD, pois ele é mais fácil de instalar e configurar.
http://www.alobbs.com/1345/Cherokee_0_8_1_benchmark.html
Pessoal,
Atendendo pedidos, e com ajuda do Ferrari na configuração, fiz um teste real: Apache X Nginx.
Primeiro Server: CentOS+Apache+2core500+1GbRam
Segundo Server: Ubuntu+Nginx+2core300+300MbRam
Quem leva a melhor nessa? façam suas apostas.
Coloquei o mesmo site nos 2 servers, um site de noticias, com MySQL e várias consultas na home. Medi o tempo de execução da home do site nos 2 servidores e peguei os maiores valores depois de algumas tentativas.
Primeiro Server (apache): 0.6 segundos
Segundo Server (nginx): 0.023 segundos
Venceu o Nginx com 2600% de dianteira.
Valeu Ferrari.
Não consigo colocar o Zend Framework pra rodar com o Nginx. É possível? Alguém conseguiu? Ou tenho que fazer proxy com o Apache?
@Diego,
é possivel sim, nunca usei o ZF, mas acredito que ele faz o uso do .htaccess, o htacces é do apache, no caso do nginx vc tem que configurar as rotas no arquivo de configuração, é tão simples quanto o metodo do apache e também é muito mais veloz.
http://wiki.nginx.org/NginxHttpRewriteModule
[]‘s
@caferrari Exatamente, o Zend Framework utiliza o .htaccess. Achei vários blogs com várias configurações diferentes para rodar o ZF no Nginx, porém nenhuma funciona. Estou sem tempo agora mas assim que possível vou verificar a wiki que você indicou. Obrigado.
Eita. Acho que era problema na minha aplicação de testes. Peguei o exemplo do Quickstart http://framework.zend.com/manual/en/learning.quickstart.intro.html
e funcionou.
Grande artigo, estou procurando uma alternativa mais rápida para rodar um sistema desenvolvido em PHP com JS (Ext).
Como uso centos e esse usa o PHP 5.1.6 não tenho muita experiencia no Debia.
Tenho uma duvida, como instalar suporte a MSSQL no PHP5?
Muito obrigado.
Ferrari, obrigado pelo ótimo tutorial. Encontrei esse script para benchmark: http://benchmarks.nickbarrett.org/
E esse site com um comparativo entre PHP-FPM vs Spawn-FCGI vs FastCGI: http://vpsbible.com/php/php-benchmarking-phpfpm-fastcgi-spawnfcgi/
Obrigado pelo comentário @Rogério Madureira
Bom apesar desse seu teste mostrar que o PHP-FPM é mais lento um pouco que as outras soluções, o FPM ainda tem vantagens.. como o spawn automático de threads dependendo da necessidade e os controles internos dele que garantem que seja fail-safe.
[]‘s
Será que eu compreendi errado? havia entendido que o benchmarking havia apontado o PHP-FPM como a solução mais rápida, com tempo médio de 374ms para completar as operações do teste, contra 413ms do SPAWN-FCGI e 461ms do PHP-FASTCGI…
Não.. eu entendi errado mesmo… então pronto.. php-fpm é perfeito.. XD
vlw!
Great internet site. Lots of handy information and facts right here. I’m just giving them for some close friends ans in addition giving around tasty. And obviously, because of your own sweat!