Nginx除了可以在企业提供高性能的web服务之外,另外还可以将 nginx 本身不具备的请求通过某种预定义的协议转发至其它服务器处理,不同的协议就是Nginx服务器与其他服务器进行通信的一种规范,主要在不同的场景使用以下模块实现不同的功能

ngx_http_proxy_module: 		#将客户端的请求以http协议转发至指定服务器进行处理
ngx_http_upstream_module: 	#用于定义为proxy_pass,fastcgi_pass,uwsgi_pass等指令引用的后端服务器分组
ngx_stream_proxy_module:	#将客户端的请求以tcp协议转发至指定服务器处理
ngx_http_fastcgi_module:	#将客户端对php的请求以fastcgi协议转发至指定服务器助理
ngx_http_uwsgi_module: 		#将客户端对Python的请求以uwsgi协议转发至指定服务器处理

实现 http 反向代理
反向代理配置参数

proxy_pass;
#用来设置将客户端请求转发给的后端服务器的主机,可以是主机名(将转发至后端服务做为主机头首部)、IP地址:端口的方式
#也可以代理到预先设置的主机群组,需要模块ngx_http_upstream_module支持

示例:
location /web {
	index index.html;
	proxy_pass http://10.0.0.18:8080; 
	proxy_pass http://10.0.0.18:8080/;
}
	
proxy_pass http://10.0.0.18:8080; 
#8080后面无/符号,需要将location后面url附加到proxy_pass指定的url后面,类似于root
#proxy_pass指定的URI不带斜线将访问的/web,等于访问后端服务器http://10.0.0.18:8080/web/index.html,即后端服务器配置的站点根目录要有web目录才可以被访问

proxy_pass http://10.0.0.18:8080/; 
#8080后面有 / 符号,相当于置换,即访问/web时实际返回proxy_pass后面uri内容.类似于alias
#proxy_pass指定的URI带斜线,等于访问后端服务器的http://10.0.0.18:8080/index.html内容返回给客户端
proxy_hide_header field;
#用于nginx作为反向代理的时候,在返回给客户端http响应时,隐藏后端服务器相应头部的信息,可以设置在http,server或location块,
示例:
proxy_hide_header ETag; 
#隐藏后端服务器ETag首部字段
proxy_pass_header field;
#默认nginx在响应报文中不传递后端服务器的首部字段Date, Server, X-Pad, X-Accel等参数,如果要传递的话则要使用 proxy_pass_header field声明将后端服务器返回的值传递给客户端
#field 首部字段大小不敏感
proxy_pass_request_body on | off;
#是否向后端服务器发送HTTP实体部分,可以设置在http,server或location块,默认即为开启
proxy_pass_request_headers on | off;
#是否将客户端的请求头部转发给后端服务器,可以设置在http,server或location块,默认即为开启
proxy_set_header;
#可更改或添加客户端的请求头部信息内容并转发至后端服务器,比如在后端服务器想要获取客户端的真实IP的时候,就要更改每一个报文的头部
proxy_set_header;
#可更改或添加客户端的请求头部信息内容并转发至后端服务器,比如在后端服务器想要获取客户端的真实IP的时候,就要更改每一个报文的头部
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout time;
#配置nginx服务器与后端服务器尝试建立连接的超时时间,默认为60秒,用法如下:
proxy_connect_timeout 6s;
#60s为自定义nginx与后端服务器建立连接的超时时间,超时会返回客户端504响应码
proxy_read_timeout time;
#配置nginx服务器向后端服务器或服务器组发起read请求后,等待的超时时间,默认60s
proxy_send_timeout time;
#配置nginx项后端服务器或服务器组发起write请求后,等待的超时 时间,默认60s
proxy_http_version 1.0;
#用于设置nginx提供代理服务的HTTP协议的版本,默认http 1.0

proxy_ignore_client_abort off;
#当客户端网络中断请求时,nginx服务器中断其对后端服务器的请求。即如果此项设置为on开启,则服务器会忽略客户端中断并一直等着代理服务执行返回,如果设置为off,则客户端中断后Nginx也会中断客户端请求并立即记录499日志,默认为off。

proxy_headers_hash_bucket_size 128;
#当配置了 proxy_hide_header和proxy_set_header的时候,用于设置nginx保存HTTP报文头的hash表的上限

proxy_headers_hash_max_size 512;
#设置proxy_headers_hash_bucket_size的最大可用空间

server_namse_hash_bucket_size 512;
#server_name hash表申请空间大小

server_names_hash_max_size 512;
#设置服务器名称hash表的上限大小

实现单台机器的代理

#针对server进行代理
server {
	listen 80;
	server_name www.thinkmo.org;
	location / {
		proxy_pass http://10.0.0.18/; # http://10.0.0.18/ 最后的 / 可加或不加
	}
}
#针对特定的location进行代理
server {
	listen 80;
	server_name www.thinkmo.org;
	location / {
		index index.html index.php;
		root /data/nginx/html/pc;
	}
	location /static {
		#proxy_pass http://10.0.0.18:80/; #注意有后面的/, 表示置换
		proxy_pass http://10.0.0.18:80; #后面没有 / , 表示附加
	}
}
#针对特定的资源实现代理
server {
	......
	location ~ \.(jpeg|png|bmp|gif)$ {
		proxy_pass http://10.0.0.18; #如果加/ 语法出错
	}
}

http反向代理高级应用
Nginx可以将客户端的请求转发至单台后端服务器但是无法转发至特定的一组的服务器,而且不能对后端服务器提供相应的服务器状态监测,Nginx可以基于ngx_http_upstream_module模块提供服务器分组转发、权重分配、状态监测、调度算法等高级功能

文档说明:https://nginx.org/en/docs/http/ngx_http_upstream_module.html
http upstream配置参数

Syntax:	upstream name { ... }
Default:	—
Context:	http

upstream NAME {
	server .....
	......
}
#用法
upstream web {
    server 10.0.0.28:80;
    server 10.0.0.38:80;
}   
server {
    listen 80 ;
    server_name localhost;
    location / { 
        proxy_pass http://web;
    }
}

server address [parameters];
#配置一个后端web服务器,配置在upstream内,至少要有一个server服务器配置。

#server支持的parameters如下:
weight=number #设置权重,默认为1,实现类似于LVS中的WRR,WLC等
max_conns=number #给当前server设置最大活动链接数,默认为0表示没有限制
max_fails=number #对后端服务器连续监测失败多少次就标记为不可用,默认为1次,当客户端访问时,才利用TCP触发对探测后端服务器健康性检查,而非周期性的探测
fail_timeout=time #对后端服务器的单次监测超时时间,默认为10秒
backup #设置为备份服务器,当所有服务器不可用时将重新启用次服务器
down #标记为down状态
resolve #当server定义的是主机名的时候,当A记录发生变化会自动应用新IP而不用重启Nginx

调度方法

hash KEY [consistent];
#基于指定请求报文中首部字段或者URI等key做hash计算,使用consistent参数,将使用ketama一致性hash算法,适用于后端是Cache服务器(如varnish)时使用,consistent定义使用一致性hash运算,一致性hash基于取模运算
hash $request_uri consistent; 	#基于用户请求的uri做hash
hash $cookie_sessionid;			#基于cookie中的sessionid这个key进行hash调度,实现会话绑定
ip_hash;
#源地址hash调度方法,基于的客户端的remote_addr(源地址IPv4的前24位或整个IPv6地址)做hash计算,以实现会话保持
least_conn;
#最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器,相当于LVS中的WLC

实现 tcp 负载均衡
tcp负载均衡配置参数

stream { #定义stream相关的服务;Context:main
	upstream backend { #定义后端服务器
		hash $remote_addr consistent; #定义调度算法
		server backend1.example.com:12345 weight=5; #定义具体server
		server 127.0.0.1:12345 max_fails=3 fail_timeout=30s;
		server unix:/tmp/backend3;
	}
	upstream dns { #定义后端服务器
		server 10.0.0.1:53535; #定义具体server
		server dns.example.com:53;
	}
	server { #定义server
		listen 12345; #监听IP:PORT
		proxy_connect_timeout 1s; #连接超时时间
		proxy_timeout 3s; #转发超时时间
		proxy_pass backend; #转发到具体服务器组
	}
	server {
		listen 127.0.0.1:53 udp reuseport;
		proxy_timeout 20s;
		proxy_pass dns;
	}
	server {
		listen [::1]:12345;
 	  	proxy_pass unix:/tmp/stream.socket;
	}
}

示例:redis负载均衡

stream {
	upstream redis_server {
		#hash $remote_addr consistent;
		server 10.0.0.28:6379 max_fails=3 fail_timeout=30s;
		server 10.0.0.38:6379 max_fails=3 fail_timeout=30s;
	}
	server {
		listen 10.0.0.18:6379;
		proxy_connect_timeout 3s;
		proxy_timeout 3s;
		proxy_pass redis_server;
	}
}

示例:mysql负载均衡

upstream mysql_server {
	least_conn;
	server 10.0.0.28:3306 max_fails=3 fail_timeout=30s;
}
	server {
		listen 10.0.0.18:3306;
		proxy_connect_timeout 6s;
		proxy_timeout 15s;
		proxy_pass mysql_server;
	}
}

动态FastCGI
CGI的由来:

最早的Web服务器只能简单地响应浏览器发来的HTTP请求,并将存储在服务器上的HTML文件返回给浏览器,也就是静态html文件,但是后期随着网站功能增多网站开发也越来越复杂,以至于出现动态技术,比如像php(1995年)、java(1995)、python(1991)语言开发的网站,但是nginx/apache服务器并不能直接运行 php、java这样的文件,apache实现的方式是打补丁,但是nginx缺通过与第三方基于协议实现,即通过某种特定协议将客户端请求转发给第三方服务处理,第三方服务器会新建新的进程处理用户的请求,处理完成后返回数据给Nginx并回收进程,最后nginx在返回给客户端,那这个约定就是通用网关接口(common gateway interface,简称CGI),CGI(协议) 是web服务器和外部应用程序之间的接口标准,是cgi程序和web服务器之间传递信息的标准化接口。

CGI协议虽然解决了语言解析器和 Web Server之间通讯的问题,但是它的效率很低,因为 Web Server每收到一个请求都会创建一个CGI进程,PHP解析器都会解析php.ini文件,初始化环境,请求结束的时候再关闭进程,对于每一个创建的CGI进程都会执行这些操作,所以效率很低,而FastCGI是用来提高CGI性能的,FastCGI每次处理完请求之后不会关闭掉进程,而是保留这个进程,使这个进程可以处理多个请求。这样的话每个请求都不用再重新创建一个进程了,大大提升了处理效率。

PHP-FPM(FastCGI Process Manager:FastCGI进程管理器)是一个实现了Fastcgi的程序,并且提供进程管理的功能。进程包括master进程和worker进程。master进程只有一个,负责监听端口,接受来自web server的请求。worker进程一般会有多个,每个进程中会嵌入一个PHP解析器,进行PHP代码的处理。

FastCGI配置指令

Nginx基于模块ngx_http_fastcgi_module实现通过fastcgi协议将指定的客户端请求转发至php-fpm处理,其配置指令如下:

fastcgi_pass address:port;
#转发请求到后端服务器,address为后端的fastcgi server的地址,可用位置:location, if inlocation

fastcgi_index name;
#fastcgi默认的主页资源,示例:fastcgi_index index.php;

fastcgi_param parameter value [if_not_empty];
#设置传递给FastCGI服务器的参数值,可以是文本,变量或组合,可用于将Nginx的内置变量赋值给自定义key

fastcgi_param REMOTE_ADDR $remote_addr; #客户端源IP
fastcgi_param REMOTE_PORT $remote_port; #客户端源端口
fastcgi_param SERVER_ADDR $server_addr; #请求的服务器IP地址
fastcgi_param SERVER_PORT $server_port; #请求的服务器端口
fastcgi_param SERVER_NAME $server_name; #请求的server name

Nginx默认配置示例:
location ~ \.php$ {
	root /scripts;
	fastcgi_pass 127.0.0.1:9000;
	fastcgi_index index.php;
	fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; #默认脚本路径
	#fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
	include fastcgi_params;
}

FastCGI实现
php安装可以通过yum或者编译安装,使用yum安装相对比较简单,编译安装更方便自定义参数或选项。

1.yum安装默认版本php和相关APP依赖的包

yum -y install php-fpm php-mysqlnd php-json

2.php相关配置优化

grep "^[a-Z]" /etc/php-fpm.conf

include=/etc/php-fpm.d/*.conf
pid = /run/php-fpm/php-fpm.pid
error_log = /var/log/php-fpm/error.log
daemonize = yes #是否后台启动

grep -Ev '^;.*$|^ *$' /etc/php-fpm.d/www.conf
[www]
user = apache
group = apache

listen = /run/php-fpm/www.sock #指定使用UDS,或者使用下面形式
;listen = 127.0.0.1:9000 #监听地址及IP

listen.acl_users = apache,nginx
listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
slowlog = /var/log/php-fpm/www-slow.log
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path]    = /var/lib/php/session
php_value[soap.wsdl_cache_dir]  = /var/lib/php/wsdlcache

3.重新启动php-fpm

systemctl restart php-fpm

4.准备php测试页面

vim /www/nginx/html/index.php #php测试页面
<?php
phpinfo();
?>

5.Nginx配置转发PHP

vim /www/nginx/conf/nginx.conf

location ~ \.php$ {
	root /www/nginx/html; #$document_root调用root目录
	fastcgi_pass unix:/run/php-fpm/www.sock;
	#fastcgi_pass 127.0.0.1:9000;
	fastcgi_index index.php;
	#fastcgi_param SCRIPT_FILENAME /www/nginx/html$fastcgi_script_name;
	fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
	#如果SCRIPT_FILENAME是绝对路径则可以省略root /www/nginx/html;
	include fastcgi_params;
}

6.访问验证php测试页面
http://10.0.0.18/index.php

下一篇