nginx的主要功能
http服务器
http服务器的反向代理
imap/pop3邮件服务器
tcp/udp协议的伪四层负载均衡调度(stream),但是受到系统套接字数量的限制。
nginx的安装配置:
官方的预制包:http://nginx.org/packages/centos/7/x86_64/RPMS/
使用EPEL源安装下面的epel源,点击进去后选择适合的版本。
Fedora-EPEL
阿里云的epel源
编译安装:
yum groupinstall "Development Tools" "Server Platform Development"
yum install pcre-devel openssl-devel zlib-devel
useradd -r nginx
./configure --prefix=/usr/local/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_dav_module --with-http_stub_status_module --with-threads --with-file-aio
make && make install
Nginx的程序架构:
master/worker
一个master进程:
负载加载和分析配置文件、管理worker进程、平滑升级
一个或多个worker进程
处理并响应用户请求
缓存相关的进程:
cache loader:载入缓存对象
cache manager:管理缓存对象
特性:异步I/O、事件驱动和非阻塞I/O
并发请求处理:通过epoll/select
文件IO:高级IO sendfile,异步,mmap
介绍一下I/O模型
分为同步I/O和异步I/O
同步I/O:阻塞性I/O、非阻塞性I/O、复用性I/O、事件驱动性I/O
异步I/O:AIO(Linux)、LOCP(Windows)
一般有两种类型:网络I/O和磁盘I/O
I/O系统调用过程
第一步,用户空间的进程向内核发起调用,内核向磁盘调用资源到内核内存
第二步,进程把调用的资源从内核内存拷贝到用户空间的内存
类型
阻塞性(挂起进程),一直等待直到请求被处理,返回结果
非阻塞性(不挂起进程),进程不用一直等待数据处理结果,但会反复查看数据处理情况,直到数据处理完成。性能和阻塞性I/O差不多。
多路复用性I/O,I/O多路复用的函数也是阻塞的,但是其与以上两种还是有不同的,I/O多路复用是阻塞在select,poll这样的系统调用之上,而没有阻塞在真正的I/O系统调用如recvfrom之上。这个进程持续发起多个调用,但是也阻塞在多个调用上。一个进程会监控发起的多个系统调用。
函数
select()最多监控1024个请求
poll()
事件驱动性I/O:进程发起系统调用,发起调用之后进程可以去处理其他请求,等到数据包准备好后,系统通过进程留下的信息回调进程通知数据包准备完成。进程再去把数据复制到应用空间,但是这个复制过程还是阻塞的。使用epool函数
系统调用函数
epoll()epool使用句柄创建3个函数,没有连接最大限制
异步I/O,AIO:这类函数的工作机制是告知内核启动某个操作,并让内核在整个操作(包括将数据从内核拷贝到用户空间)完成后通知我们。
nginx模块:高度模块化,但其模块早期不支持DSO机制;近期版本支持动态装载和卸载;
模块分类:
核心模块:core module
标准模块:
HTTP modules:
Standard HTTP modules
Optional HTTP modules
Mail modules
Stream modules:传输层代理模块
3rd party modules:支持第三方模块
配置文件的组成部分:
主配置文件:nginx.conf
fastcgi, uwsgi,scgi等协议相关的配置文件
mime.types:支持的mime类型
主程序文件:/usr/sbin/nginx
启动脚本:nginx.service
变量
内建变量:由Nginx模块引入,可直接引用;
自定义变量:由用户使用set命令定义;
set variable_name value;
引用变量:$variable_name
nginx的内置变量
$args 此变量与请求行中的参数相等 注意我请求中的 referer 此变量表示我请求的所有参数
$args 这个变量等于GET请求中的参数。例如,foo=123&bar=blahblah;这个变量只可以被修改
$binary_remote_addr 二进制码形式的客户端地址。
$body_bytes_sent 传送页面的字节数
$content_length 请求头中的Content-length字段。
$content_type 请求头中的Content-Type字段。
$cookie_COOKIE cookie COOKIE的值。
$document_root 当前请求在root指令中指定的值。
$document_uri
$host 请求中的主机头(Host)字段,如果请求中的主机头不可用或者空,则为处理请求的server名称(处理请求的server的server_name指令的值)。值为小写,不包含端口。
$hostname 机器名使用 gethostname系统调用的值
$http_HEADER HTTP请求头中的内容,HEADER为HTTP请求中的内容转为小写,-变为_(破折号变为下划线),例如:$http_user_agent(Uaer-Agent的值), $http_referer...;
$sent_http_HEADER HTTP响应头中的内容,HEADER为HTTP响应中的内容转为小写,-变为_(破折号变为下划线),例如: $sent_http_cache_control,$sent_http_content_type...;
$is_args 如果$args设置,值为"?",否则为""。
$limit_rate 这个变量可以限制连接速率。
$nginx_version 当前运行的nginx版本号。
$query_string 与$args相同。
$remote_addr 客户端的IP地址。
$remote_port 客户端的端口。
$remote_user 已经经过Auth Basic Module验证的用户名。
$request_filename 当前连接请求的文件路径,由root或alias指令与URI请求生成。
$request_body 这个变量(0.7.58+)包含请求的主要信息。在使用proxy_pass或fastcgi_pass指令的location中比较有意义。
$request_body_file 客户端请求主体信息的临时文件名。
$request_completion 如果请求成功,设为"OK";如果请求未完成或者不是一系列请求中最后一部分则设为空。
$request_method 这个变量是客户端请求的动作,通常为GET或POST。包括0.8.20及之前的版本中,这个变量总为main request中的动作,如果当前请求是一个子请求,并不使用这个当前请求的动作。
$request_uri 这个变量等于包含一些客户端请求参数的原始URI,它无法修改,请查看$uri更改或重写URI。含有参数的完整的初始URI 如上例子就是
$scheme 所用的协议,比如http或者是https,比如rewrite ^(.+)$ $scheme://example.com$1 redirect;
$server_addr 服务器地址,在完成一次系统调用后可以确定这个值,如果要绕开系统调用,则必须在listen中指定地址并且使用bind参数。
$server_name 服务器名称。
$server_port 请求到达服务器的端口号。
$server_protocol 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
$uri 请求中的当前URI(不带请求参数,参数位于$args),不同于浏览器传递的$request_uri的值,它可以通过内部重定向,或者使用index指令进行修改。不包括协议和主机名,例如/foo/bar.html
$proxy_add_x_forwarded_for 变量包含客户端请求头中的"X-Forwarded-For",与$remote_addr用逗号分开,如果没有"X-Forwarded-For" 请求头,则$proxy_add_x_forwarded_for等于$remote_addr。$remote_addr变量的值是客户端的IP。
nginx管理工具的命令
-?,-h : 打开帮助信息
-v : 显示版本信息并退出
-V : 显示版本和配置选项信息,然后退出
-t : 检测配置文件是否有语法错误,然后退出
-T :检查配置文件并显示配置文件内容
-q : 在检测配置文件期间屏蔽非错误信息
-s signal : 给一个nginx主进程发送信号:stop(停止), quit(退出), reopen(重启), reload(重新加载配置文件)
-p prefix : 设置前缀路径(默认是:/usr/local/Cellar/nginx/1.2.6/)
-c filename : 设置配置文件(默认是:/usr/local/etc/nginx/nginx.conf)
-g directives : 设置配置文件外的全局参数
主配置文件结构:
main block:主配置段,也即全局配置段;
event { #事件驱动相关的配置;
...
}
http { #http/https 协议相关的配置段;
...
}
mail { #mail服务相关的配置段;
...
}
stream { #四层代理配置段;
...
}
配置指令:
main全局配置段常见的配置指令:
分类:
正常运行必备的配置
优化性能相关的配置
用于调试及定位问题相关的配置
事件驱动相关的配置
注意:
(1) 指令必须以分号结尾;
(2) 支持使用配置变量;
正常运行必备的配置:
1、user
Syntax: user user [group];
Default: user nobody nobody;
Context: main
#定义工作进程使用的用户和组凭据。 如果省略group,则使用其名称等于user的组。
2、pid /PATH/TO/PID_FILE;
指定存储nginx主进程进程号的文件路径;
3、include file | mask;
指明包含进来的其它配置文件片断;
4、load_module file; 新版本才支持
性能优化相关的配置:
1、worker_processes number | auto;
worker进程的数量;通常应该等于小于当前主机的cpu的物理核心数;
auto:当前主机物理CPU核心数;
2、worker_cpu_affinity cpumask ...; #绑定worker进程到一个cpu核心上,默认不绑定。
worker_cpu_affinity auto [cpumask];
nginx进程的CPU亲缘性;
CPU MASK:
0000 0001:0号CPU
0000 0010:1号CPU
0000 0100:2号CPU
#如果只有四核只用四个数值就行了,每次增加四个数值,手动绑定直接在选项后面写CPU编号,0000 0011:表示0和1号CPU;
3、worker_priority number;
指定worker进程的nice值,设定worker进程优先级;[-20,20]数值越小优先级越高。
4、worker_rlimit_nofile number;,进程每接收到一个请求,就要打开一个文件。
worker进程所能够打开的文件数量上限;
调试、定位问题:
1、daemon on|off; 在CentOS 6中是on,CentOS 7是off。 #是否以守护进程方式运行Nignx;
2、master_process on|off; #是否以master/worker模型运行nginx;默认为on;off为单进程
3、error_log file [level]; #日志文件存放位子和事件等级
事件驱动相关的配置:
events {
...
}
1、worker_connections number; #每个worker进程所能够打开的最大并发连接数数量;
#服务器最大并发数= worker_processes * worker_connections
2、use method; #指明并发连接请求的处理方法;可选项:select、poll、epoll,默认epoll
use epoll;
3、accept_mutex on | off; #处理新的连接请求的方法;on意味着由各worker轮流处理新请求,Off意味着每个新请求的到达都会通知所有的worker进程,worker去抢这个请求;
http协议的相关配置:下面的一些可以定义在HTTP中也可以定义在server中
http {
...
...:各server的公共配置
server {
...
}:每个server用于定义一个虚拟主机;
server {
listen
server_name
root
alias
location [OPERATOR] URL {
...
if CONDITION {
...
}
}
}
}
配置虚拟主机
每个nginx主机都是虚拟主机。
server { #配置一个虚拟主机;
listen address[:PORT]|PORT;
server_name SERVER_NAME;
root /PATH/TO/DOCUMENT_ROOT;
}
listen address[:port] [default_server] [ssl] [http2 | spdy] [backlog=number] [rcvbuf=size] [sndbuf=size]
#指定监听端口
default_server :设定为默认虚拟主机;
ssl :限制仅能够通过ssl连接提供服务;
backlog=number :后援队列长度;
rcvbuf=size :接收缓冲区大小;
sndbuf=size :发送缓冲区大小;
http2 :使用http2协议
server_name name ...; #指明虚拟主机的主机名称;后可跟多个由空白字符分隔的字符串;
#支持*通配任意长度的任意字符;server_name *.magedu.com www.magedu.*
#支持~起始的字符做正则表达式模式匹配;server_name ~^www\d+\.magedu\.com$
匹配机制:
(1) 首先是字符串精确匹配;
(2) 左侧*通配符;
(3) 右侧*通配符;
(4) 正则表达式;
tcp_nodelay on | off; #在keepalived模式下的连接是否启用TCP_NODELAY选项;
tcp_nopush on|off; #在sendfile模式下,是否启用TCP_CORK选项;
sendfile on | off; #是否启用sendfile功能;文件高效传输功能。
#定义路径相关的配置:
root path; #设置web资源路径映射;用于指明用户请求的url所对应的本地文件系统上的文档所在目录路径;可以放在这些字段中:http, server, location, if in location;
location [ = | ~ | ~* | ^~ ] uri { ... } Sets configuration depending on a request URI.
location /bbs {
root "/app/bbs";
} 这个字段表示url根下的web它的路径是放在/app/web下的bbs
#在一个server中location配置段可存在多个,用于实现从uri到文件系统的路径映射;ngnix会根据用户请求的URI来检查定义的所有location,并找出一个最佳匹配,而后应用其配置;
=:对URI做精确匹配;例如, http://www.magedu.com/,http://www.magedu.con/index.html.只能匹配第一个,因为第二个多了一个index.html,多一个字符就无法匹配。
~ :对URI做正则表达式模式匹配,区分字符大小写;
~*:对URI做正则表达式模式匹配,不区分字符大小写;
^~:对URI的左半部分做匹配检查,不区分字符大小写;
不带符号:以URI为前缀的所有uri;
#匹配优先级:=, ^~, ~/~*,不带符号;
alias path; #定义路径别名,文档映射的另一种机制;仅能用于location上下文;
#注意:location中使用root指令和alias指令的意义不同;
(a) root,给定的路径对应于location中的/uri/左侧的/;
(b) alias,给定的路径对应于location中的/uri/右侧的/;
index file ...;
error_page code ... [=[response]] uri; #定义针对指定的错误信息显示的指定的错误页。
error_page 404 /404.html; #这个还可把一个响应吗修改为其他的响应码。
location = /404.html {
root "/www/error_pages";
}
error_page 404 =200 /404.html 这个客户端触发404错误出但是服务器端反馈的是200的响应码
try_files file ... uri;
定义客户端请求的相关配置
keepalive_timeout timeout [header_timeout]; #设定保持连接的超时时长,0表示禁止长连接;默认为75s;
keepalive_requests number; #在一次长连接上所允许请求的资源的最大数量,默认为100;
keepalive_disable none | browser ...; #对哪种浏览器禁用长连接;
send_timeout time; #向客户端发送响应报文的超时时长,此处,是指两次写操作之间的间隔时长;
client_body_buffer_size size; #用于接收客户端请求报文的body部分的缓冲区大小;默认为16k;超出此大小时,其将被暂存到磁盘上的由client_body_temp_path指令所定义的位置;
client_body_temp_path path [level1 [level2 [level3]]]; #设定用于存储客户端请求报文的body部分的临时存储路径及子目录结构和数量;按照16进制的数字;
client_body_temp_path /var/tmp/client_body 1 2 2
1:表示用一位16进制数字表示一级子目录;0-f
2:表示用2位16进程数字表示二级子目录:00-ff
2:表示用2位16进程数字表示三级子目录:00-ff
对客户端进行限制的相关配置:
limit_rate rate; #限制响应给客户端的传输速率,单位是bytes/秒,0表示无限制;
limit_except method ... { ... } #限制对指定的请求方法之外的其它方法的使用客户端;
limit_except GET {
allow 192.168.1.0/24;
deny all;
} #表示除了GET之外的方法,只允许1.0网段使用。
文件操作优化的配置
aio on | off | threads[=pool]; #是否启用aio功能;异步I/O,建议开启;
directio size | off; #在Linux主机启用O_DIRECT标记,此处意味文件大于等于给定的大小时不在内核中不缓存,使用直接I/O例如directio 4m;
open_file_cache on|off; #是否开启缓存
open_file_cache max=N [inactive=time];
nginx可以缓存以下三种信息:
(1) 文件的描述符、文件大小和最近一次的修改时间;
(2) 打开的目录结构;
(3) 没有找到的或者没有权限访问的文件的相关信息;
max=N:可缓存的缓存项上限;达到上限后会使用LRU(最少最近)算法实现缓存管理;
inactive=time:缓存项的非活动时长,在此处指定的时长内未被命中的或命中的次数少于open_file_cache_min_uses指令所指定的次数的缓存项即为非活动项;
open_file_cache_valid time; #缓存项有效性的检查频率;默认为60s;
open_file_cache_min_uses number; #在open_file_cache指令的inactive参数指定的时长内,至少应该被命中多少次方可被归类为活动项;
open_file_cache_errors on | off; #是否缓存查找时发生错误的文件一类的信息;
常用模块的配置
ngx_http_access_module模块:实现基于ip的访问控制功能
allow address | CIDR | unix: | all;
deny address | CIDR | unix: | all; #设置访问控制要在后面定义一个默认策略。
可以放在:http、server、location、limit_except 字段中。
ngx_http_auth_basic_module模块,实现基于用户的访问控制,使用basic机制进行用户认证;
auth_basic string | off; #提示信息
auth_basic_user_file file; #用户文件路径
location /admin/ {
alias /webapps/app1/data/;
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.ngxpasswd;
}
注意:使用htpasswd创建授权用户文件,这个命令由httpd-tools所提供;
ngx_http_stub_status_module模块,用于输出nginx的基本状态信息;
stub_status;
配置示例:
location /basic_status {
stub_status;
}
查看到的信息
Active connections: 291
server accepts handled requests
16630948 16630948 31070465
Reading: 6 Writing: 179 Waiting: 106
Active connections :活动状态的连接数;
accepts :已经接受的客户端请求的总数;
handled :已经处理完成的客户端请求的总数;
requests :客户端发来的总的请求数;
Reading :处于读取客户端请求报文首部的连接的连接数;
Writing :处于向客户端发送响应报文过程中的连接数;
Waiting :处于等待客户端发出请求的空闲连接数;
ngx_http_log_module模块 定义http的访问格式
log_format name string ...;
string可以使用nginx核心模块及其它模块内嵌的变量;
"$http_x_forwarded_for 这个模块是用于后端服务器通过数据包的首部信息获取真正客户端的地址
access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
访问日志文件路径,格式及相关的缓冲的配置;
buffer=size
flush=time
access_log /app/test.log mian;
open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
open_log_file_cache off;
缓存各日志文件相关的元数据信息;
max:缓存的最大文件描述符数量;
min_uses:在inactive指定的时长内访问大于等于此值方可被当作活动项;
inactive:非活动时长;
valid:验正缓存中各缓存项是否为活动项的时间间隔;
ngx_http_gzip_module:压缩模块
gzip on | off; 是否启用压缩
gzip_comp_level level; #压缩等级,可选等级1-9默认是1。
gzip_disable regex ...; #不压缩的正则表达式匹配到的浏览器
gzip_min_length length; #启用压缩功能的响应报文大小阈值;
gzip_buffers number size; #支持实现压缩功能时为其配置的缓冲区数量及每个缓存区的大小;默认值为:gzip_buffers 32 4K或16 8K
gzip_proxied off | expired | no-cache | no-store | private | no_last_modified | no_etag | auth | any ...;nginx
#作为代理服务器接收到从被代理服务器发送的响应报文后,在何种条件下启用压缩功能的off:对代理的请求不启用,
默认值设置no-cache, no-store,private:表示从被代理服务器收到的响应报文首部的Cache-Control的值为此三者中任何
一个,则启用压缩功能;
gzip_types mime-type ... ; #压缩过滤器,仅对此处设定的MIME类型的内容启用压缩功能,默认为text/html
示例:
gzip on;
gzip_comp_level 6;
gzip_min_length 64;
gzip_proxied any;
gzip_types text/xml text/css application/javascript;
ngx_http_ssl_module模块:
ssl on | off; #是否启用ssl功能
ssl_certificate file; #当前虚拟主机使用PEM格式的证书文件;
ssl_certificate_key file; #当前虚拟主机上与其证书匹配的私钥文件;
ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2]; #支持ssl协议版本,默认为后三个;
ssl_session_cache off | none | [builtin[:size]] [shared:name:size]; # off关闭、none不启用
builtin[:size]:使用OpenSSL内建的缓存,此缓存为每worker进程私有;
[shared:name:size]:在各worker之间使用一个共享的缓存;
ssl_session_timeout time; #客户端一侧的连接可以复用ssl session ca che中缓存的ssl参数的有效时长;
配置示例:
server {
listen 443 ssl;
server_name www.magedu.com;
root /vhosts/ssl/htdocs;
ssl on;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
ssl_session_cache shared:sslcache:20m;
}
ngx_http_rewrite_module模块:将用户请求的URI基于regex所描述的模式进行检查,而后完成替换;
rewrite regex replacement [flag] #将用户请求的URI基于regex所描述的模式进行检查,匹配到时将其替换为replacement指定的新的URI;
#注意:如果在同一级配置块中存在多个rewrite规则,那么会自下而下逐个检查;被某条件规则替换完成后,会重新一轮的替换检查,
因此,隐含有循环机制;[flag]所表示的标志位用于控制此循环机制;
#如果replacement是以http://或https://开头,则替换结果会直接以重向返回给客户端;
[flag]:
last:重写完成后停止对当前URI在当前location中后续的其它重写操作,而后对新的URI启动新一轮重写检查;提前重启新一轮循环;
break:重写完成后停止对当前URI在当前location中后续的其它重写操作,而后直接跳转至重写规则配置块之后的其它配置;结束循环;
redirect:重写完成后以临时重定向方式直接返回重写后生成的新URI给客户端,由客户端重新发起请求;不能以http://或https://开头;
permanent:重写完成后以永久重定向方式直接返回重写后生成的新URI给客户端,由客户端重新发起请求;
return 提前返回
return code [text];
return code URL;
return URL;
Stops processing and returns the specified code to a client.
rewrite_log on | off; #是否开启重写日志;
if (condition) { ... } #引入一个新的配置上下文 ;条件满足时,执行配置块中的配置指令;可以放在,server, location;
condition:
比较操作符:
==
!=
~:模式匹配,区分字符大小写;
~*:模式匹配,不区分字符大小写;
!~:模式不匹配,区分字符大小写;
!~*:模式不匹配,不区分字符大小写;
文件及目录存在性判断:
-e, !-e
-f, !-f
-d, !-d
-x, !-x
ngx_http_referer_module模块:限制引用链接。
valid_referers none | block | server_names | string ...;
定义referer首部的合法可用值;
referer首部显示用户从哪个页面跳转到这个页面的。
none:请求报文首部没有referer首部;
block:请求报文的referer首部没有值;
server_names:参数,其可以有值作为主机名或主机名模式;
arbitrary_string:直接字符串,但可使用*作通配符;
regular expression:被指定的正则表达式模式匹配到的字符串;要使用~打头,例如 ~.*\.magedu\.com;
referer_hash_bucker_szie szie ; 保存的定义模式的hash值空间的初始大小
referer_hash_max_size szie ;保存hash值最大内存空间。
配置示例:
valid_referers none block server_names *.magedu.com *.mageedu.com magedu.* mageedu.* ~\.magedu\.;
if($invalid_referer) {
return http://www.magedu.com/invalid.jpg;
}
注:如果定义了合法引用,那么未定义的全为非法引用。
ngx_http_proxy_module模块:http代理模块。
proxy_pass URL; #后端服务器的地址
#注意:proxy_pass后面的路径不带uri时,其会将location的uri传递给后端主机;
server {
...
server_name HOSTNAME;
location /uri/ {
proxy http://hos[:port];
}
...
}
http://HOSTNAME/uri --> http://host/uri
#proxy_pass后面的路径是一个uri时,其会将location的uri替换为proxy_pass的uri;location和proxy_pass是映射关系,
如果location定义了/bbs,proxy_pass只写了http://192.168.166.1,没有写/bbs或根,那访问代理服务器的/bbs就会被代理到后端
的服务器的/bbs,也就是说访问代理服务器的路径就代理到后端服务器的同样的路径。
server {
...
server_name HOSTNAME;
location /uri/ {
proxy http://host/new_uri/;
}
...
}
http://HOSTNAME/uri/ --> http://host/new_uri/
#注:如果location定义uri时使用了正则表达式的模式,或在if语句或limt_execept中使用proxy_pass指令,则proxy_pass之后
必须不能使用uri; 用户请求时传递的uri将直接附加代理到的服务的之后;
server {
...
server_name HOSTNAME;
location ~|~* /uri/ {
proxy http://host;
}
...
}
http://HOSTNAME/uri/ --> http://host/uri/;
proxy_set_header field value; #设定发往后端主机的请求报文的请求首部的值;Context:http、server、location
proxy_set_header X-Real-IP $remote_addr; #定义一个请求首部,值为客户机的IP地址
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#$proxy_add_x_forwarded_for变量包含客户端请求头中的"X-Forwarded-For",与$remote_addr用逗号分开,如果没有"X-Fo
rwarded-For" 请求头,则$proxy_add_x_forwarded_for等于$remote_addr。$remote_addr变量的值是客户端的IP。当Nginx设置
X-Forwarded-For于$proxy_add_x_forwarded_for后会有两种情况发生:
1、如果从CDN过来的请求没有设置X-Forwarded-For头(通常这种事情不会发生),而到了我们这里Nginx设置将其设置为$proxy_
add_x_forwarded_for的话,X-Forwarded-For的信息应该为CDN的IP,因为相对于Nginx负载均衡来说客户端即为CDN,这样的话,后端的
web程序时死活也获得不了真实用户的IP的。
2、CDN设置了X-Forwarded-For,我们这里又设置了一次,且值为$proxy_add_x_forwarded_for的话,那么X-Forwarded-For的
内容变成 ”客户端IP,Nginx负载均衡服务器IP“如果是这种情况的话,那后端的程序通过X-Forwarded-For获得客户端IP,则取逗号分隔的
第一项即可。
如上两点所说,如果我们知道了CDN设置了X-Forwarded-For信息,且只有客户端真实的IP的话,那么我们的Nginx负载均衡服务器可以不必理会该头,让它默认即可。
proxy_cache_path #定义可用于proxy功能的缓存;Context:http
proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time][max_size=size][manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time]
[loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
格式:proxy_cache_path /app/cache keys_zone=aa:10m levels=1:2 max_size=2g;
keys_zone=aa:10m #定义一个缓存,名字为aa,大小为10m
levels=1:2 #定义缓存目录结构,1:2表示一级子目录是1个16进制数,二级子目录2个16进制数。
max_size=2g #缓存空间的最大空间
proxy_cache zone | off; #指明要调用的缓存,或关闭缓存机制;Context:http、server、location
proxy_cache_key string; #缓存中用于“键”的内容;可以是url,也可以是url后面的内容。
默认值:proxy_cache_key $scheme$proxy_host$request_uri;协议、主机、url
proxy_cache_valid [code ...] time; #定义对特定响应码的响应内容的缓存时长;
proxy_cache_valid 200 302 6m;
定义在http{...}中;
proxy_cache_path /var/cache/nginx/proxy_cache levels=1:1:1 keys_zone=pxycache:20m max_size=1g;
定义在需要调用缓存功能的配置段,例如server、location{...};
proxy_cache pxycache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 301 1h;
proxy_cache_valid any 1m;
proxy_cache_use_stale #后端主机无法访问时,是否可以使用缓存响应客户端请求。error
proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ...;
error #后端服务器发送了错误
timeout #后端服务器超时
invalid_header #后端服务器有一个非法的首部
updating #后端服务器正在更新
http_500 #后端服务器响应了502
http_50 ...
off 关闭
proxy_cache_methods GET | HEAD | POST ...; #允许哪些操作可以缓存。默认值为get、head
proxy_hide_header field; #隐藏缓存数据中响应给客户端的首部。默认:Date、Server、X-Pad、and X-Accel-By defult。
X-Powerer-by 隐藏php版本信息
proxy_connect_timeout time; #定义创建代理服务和后端服务器连接的超时时长。默认为60s;最长为75s;下面的默认值一样
proxy_read_timeout time; #后端服务器发给代理服务器响应报文的超时时长
proxy_send_timeout time; #发送给后端服务器请求报文的超时时长
ngx_http_headers_module模块,向由代理服务器响应给客户端的响应报文添加自定义首部,或修改指定首部的值;
add_header name value [always]; #添加自定义首部;
示例:
add_header X-Via $server_addr; #在发送给客户端的响应报文中添加代理服务器的IP
add_header X-Accel $server_name; #在发给客户端的响应报文中添加代理服务器的主机名
expires [modified] time;
expires epoch | max | off; #用于定义Expire或Cache-Control首部的值;
ngx_http_fastcgi_module模块:代理支持fastcgi服务,如PHP。
fastcgi_pass address; #定义后端动态页面服务器的地址
address为fastcgi server的地址; location, if in location;
http://www.ilinux.io/admin/index.php --> /admin/index.php (uri)/data/application/admin/index.php
fastcgi_index name; #fastcgi默认的主页资源;
fastcgi_param parameter value [if_not_empty]; #向后端的php服务器传递参数。比如请求资源的路径、这里用于向后端php服务器的资源路径
参数:要传递的参数列表在/etc/nginx/fastcgi_params文件中。
配置示例1:
前提:配置好fpm server和mariadb-server服务;
location ~* \.php$ { #这里匹配到的资源名成被定义成变量$fastcgi_script_name;传递给后端服务需要填写
root /usr/share/nginx/html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params; #定义这个配置包含要传递的参数定义文件
}
SCRIPT_FILENAME 表示传递给后端服务器的资源名和路径
配置示例2:通过/pm_status和/ping来获取fpm server状态信息;
location ~* ^/(pm_status|ping)$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
}
#注:访问代理服务器的pm_status路径时。可以看到php-fpm的连接池的状态。输入pm_status?full可以看到全部的状态
fastcgi_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time]
[max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number]
[loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time]
[purger_threshold=time];
#定义fastcgi的缓存;缓存位置为磁盘上的文件系统,由path所指定路径来定义;不带中括号的为必选。
levels=levels: #缓存目录的层级数量,以及每一级的目录数量;levels=ONE:TWO:THREE
leves=1:2:2
keys_zone=name:size #k/v映射的内存空间的名称及大小
inactive=time #非活动时长
max_size=size #磁盘上用于缓存数据的缓存空间上限
fastcgi_cache zone | off; #调用指定的缓存空间来缓存数据;http, server, location
fastcgi_cache_key string; #定义用作缓存项的key的字符串;
fastcgi_cache_methods GET | HEAD | POST ...; #为哪些请求方法使用缓存;
fastcgi_cache_min_uses number; #缓存空间中的缓存项在inactive定义的非活动时间内至少要被访问到此处所指定的次数方可被认作活动项;
fastcgi_cache_valid [code ...] time; #不同的响应码各自的缓存时长;
示例:
http {
...
fastcgi_cache_path /var/cache/nginx/fastcgi_cache levels=1:2:1 keys_zone=fcgi:20m inactive=120s;
...
server {
...
location ~* \.php$ {
...
fastcgi_cache fcgi;
fastcgi_cache_key $request_uri;
fastcgi_cache_valid 200 302 10m;
fastcgi_cache_valid 301 1h;
fastcgi_cache_valid any 1m;
...
}
...
}
...
}
fastcgi_keep_conn on | off; #默认情况下,fastcgi会关闭连接,但是我们可以设置长连接。这个选项提示是否开启长连接,on启动、off关闭
ngx_http_upstream_module :七层调度
upstream name { ... } #定义后端服务器组;引入一个新的上下文;只能用于http{}上下文中;
#注: 默认的调度方法是wrr;权重的调度方法是真实服务器的权重是几那就认为它有几虚拟服务器,然后按照虚拟服务器的总数进行轮询调度。 如果不设置默认每个服务器的权重都是1,等同与rr(轮询)。
server address [parameters] #定义服务器地址和相关的参数;
地址格式:
IP[:PORT]
HOSTNAME[:PORT]
unix:/PATH/TO/SOME_SOCK_FILE
参数:
weight=number# #权重,默认为1;
max_fails=number #探测服务器失败尝试的最大次数;
max_conns=number #最大连接数,新版本只有企业版支持
fail_timeout=time #设置服务器为不可用状态的超时时长;默认为10s,和max_fails对应
backup #把服务器标记为“备用”状态;
down #手动标记其为不可用;
算法
least_conn; #最少连接调度算法;当服务器的权重相同时为lc最小连接调度。当server拥有不同的权重时为wlc;当所有后端主机的连接数相同时,则使用wrr进行调度;
ip_hash; #源地址hash算法;能够将来自同一个源IP地址的请求始终发往同一个upstream server;
hash key [consistent]; #基于指定的key的hash表实现请求调度,此处的key可以文本、变量或二者的组合;
#注:consistent:参数,指定使用一致性hash算法;建议添加,不添加对应下面的第一个算法,添加对应第二个。
使客户端尽量调用到一台后端服务器的,而调度器又不需要记录对应表的算法有两种
- 余数hash:每一台服务器对应一个编号,客户端进行hash运算,运算出的值和编号总数进行取模运算,得出一台后端服务器,每次客户端访问时都会的到同一个结果。但是这个算法有些缺陷,当后端服务器的数量发生变化时会导致前面的取模结果失效。
2.一致性hash:先构造一个长度为232的整数环,根据节点名称的Hash值(其分布为0至232-1)将缓存服务器节点放置在这个Hash环上,然后根据需要缓存的数据的Key值计算得到其Hash值(其分布也为0至232-1),然后在Hash环上顺时针查找距离这个Key值的Hash值最近的服务器节点,完成Key到服务器的映射查找。缺点,hash环上的缓存服务器可能会出现偏斜,导致缓存服务器分布在非常临近的节点上。解决办法:调高缓存服务器的权重,从而可以生成较多的虚拟服务器,来分布在hash环上。
示例:
hash $request_uri consistent 。 #uri最为key可以提高缓存的命中率
hash $remote_addr
hash $cookie_name
keepalive connections; #可使用长连接的连接数量;每worker与后端服务保持的最大空闲长连接数量;
```
###### ngx_stream_core_module:伪四层调度核心模块
```
listen address:port [ssl] [udp] [backlog=number] [bind] [ipv6only=on|off] [reuseport]
[so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];
监听的端口;
默认为tcp协议;
udp: 监听udp协议的端口;
```
###### ngx_stream_proxy_module:伪四层调度
```
proxy_pass address; #后端服务器地址
proxy_timeout timeout; #设置两次读写操作之间的间隔,就是一次读写不成功的再次重试时间。默认为10m;
proxy_connect_timeout time; #设置nginx与被代理的服务器尝试建立连接的超时时长;默认为60s;
proxy_next_upstream on|off 默认on #给客户端调度了一台服务器,如果这台服务器无法访问时是否允许由调度器自动帮客户端调度到另一台服务器。
proxy_next_upstream_timeout time #重新给客户端调度的后端服务器的访问超时时间。
proxy_next_upstream_tries number #超时次数。超过此设置的次数为超时,默认为0,无限制。
示例:
stream {
upstream s shsrvs {
server 192.168.10.130:22;
server 192.168.10.131:22;
hash $remote_addr consistent;
}
server {
listen 172.16.100.6:22202;
proxy_pass sshsrvs;
proxy_timeout 60s;
proxy_connect_timeout 10s;
}
}
```
###### ngx_stream_log_module 代理日志功能,默认关闭,1.11.4支持
```
access_log path format [buffer=size] [gzip[=level]][flush=time][if=condition] off
示例:
stream {
log_format basic '$remote_addr [$time_local]'
'$protocol $status $bytes_sent $bytes_received'
'$session_time';
access_log /var/log/nginx/access.log basic;
}
```
###### ngx_stream_access_module 四层代理的访问控制
```
allow address cidr|unix|all
server {
deny 1.1.1.1;
allow 2.2.2.0/16;
deny all;
}
```