LNMP流程图 |
||||
nginx |
PHP |
Mysql |
||
Nginx Fastcgi_pass |
<-FastCGI-> |
fastcgi-(php-fpm)<->wrapper |
Php 解析器 (Php.ini) |
<->mysql |
fastcgi-(php-fpm)<->wrapper |
||||
fastcgi-(php-fpm)<->wrapper |
||||
fastcgi-(php-fpm)<->wrapper |
||||
fastcgi-(php-fpm)<->wrapper |
Apache和nginx解析PHP的区别 |
|
Apache |
Nginx |
libphp5.so模块加载到主配置文件 LoadModul php5_module modules/libphp5.so AddType application/x-httpd-php .php |
通过FastCGI接口连接自带的php-fpm 派生出wrapper 连接到php.ini。解析后数据原路返回 |
LNMPT构架
一 安装
1.nginx
(1)安装所需的库文件:
#yum -y install libmcrypt-devel mhash-devel libxslt-devel \
libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel \
zlib zlib-devel glibc glibc-devel glib2 glib2-devel bzip2 bzip2-devel \
ncurses ncurses-devel curl curl-devel e2fsprogs e2fsprogs-devel \
krb5 krb5-devel libidn libidn-devel openssl openssl-devel
(2) nginx 所需的支持 pcre 和zlib .前者是为了重写,后者是为了gzip解压缩
(3)安装nginx;
./configure --with-http_stub_status_module --prefix=/usr/local/nginx --with-pcre=/app/pcre-8.10 --with-zlib=/app/zlib-1.2.5
make
make instll
这里 --with-http_stub_status_module 是激活状态。
/app/pcre-8.10 和 zlib-1.2.5 是解压后的源码包的地址。这里nginx的优越性的体现不用编译后的直接可以调用源码包
mysql略过。安装lamp的时候很清晰了。
2.php
./configure --prefix=/usr/local/php --enable-fpm --with-fpm-user=nginx --with-fpm-group=nginx --with-curl --with-mcrypt=/usr/local/libmcrypt --enable-mbstring --with-mysql=/usr/local/mysql --enable-pdo --with-pdo-mysql=mysqlnd --with-mysqli=/usr/local/mysql/bin/mysql_config --with-openssl --with-imap-ssl --with-gd --with-jpeg-dir=/usr/lib/ --with-png-dir=/usr/lib/ --enable-exif --enable-zip
这里需要注意几点:
--with-mcrypt=/usr/local/libmcrypt 我的错误信息里提示缺少libmcrypt包这里编译安装的。
enable-fpm启用支持fpm(老的版本里fpm是插件。高版本集成到PHP里面了。
PHP的 PHP-fpm 配置文件解析:
nginx 解析PHP程序。原理是:(反向代理机制)通过FastCGI接口把需求发送给PHP的php-fpm模块通过派生的wraaper与php.ini解析。
把解析的数据原路返回给nginx。
# cat /usr/local/php/etc/php-fpm.conf | egrep -v "^$|^;"
[global]
[www]
user = nginx #属主
group = nginx #属组
listen = 127.0.0.1:9000 #监听的端口
pm = dynamic
pm.max_children = 5 #子进程数
pm.start_servers = 2 #默认开启的进城数
pm.min_spare_servers = 1 # 最小空闲进程
pm.max_spare_servers = 3 #最大空闲进程
PHP如何加载一个新模块:
1.进入解压的源码目录的/ext目录下任意一个模块目录下:
2.使用PHP安装后的bin/phpize 命令生成可以预编译工具。
3. #./configure --with-php-config=/usr/local/php/bin/php-config (借助php-config工具)
4. # make && make install
5.查看结果:# ls lib/php/extensions/no-debug-non-zts-20131226/ (此目录是是否还有)
二整合功能
配置nginx的主配置文件 conf/nginx.conf
user nginx; # 创建nginx useradd -s /sbin/nologin -M
location ~ \.hpp$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/local/nginx/html$fastcgi_script_name;
include fastcgi_params;
}
启动nginx: ./sbin/nginx (加入-t 检查配置文件语法。)
如果已经启动了可以重新加载: # kill -HUP `cat /usr/local/nginx/logs/nginx.pid`
启动php ./sbin/php-fpm (可以开启PHP所在服务器的9000端口。这个端口负责接收nginx的转发请求)
php 与nginx就可以工作了。
扩展nginx的知识和做nginx的负载和缓存
nginx的目录结构;
# tree -L 1
.
├── client_body_temp
├── conf #配置文件目录
├── fastcgi_temp
├── html #程序放置位置(相当于 apache的 htdocs)
├── logs # 日志
├── proxy_temp
├── sbin #命令目录 ./sbin/nginx 是nginx启动命令
├── scgi_temp
└── uwsgi_temp
# tree -l ./conf/
./conf/ (配置文件。所有.default都是备份文件)
├── fastcgi.conf #fastcgi相关参数配置文件
├── fastcgi.conf.default
├── fastcgi_params #fastcgi 的参数文件
├── fastcgi_params.default
├── koi-utf
├── koi-win
├── mime.types #媒体类型。就是网页所包含的元素类型
├── mime.types.default
├── nginx.conf #nginx的主配置文件
├── nginx.conf.default
├── scgi_params
├── scgi_params.default
├── uwsgi_params
├── uwsgi_params.default
└── win-utf
Nginx 的配置文件的 nginx.conf的结构:
main { #这里没有main{}是为了便于说明。
}
events{
}
http{
server{
location{
}
}
}
如上所例:整个层次结构是 main events http{server{location{}}}几个层次模块话结构。
按功能划又可定义成四个模块:main(全局设置)、server(主机设置)、upstream(负载均衡服务器设置)和 location(URL匹配特定位置的设置)。main部分设置的指令将影响其他所有设置;server部分的指令主要用于指定主机和端口; upstream指令主要用于负载均衡,设置一系列的后端服务器;location部分用于匹配网页位置。
这四者之间的关系式:server继承main,location继承server,upstream既不会继承其他设置也不会被继承。此外:还可以通过 include命令来扩展模块。例如支持PHP就扩展了fastcgi(include fastcgi_params;)
多个server会配置多个虚拟主机。可以把每个server模块单独写成文件通过include命令引入,减少耦合性。
简析:nginx.conf 配置的内容
user nginx nginx; #注模块命令。nginx所属的主和组。一般新建不可登陆用户替代
worker_processes 4; #nginx开启的进城数,可以与主机的CPU核数相等
#这里设置不对可引发502错误:(连接超时 我们向服务器发送请求 由于服务器当前链接太多,
#导致服务器方面无法给于正常的响应,产生此类报错)
# 这里和可以开启绑定CPU worker_cpu_affinity 0001 0100 1000 0010;进一步优化CPU
error_log logs/error.log notice; #nginx的错误日志
pid logs/nginx.pid; #指定进程pid的存储位置
worker_rlimit_nofile 65535; # nginx 打开最大文件数限制受限与系统参数(ulitim -n)。
# ulimit -n 65535
events{
use epoll; # nginx 的工作模式一般kernel 2.6以上版本可用
worker_connections 65536; #文件最大连接数(受限于 ulimit -n 65535)
}
http{
include conf/mime.types;
#include (包含其它配置文件减小。注配置文件的体积)
default_type application/octet-stream;
#默认类型为二进制流。也就是当文件类型未定义时使用这种方式。例如在没有配置PHP环境时,
#Nginx是不予解析的,此时,用浏览器访问PHP文件就会出现下载窗口。
log_format main ‘$remote_addr - $remote_user [$time_local] ‘
‘"$request" $status $bytes_sent ‘
‘"$http_referer" "$http_user_agent" ‘
‘"$gzip_ratio"‘;
log_format download ‘$remote_addr - $remote_user [$time_local] ‘
‘"$request" $status $bytes_sent ‘
‘"$http_referer" "$http_user_agent" ‘
‘"$http_range" "$sent_http_content_range"‘;
#log_access 日志的格式 可以用 main 引用。
access_log logs/www.ixdba.net.access.log main;
#指明访问日志的位置,并且声明了日志的格式
client_max_body_size 20m;
#允许客户端最大单个文件的字节数
client_header_buffer_size 32k;
#定义客户端 headerbuffer 缓冲区大小
large_client_header_buffers 4 32k;
#指定客户端请求中较大的信息头的缓存的数量和大小
Sendfile on;
#开启高效传输模式
tcp_nopush on;
tcp_nodelay on;
#这2个参数开启防止网速拥堵
keepalive_timeout 60;
#保持连接的活动时间,在60秒内不会断开
client_header_timeout 10;
# 读取客户端头部请求的超时时间
client_body_timeout 10;
# 客户端 主题部分读取超时时间
send_timeout 10;
#响应客户端超时时间
下面这段代码是HttpGzip模块在Nginx配置中的相关属性设置
gzip on;
# 开启传输压缩功能 。节省带宽,消耗CPU性能
gzip_min_length 1k;
# 压缩最小长度限制
gzip_buffers 4 16k;
#申请4个16k 的内存作为压缩流缓存
gzip_http_version 1.1;
#识别http协议版本。1.1
gzip_comp_level 2;
#指定gzip压缩比
gzip_types text/plain application/x-javascript text/css application/xml;
# 压缩压缩类型 。无论是否指定 text/html 都会压缩的。
gzip_vary on;
# 让前端的缓存服务器缓存经过GZIP压缩的页面
下面这段代码是虚拟主机的配置
server{
listen 80;
# 指定虚拟主机的服务端口
server_name 192.168.12.188 www.ixdba.net;
# 指定域名或ip 用空格分开
index index.html index.htm index.jsp;
#访问的默认首页地址
root /web/wwwroot/www.swallow.com
# 指定虚拟主机网站的根目录
charset utf8;
#网页默认编码格式
access_log logs/www.swallow.com.access.log main;
#访问日志的根式
下面这段代码是URL地址匹配设置
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
root /web/swallow.com;
expires 30d;
}
~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
正则匹配所有以.gif 等结尾的静态访问,都交给nginx。expires 30 d 是静态文件的过期时间是30天。
同理,下面这段代码是将upload和html下所有文件都交给Nginx来处理,当然,upload和html目录包含在/web/swallow.com目录中。
location ~ ^/(upload|html)/ {
root /web/swallow.com;
expires 30d;
}
在下面这段代码中,通过location关键字实现了将所有以.jsp为后缀的文件都交给本机的8080端口处理(这里安装了tomcat)。
location ~ .*.jsp$ {
index index.jsp;
proxy_pass http://localhost:8080;
}
下面这段代码配置的是Nginx的运行状态
StubStatus模块能够获取Nginx自上次启动以来的工作状态:
编译安装是:--with-http_stub_status_module 参数就是为了查看这个功能。
location / {
stub_status on;
access_log logs/NginxStatus.log;
auth_basic "NginxStatus";
auth_basic_user_file ../htpasswd;
}
依次是: 激活状态模式。
生成激活访问日志文件
设置加密状态,“”里面为密钥提示信息
密码文件的位置 默认是 conf/htpasswd
生成密码的方式:借助apache的 htpasswd
htpasswd [-c] passwordfile username
htpasswd -c /usr/local/nginx/conf/htpasswd swa
password
repassword
这样在conf目录下多了一个htpasswd文件:swa:密码的MD5格式
Nginx 的日常维护
1.nginx注配置文件的检查:
./sbin/nginx -t
./sbin/nginx -v 显示编译安装的参数
./sbin/nginx -V 显示编译安装的参数和nginx的版本
2.nginx的启动,关闭和重启
启动:./sbin/nginx
关闭: kill nignx‘pid
可以通过 ps -ef | grep nginx 和 cat /usr/local/nginx/logs/nginx.pid 获取nginx的pid
平滑重启: ./sbin/nginx -s reload (平滑重启)
重新加载: kill -HUP `cat /usr/local/nginx/logs/nginx.pid`
Nginx 反向代理:多域名跳转
server {
server_name www.tb.com;
location / {
proxy_pass http://192.168.1.139:8080/web/;
}
location /admin {
proxy_pass http://192.168.1.139:8080/admin;
}
}
server {
server_name m.tb.com;
location / {
proxy_pass http://192.168.1.139:8080/wap/;
}
}
在tomcat服务器的webapps 下创建3个目录web,admin,wap ,并分别写入特定的内容。做好本地hosts解析。
访问 www.tb.com 跳转到本地tomcat的web下
访问 www.tb.com/admin 跳转到本地tomcat的admin下
访问 w.tb.com 跳转到本地tomcat的WAP下。
反向代理是通过 location { proxy_pass } 实现的。这里 location / 相应的的proxy_pass 地址最后必须是/
nginx反向代理:新旧域名过渡(引流,维护网站流量)
www.taob.com为旧的域名,而www.tb.com为新的域名
301 永久定向(permanent)
server {
listen 80;
server_name www.taob.com;
location / {
rewrite ^/(.*)$ http://www.tb.com/$1 permanent;
}
或者通过ngnix核心变量host,实现
server {
listen 80;
server_name www.taob.com www.tb.com
if ($host !="www.tb.com"){
rewrite ^/(.*)$ http://www.tb.com/$1 permanent;
}
}
需要注意的是alias 和 root 的区别
location /i {
alias /www/image/;
} #会访问 /www/image/
location /a {
root /www/image/;
} #会访问 /www/image/a
alias 是指定路径。root是根路径。
location 在nginx的应用
location匹配规则优先级:= 最精确 ^~ 忽略正则 ~* 不区分大小写的正则 /表示模糊匹配如果没有前面3个默认匹配这个
location = / {
[ config A ]
}
location ^~ /images/ {
[ config C ]
}
location ~* \.(gif|jpg|jpeg|swf)$ {
[ config D ]
}
location / {
[ config B ]
}
location 实现访问控制
要禁止访问某个目录,可添加如下设置:
location ~ ^/(WEB-INF)/ {
deny all;
}
要禁止访问*.txt、*.doc文件,可添加如下设置:
location ~* \.(txt|doc)${
root /data/www/webapps;
deny all;
}
URL重写应用实例
正则表达式匹配:
~ 表示区分大小写匹配
~* 表示不区分大小写匹配
^~表示遇到匹配后停止解析后面的正则表达式
!~和!~*分别表示区分大小写不匹配及不区分大小写不匹配
文件及目录匹配:
-f和!-f用来判断是否存在文件
-d和!-d用来判断是否存在目录
-e和!-e用来判断是否存在文件或目录
-x和!-x用来判断文件是否可执行
在Nginx配置文件中,有很多内置变量,这些变量经常和if指令一起使用。常见的内置变量有如下几种:
$args,此变量与请求行中的参数相等
$document_root,此变量等同于当前请求的root指令指定的值
$uri,此变量等同于当前request中的URI。
$document_uri,此变量与$uri含义一样。
$host,此变量与请求头部中“Host”行指定的值一致。
$limit_rate,此变量用来设置限制连接的速率。
$request_method,此变量等同于request的method,通常是“GET”或“POST”。
$remote_addr,此变量表示客户端IP地址。
$remote_port,此变量表示客户端端口。
$remote_user,此变量等同于用户名,由ngx_http_auth_basic_module认证。
$request_filename,此变量表示当前请求的文件的路径名,由root或alias和URI request组合而成。
$request_uri,此变量表示含有参数的完整的初始URI。
$query_string,此变量与$args含义一致。
$server_name,此变量表示请求到达的服务器名。
$server_port,此变量表示请求到达的服务器的端口号
if指令应用实战
语法:if (condition) { … }
默认值:none
使用字段:server, location
server {
listen 80;
server_name www.tb.com;
access_log logs/host.access.log main;
location / {
root /usr/local/nginx/html;
index index.html index.htm;
}
location ~*\.(gif|jpg|jpeg|png|bmp|swf|htm|html|css|js)$ {
root /usr/local/nginx/www/img;
if (!-f $request_filename)
{
root /data/www/html/img;
}
if (!-f $request_filename)
{
root /webapps/images;
}
}
location ~*\.(jsp)$ {
root /webdata/webapp/www/ROOT;
if (!-f $request_filename)
{
root /usr/local/nginx/www/jsp;
}
proxy_pass http://127.0.0.1:8888;
}
}
这里要访问静态资源。有3个目录/usr/local/nginx/html,/data/www/html/img, /webapps/images。
这种情况主要是前期制作网站的时候。没有规划好,静态文件分散。这样判断就不用去修改原网站结构。
对于动态的访问直接访问/webdata/webapp/www/ROOT,/usr/local/nginx/www/jsp
rewrite指令实战
Nginx通过ngx_http_rewrite_module模块支持url重写、支持if条件判断,但要使用rewrite功能,需要PCRE支持,应在编译nginx时指定PCRE源码目录。rewrite的使用语法如下:
语法:rewrite regex flag
默认值:none
使用字段:server, location, if
在默认情况下,rewrite指令默认值为空,可在nginx配置文件的server、location、if部分使用,rewrite指令的最后一项参数为flag标记,其支持的flag标记主要有以下几种:
last, 相当于Apache里的[L]标记,表示完成rewrite之后搜索相应的URI或location。
break,表示终止匹配, 不再匹配后面的规则。
redirect,将返回302临时重定向,在浏览器地址栏会显示跳转后的URL地址。
permanent,将返回301永久重定向,在浏览器地址栏会显示跳转后的URL地址。
其中,last和break用来实现URL重写,浏览器地址栏中的URL地址不变。下面是一个示例配置:
location ~ ^/best/ {
rewrite ^/best/(.*)$ /test/$1 break;
proxy_pass http://www.taob.com;
}
在这个例子中,使用了break标记,可实现将请求为http://www.tb.com/best/webinfo.html 的页面重定向到http://www.taob.com/test/webinfo.html 页面而不引起浏览器地址栏中URL的变化。这个功能在新旧网站交替的时候非常有用。
Nginx作为负载均衡服务器应用案例
nginx负载均衡配置方法:先 配置负载均衡规则模块。然后在server{}模块引用
Nginx的负载均衡模块目前支持4种调度算法,下面分别进行介绍,其中后两项属于第三方的调度方法。
轮询(默认),每个请求按时间顺序逐一分配到不同的后端服务器,如果后端某台服务器死机,故障系统被自动剔除,使用户访问不受影响。
Weight,指定轮询权值,Weight值越大,分配到的访问机率越高,主要用于后端每个服务器性能不均的情况下。
ip_hash,每个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。
fair,比上面两个更加智能的负载均衡算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,
也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。
Nginx本身是不支持fair的,如果需要使用这种调度算法,必须下载Nginx的upstream_fair模块。
url_hash,按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率。
Nginx本身是不支持url_hash的,如果需要使用这种调度算法,必须安装Nginx 的hash软件包。
在HTTP Upstream模块中,可以通过server指令指定后端服务器的IP地址和端口,同时还可以设定每个后端服务器在负载均衡调度中的状态。
常用的状态有:
down,表示当前的server暂时不参与负载均衡。
backup,预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻。
max_fails,允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。
fail_timeout,在经历了max_fails次失败后,暂停服务的时间。max_fails可以和fail_timeout一起使用。
注意 当负载调度算法为ip_hash时,后端服务器在负载均衡调度中的状态不能是weight和backup。
实际操作(配置负载池 myserver 引用负载池)
upstream myserver {
server 192.168.1.139:8080 weight=1 max_fails=3 fail_timeout=20s;
server 192.168.1.141:8080 weight=3 max_fails=3 fail_timeout=20s;
}
server {
listen 80;
server_name 192.168.1.139;
root /usr/local/tomcat/webapps/ROOT/;
location / {
proxy_pass http://myserver;
#index index.jsp
proxy_next_upstream http_500 http_502 http_503 error timeout invalid_header;
include /usr/local/nginx/conf/proxy.conf;
}
}
可以做探针文件通过目录的改变来查看weight的作用。
这里需要手动填写 proxy.conf文件。
# cat conf/proxy.conf
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
Nginx作为Web缓存服务器应用案例:
下载地址:http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz
是以模块的形式加载到nginx里面的需要重新编译nginx:添加编译参数:
--add-module=/app/ngx_cache_purge-2.3 (这个位置还是解压后的源码包位置。不需要编译ngx_cache_purge)
配置信息:
http {
proxy_cache_path /backup/proxy_cache_dir levels=1:2 keys_zone=cache_one:4096m inactive=1d max_size=3g;
#这里需要在http模块中配置cache信息 path路径;最好将缓存放入一个独立磁盘
#levels:用来设置目录深度。数字代表每层目录的名称的字符个数。
#zone 代表缓存区域的cache名称(cache_one) 4096是缓存大小。
#inactived:1d 代表缓存1天。
#size代表缓存磁盘的大小。一般内存中的缓存放不下了。就会写入磁盘。
proxy_temp_path /backup/proxy_temp_dir;
#proxy_temp_path用于指定临时缓存文件的存储路径,这里需要注意的是,
#proxy_temp_path和proxy_cache_path指定的路径必须在同一磁盘分区。
server {
location / {
proxy_cache cache_one;
#反向代理缓存设置指令,需要将proxy_cache指令放到location字段,
#这样匹配此location的url才能被缓存。cache_one 就是上面定义的缓存区域名称
proxy_cache_valid 200 304 12h;
#对不同的HTTP状态码设置不同的缓存时间
proxy_cache_key $host$uri$is_args$args;
#这个指令是设置以什么样的参数得到缓存的文件名,默认为“$scheme$proxy_host$request_uri”,
#表示以协议、主机名、请求uri(包含参数)作md5得出缓存的文件名。
#这里是以域名、URI、参数组合成web缓存的Key值,Nginx根据Key值哈希,存储缓存内容到二级缓存目录内
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://127.0.0.1:8080;
expires 1d;
}
location ~ /purge(/.*) #清除缓存的方法
{
allow 127.0.0.1;
allow 192.168.88.0/24;
#表示只允许指定的IP或IP段才可以清除URL缓存。
deny all;
proxy_cache_purge cache_one $host$1$is_args$args;
}
location ~ .*\.(jsp|php|jspx)?$
#设置不做缓存的内容,这里设置扩展名以.jsp、.php、.jspx结尾的动态应用程序不缓存
{
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://127.0.0.1:8080;
}
}
}
应用清除缓存策略:location ~ /purge(/.*)
例如:,要清除http://www.tb.com/cms/a/xinwen/2014/0413/2.html 这个页面的缓存文件,
只需在浏览器重输入http://www.tb.com/purge/cms/a/xinwen/2014/0413/2.html 地址即可
在域名后面添加purge 后跟要清除的内容。
当然也可以清空缓存存放的目录。