为了提升性能,PHP7 已经完全基于 PHPNG 进行重写,不过依然有很多其他的方法可以用来进一步提升 PHP7 性能。
Nginx 与 Apache
目前有很多 HTTP Server 软件可供使用,目前最流行的是 Nginx 与 Apache。
Apache:完整,稳定。每一个请求都由一个线程或进程处理,导致开销大,高并发情况下其性能低下的问题凸显。
Nginx:轻量,异步。 由于请求异步处理,每个进程可以处理数千个连接,因此可以使用很少的进程来承载高并发流量。
vs:在构建高性能服务器时,Apache 并不是问题所在,PHP才是真正的瓶颈。(试想如果请求都能很快被处理返回..)
缓存静态文件
将静态文件(如图片、css文件、js文件资源)缓存在用户设备上。可通过配置 HTTP 响应头信息实现:
Apache
<FilesMatch "\.(ico|jpg|jpeg|png|gif|css|js|woff)$">
Header set Cache-Control "max-age=604800, publilc"
</FilesMatch>
Nginx
Location ~* .(ico|jpg|jpeg|png|gif|css|js|woff)$ {
Expires 7d;
}
HTTP 持久链接(HTTP Keep-alive 技术)
相对于传统每次请求都需要三次握手建立链接,Keep-alive 技术在建立连接之后不需再产生握手环节,避免开销,但服务器并发数上升到一定程度,程序性能下降,为此设置链接超时非常有必要。
Apache
<ifModule mod_headers.c>
Header set Connection keep-alive
</ifModule>
Nginx
keepalive_requests 100
keepalive_timeout 100
GZIP 压缩
将网络中传输的内容进行压缩之后再传递可以有效地减轻传输负担。
apache
<ifModule mod_deflate.c>
SetOutputFilter DEFALTE
#添加需要进行过滤的文件类型
AddOutputFilterByType DEFALTE text/html text/plain text/xml text/css text/javascript application/javascript
#不压缩图片
setEnvIfNoCase Request_URI \.(?:gif|jpe?g|png) $ no-gzip dont-vary
</ifModule>
nginx
gzip on;
gzip_vary on;
gzip_types text/plain text/xml text/css text/javascript application/javascript;
gzip_com_level 4;
PHP 独立部署服务
apache 是以 mod_php 模块的方式加载php的,mod_php 通过嵌入 PHP 解释器到 Apache 进程中,不论是否用到 PHP 解释器都会将其加载到内存中,典型的就是处理CSS、JS之类的静态文件是完全没有必要加载解释器。
所以我们可以让 php-fpm 和 apache 结合,让它们都独立部署,通过 fastcgi 协议相互传递数据,这样apache只需要关注 http 请求连接即可,php 进程则由 php-fpm 创建与维护。(效仿Nginx+PHP,Nginx 本身就是与 PHP 相互独立的。)
关闭不用的模块
为了节省资源建议关闭Apache 和 nginx 没使用的模块。
apache 获得加载的所有模块的列表
apachectl -M
nginx 列出开启的模块
nginx -V
通常情况下,nginx仅开启了所需的模块进行工作
web服务器资源
每个服务器都会默认一些全局设置来使用 RAM 等资源。
nginx 提供了两个变量 worker_processes、worker_connections 来决定着可以有多少nginx进程被运行。一般一个进程运行在一个 cpu 上时比较合适的。worker_connections配置决定了这一个进程中同时可以处理的链接数。这里的配置取决于物理核数。
ulimit -n
执行这个命令后显示的数值,就可以作为worker_connections配置的设置值。
CDN(内容分发网络)
CDN 网络通常服务于媒体文件,例如图片文件、css文件、js文件和音视频文件,这些文件会被缓存在各地的服务器上,这些服务器在地域上足够分散,当收到请求时,CDN网络会选择最适合用户的最近节点,将内容下发给用户。
个人站或小企业站一般都不会建立自己的 CDN 服务器集群,可以通过付费加入诸如七牛云、阿里云等服务平台。
CSS与JS优化
合并:css、js 文件越多,需要的请求就越多,从而影响其性能,所以将多个 css 和 js 文件分别合并为一个文件,减少请求。
缩小:删除 css 和 js 文件中所有空行、注释和格外空格,这样能够减小文件体积,提高文件加载速度(可借助 Minify 工具)
全页缓存
网站的完整页面存储在缓存中,下一个请求直接读取缓存。(适用于不常改变的内容,如新闻文章)
Varnish 是一款高性能的开源HTTP加速器,其主要用来做为反向代理中的缓存服务器使用,安装 Varnish 服务器后,请求先到达 varnish ,varnish 检测是否有缓存数据,有直接返回结果,无则向web服务器请求数据,得到缓存之后缓存并返回。
负载均衡(LB)
客户端的请求先到达负载均衡服务器(LB),由负载均衡服务器通过一定的调度算法将流量分发到不同的应用服务器上面,同时负载均衡服务器也会对应用服务器做周期性的健康检查,当发现故障节点时便动态的将节点从应用服务器集群中剔除,以此来保证应用的高可用。
常用开源软件负载均衡器有:Nginx、LVS、Haproxy。
Haproxy 部署(测试)
1. 安装 Haproxy 服务器
yum -y install haproxy
2. 以不同端口模拟两台web服务器
# 分别开放端口8080、8081、8082,其中 8080 作为 Haproxy LB 服务器,8081、8082 作为两台服务器
3. 配置 nginx
添加两个域名配置(120.78.92.223:8080 指向 /var/www/html/test8080,120.78.92.223:8081 指向 /var/www/html/test8081),如下:
server {
listen 8080;
listen [::]:8080;
server_name 120.78.92.223;
root /var/www/html/test8080;
location / {
index index.php admin.php index.html index.htm test2.php;
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=/$1 last;
}
}
location ~ \.php(.*)$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# 要开启 phpinfo 模式
# 即去掉 php.ini 中 ;cgi.fix_pathinfo=1 的注释
fastcgi_param PATH_INFO $1;
include fastcgi_params;
}
#要缓存文件的后缀,可以在以下设置。
location ~ .*\.(gif|jpg|png|css|js)(.*) {
expires 90d;
}
}
4. 配置 haproxy.cfg 文件
#---------------------------------------------------------------------
# Example configuration for a possible web application. See the
# full configuration options online.
#
# http://haproxy.1wt.eu/download/1.4/doc/configuration.txt
#
#---------------------------------------------------------------------
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
#
# 1) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
#
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend main *:8080
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static
default_backend app
#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
backend static
balance roundrobin
server static 127.0.0.1:8080 check
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
balance roundrobin
server app1 120.78.92.223:8081 check
server app2 120.78.92.223:8082 check
5. 重启 haproxy
systemctl restart haproxy
6. 访问 120.78.92.223:8080
现在,在浏览器中输入LB服务器的ip或主机名,web应用程序页面将从web1或web2获取数据并显示出来。
停用任意一个web服务器,然后重新加载页面,应用仍可以工作,因为haproxy自动检测到其中一个web服务器已经关闭,并将流量重定向到第二个服务器中。
参考:《高性能PHP7,Learning PHP7 High Performance》