50
Proper configura-on for high performance websites Harald Zeitlhofer February 2015 Boost your website by running PHP on Nginx @HZeitlhofer [email protected]

Running php on nginx

Embed Size (px)

Citation preview

Page 1: Running php on nginx

1 #Dynatrace

Proper  configura-on  for  high  performance  websites  

Harald  Zeitlhofer  February  2015  

 

Boost  your  website  by  running  PHP  on  Nginx  

@HZeitlhofer  [email protected]  

 

Page 2: Running php on nginx

2 #Dynatrace

Nginx  

Page 3: Running php on nginx

3 #Dynatrace

• Lightweight  HTTP  server  • Fast  especially  at  high  load  • Open  Source  project  (BSD)    by  Igor  Sysoev  

• Nginx,  Inc.  founded  in  2011  • Nginx+:  enhanced  func-onality  and  enterprise  support  

•  Load  balancer  

•  Media  server  

Page 4: Running php on nginx

4 #Dynatrace

Leading  among    top  10.000  websites  

Page 5: Running php on nginx

5 #Dynatrace

Nginx  vs  Apache  

Page 6: Running php on nginx

6 #Dynatrace

Request  handling  

Page 7: Running php on nginx

7 #Dynatrace

• mod_php  

• mod_fcgid  

• mod_fastcgi  

 

Integra-on  

• ngx_h+p_fastcgi_modul  

Page 8: Running php on nginx

8 #Dynatrace

PHP  FastCGI  Process  Manager  

Page 9: Running php on nginx

9 #Dynatrace

• Apache  Module  •  used  for  most  PHP  environments  

• CGI  •  Command  Line  Interface  (CLI)  

• FastCGI  (PHP-­‐FPM)  •  Available  since  5.3.3,  stable  since  5.4.1  

•  Run  mul-ple  PHP  worker  processes  to  serve  CGI  requests  

•  Mul-ple  connec-on  pools  (different  uid/gid  environments  possible)  

•  Isola-on  from  webserver  (fastcgi_finish_request)  

PHP  run  modes  

Page 10: Running php on nginx

10 #Dynatrace

•  Installa-on    

• Pool  configura-on  /etc/php5/fpm/pool.d/www.conf

PHP-­‐FPM  

[www] user = www-data group = www-data listen = 127.0.0.1:9000 # for Unix socket: unix:/var/run/php5-fpm.sock;

root@hzvm01:/etc/nginx/sites-enabled# ps -ef | grep php root 6435 1 0 14:39 ? 00:00:32 php-fpm: master process (/etc/php5/fpm/php-fpm.conf) spelix 6439 6435 0 14:39 ? 00:00:00 php-fpm: pool batch spelix 6440 6435 0 14:39 ? 00:00:00 php-fpm: pool batch www-data 10576 6435 1 18:45 ? 00:00:48 php-fpm: pool www www-data 10920 6435 1 18:47 ? 00:00:47 php-fpm: pool www www-data 10927 6435 1 18:47 ? 00:00:46 php-fpm: pool www

sudo apt-get install php5-fpm

Page 11: Running php on nginx

11 #Dynatrace

• Pool  configura-on  /etc/php5/fpm/pool.d/www.conf

PHP-­‐FPM  

[pool_name] ... pm = [dynamic/static] pm.max_children = 10 ;only used for dynamic: pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 3

pm.max_children      =  total  available  memory  /  memory  used  by  1  PHP  process  

Page 12: Running php on nginx

12 #Dynatrace

Nginx  and  PHP-­‐FPM  Integra-on  

Page 13: Running php on nginx

13 #Dynatrace

•  /etc/nginx/nginx.conf    

 # max_clients = worker_processes * worker_connections worker_processes 8; # number of CPUs worker_rlimit_nofile 40000; events { worker_connections 1024; multi_accept on; }

Page 14: Running php on nginx

14 #Dynatrace

• Communica-on  via  sockets  •  TCP  vs  Unix  

•  Unix  slightly  faster  when  used  on  localhost  

•  Use  TCP  for  high  load  

location ~* \.php$ { fastcgi_index index.php; fastcgi_pass 127.0.0.1:9000; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_NAME $fastcgi_script_name; }

fastcgi_pass unix:/var/run/php5-fpm.sock;

Page 15: Running php on nginx

15 #Dynatrace

Nginx  –  PHP  transac-on  flow  

Page 16: Running php on nginx

16 #Dynatrace

•  Sta-c  content  to  be  served  by  Nginx  •  Dynamic  requests  to  be  sent  to  PHP-­‐FPM  

Integra-on  

server { listen 80; root /var/www/test; index index.php index.html index.htm; server_name test.whateveryourdomain.is; location ~ \.(html|js|css|gif|jpg|jpe|jpeg|png|bmp|tif|pdf|ico)$ { try_files $uri @notfound; } location / { try_files $uri $uri/ =404; } location ~* \.php$ {

fastcgi_index index.php; fastcgi_pass php; include fastcgi_params; }

}

Page 17: Running php on nginx

17 #Dynatrace

hdp://www.mysite.com/news/browse/2014  

è  to  be  handled  by  index.php  

URL  rewrite  

... RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-l RewriteRule ^(.+)$ index.php ...

Page 18: Running php on nginx

18 #Dynatrace

hdp://www.mysite.com/news/browse/2014  

è  to  be  handled  by  index.php  

URL  rewrite  

upstream php { server unix:/var/run/php5-fpm.sock; } server {

listen 80; root /var/www; index index.php index.html index.htm; server_name www.mysite.com;

location / {

try_files $uri $uri/ @missing; }

location @missing {

rewrite (.*) /index.php; }

location ~ .php$ {

fastcgi_index index.php; include fastcgi_params; fastcgi_pass php;

} }

Page 19: Running php on nginx

19 #Dynatrace

using  Nginx/PHP-­‐FPM  there’s  a  beder  way:  

URL  rewrite  

upstream php { server unix:/var/run/php5-fpm.sock; } server {

listen 80; root /var/www; index index.php index.html index.htm; server_name www.mysite.com;

location /images {

try_files $uri $uri/ =404; }

location /scripts {

try_files $uri $uri/ =404; }

location / {

fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME /var/www/index.php; fastcgi_pass php; }

}

<?php

$params = explode('/', trim($_SERVER["DOCUMENT_URI"],'/')); ...

Page 20: Running php on nginx

20 #Dynatrace

• Easy  way  to  deploy  your  applica-on  • All  source  files  packed  into  one  *.phar  file  

PHAR  –  PHP  Archives  

location ~* \.(php|phar)$ { fastcgi_index index.php; fastcgi_pass 127.0.0.1:9000; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/myapp.phar; }

Page 21: Running php on nginx

21 #Dynatrace

PHAR  example  root@hzvm01:/var/www/app/src# ls -lrtR .: total 8 drwxrwxr-x 2 root root 4096 Oct 10 16:27 lib -rw-r--r-- 1 root root 27 Oct 10 16:27 index.php ./lib: total 4 -rw-r--r-- 1 root root 87 Oct 10 16:27 App.php

root@hzvm01:/var/www/app/src# cat index.php <?php $app = new App(); ?>

root@hzvm01:/var/www/app/src# cat lib/App.php <?php class App { function __construct() { echo "Starting Application\n"; }

}

Page 22: Running php on nginx

22 #Dynatrace

PHAR  example  

location /myapp { fastcgi_index index.php; fastcgi_pass 127.0.0.1:9000; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/myapp.phar; }

root@hzvm01:/var/www/app# phar pack -f myapp.phar src lib/App.php index.php root@hzvm01:/var/www/app# l myapp.phar -rw-r--r-- 1 root root 6923 Oct 10 19:51 myapp.phar

Page 23: Running php on nginx

23 #Dynatrace

PHAR  execu-on  

Page 24: Running php on nginx

24 #Dynatrace

Performance  

Page 25: Running php on nginx

25 #Dynatrace

• Nginx  running  with  default  sehngs  

• Apache  •  AllowOverride  None  

•  Mul--­‐process  mode  to  allow  usage  of  mod_php  

Benchmarking  Nginx  vs  Apache  

Page 26: Running php on nginx

26 #Dynatrace

Sta-c  HTML,  10k  requests  

0  

1  

2  

3  

4  

5  

6  

7  

8  

9  

100   500   1000   2000  

Apache/2.4.9  nginx/1.1.19  

concurrency  

Total  respo

nse  -m

e  [sec]  

Page 27: Running php on nginx

27 #Dynatrace

Nginx  and  Caching  

Page 28: Running php on nginx

28 #Dynatrace

• Part  of  the  Nginx  FastCGI  module  

Nginx  FastCGI  cache  

fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=APPKEY:100m inactive=60m; fastcgi_cache_key "$scheme$request_method$host$request_uri";

location ~* \.php$ { fastcgi_index index.php; fastcgi_pass 127.0.0.1:9000; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_cache APPKEY; fastcgi_cache_valid 200 60m; }

Page 29: Running php on nginx

29 #Dynatrace

Tes-ng  FastCGI  cache  

Page 30: Running php on nginx

30 #Dynatrace

Tes-ng  FastCGI  cache  

Page 31: Running php on nginx

31 #Dynatrace

Tes-ng  FastCGI  cache  

<?php echo time()."\n"; ?>

Page 32: Running php on nginx

32 #Dynatrace

• ngx_hdp_memcached_module  

Full  page  cache  with  Nginx  and  Memcached  

server { location / { set $memcached_key "$uri"; memcached_pass localhost:11211; error_page 404 502 504 = @fallback; } location @fallback { proxy_pass http://backend; } }

Page 33: Running php on nginx

33 #Dynatrace

• PHP    

Full  page  cache  with  Nginx  and  Memcached  

<?php ... function cachePage($content) { $c = new Memcached(); $c->addServer('localhost',11211); $c->set($_SERVER[”REQUEST_URI"], $content);

} ... $content = $this->renderPage(); $this->cachePage($content); ... ?>

Page 34: Running php on nginx

34 #Dynatrace

PHP,  5k  requests,  concurrency  100  

0  

1  

2  

3  

4  

5  

6  

7  

8  

Apache+PHP   Nginx+PHP   Nginx+Memcached  

<?php echo “Hello World”; ?>

Page 35: Running php on nginx

35 #Dynatrace

Server Software: Apache/2.4.7 Server Hostname: test.hzvm01 Server Port: 88 Document Path: /index.php Document Length: 10 bytes Concurrency Level: 100 Time taken for tests: 7.296 seconds Complete requests: 5000 Failed requests: 0 Total transferred: 985000 bytes HTML transferred: 50000 bytes Requests per second: 685.31 [#/sec] (mean) Time per request: 145.920 [ms] (mean) Time per request: 1.459 [ms] (mean, across all concurrent requests) Transfer rate: 131.84 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 6 6.5 4 56 Processing: 30 138 57.2 120 938 Waiting: 30 135 56.4 117 937 Total: 55 144 55.8 126 938

PHP,  5k  requests,  concurrency  100  

Page 36: Running php on nginx

36 #Dynatrace

Server Software: Nginx + PHP Server Hostname: test.hzvm01 Server Port: 80 Document Path: /index.php Document Length: 10 bytes Concurrency Level: 100 Time taken for tests: 4.514 seconds Complete requests: 5000 Failed requests: 0 Total transferred: 625000 bytes HTML transferred: 50000 bytes Requests per second: 1107.62 [#/sec] (mean) Time per request: 90.284 [ms] (mean) Time per request: 0.903 [ms] (mean, across all concurrent requests) Transfer rate: 135.21 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 2 3.2 1 38 Processing: 22 88 13.1 87 148 Waiting: 21 87 13.1 86 148 Total: 42 89 12.5 88 148

PHP,  5k  requests,  concurrency  100  

Page 37: Running php on nginx

37 #Dynatrace

Server Software: Nginx + Memcached Server Hostname: test.hzvm01 Server Port: 82 Document Path: /index.php Document Length: 23 bytes Concurrency Level: 100 Time taken for tests: 3.058 seconds Complete requests: 5000 Failed requests: 0 Total transferred: 865000 bytes HTML transferred: 115000 bytes Requests per second: 1634.92 [#/sec] (mean) Time per request: 61.165 [ms] (mean) Time per request: 0.612 [ms] (mean, across all concurrent requests) Transfer rate: 276.21 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 7 24 6.0 24 59 Processing: 8 36 7.8 36 75 Waiting: 6 28 7.4 29 69 Total: 32 60 9.3 60 101

PHP,  5k  requests,  concurrency  100  

Page 38: Running php on nginx

38 #Dynatrace

•  set  HTTP  response  expires  header  

Client  Side  Caching  

location ~ \.(html|js|css|gif|jpg|jpe|jpeg|png|bmp|tif|pdf|ico)$ { expires 90d; access_log off; error_log off; try_files $uri =404; }

Page 39: Running php on nginx

39 #Dynatrace

• keep  handlers  for  requested  sta-c  files  open  

Filehandle  Caching  

open_file_cache max=1000 inactive=5m; open_file_cache_valid 60s; open_file_cache_min_uses 5; open_file_cache_errors off;

Page 40: Running php on nginx

40 #Dynatrace

•  ngx_hdp_upstream_module  

Load  balancing  PHP  

upstream php_loadbalancer { ip_hash; server unix:/var/run/php5-fpm.sock weight=5; server 192.168.56.12:7777 weight=2; server 192.168.56.13:7777;

} server { listen 80; root /home/www/test; server_name test.hzvm01; location / { try_files $uri =405; } location ~ \.php$ { fastcgi_pass php_loadbalancer; fastcgi_index index.php; include fastcgi_params; }

}

Page 41: Running php on nginx

41 #Dynatrace

Load  balancing  PHP  

Page 42: Running php on nginx

42 #Dynatrace

Load  balancing  /  Reverse  Proxy  upstream backend { ip_hash; server 192.168.56.11 weight=5; server 192.168.56.12 weight=2; server 192.168.56.13;

} server { listen 80; root /var/www/mysite.com/html; server_name www.mysite.com; location / { try_files $uri =405; proxy_pass http://backend; }

}

Page 43: Running php on nginx

43 #Dynatrace

Reverse  Proxy  /  Load  balancing  /  Caching  proxy_cache_path /etc/nginx/cache keys_zone=APPKEY:10m; proxy_cache_key "$host$request_uri$cookie_user"; proxy_cache_min_uses 5; proxy_cache_methods GET HEAD; proxy_cache_valid 200 302 10m; proxy_cache_valid 404 1m; upstream backend { ip_hash; server 192.168.56.11 weight=5; server 192.168.56.12 weight=2; server 192.168.56.13;

} server { listen 80; root /var/www/mysite.com/html; server_name www.mysite.com; proxy_cache APPKEY; location / { proxy_pass http://backend; }

}

Page 44: Running php on nginx

44 #Dynatrace

Performance  Monitoring  

Page 45: Running php on nginx

45 #Dynatrace

End-­‐To-­‐End  Monitoring  

Page 46: Running php on nginx

46 #Dynatrace

User  Experience  Management  

Page 47: Running php on nginx

47 #Dynatrace

Page 48: Running php on nginx

48 #Dynatrace

Page 49: Running php on nginx

49 #Dynatrace

• Load  Generator  (Apache  Benchmark,  JMeter)  

• Firebug,  Google  Developer  Tools  Dynatrace  Ajax  Edi-on  

• Google  PageSpeed  • Dynatrace  Free  Trial  

•  Free  trial  license  for  30  days  

•  Free  for  developers  on  local  machine  

Tools  

hdp://bit.ly/ddrial  

Page 50: Running php on nginx

50 #Dynatrace

Thank You [email protected]  @HZeitlhofer    

www.dynatrace.com