用户速度体验的1-3-10原则
性能对用户的行为的影响
I/O介绍
NGINX比Apache性能优秀,与I/O模型密切相关
I/O模型常用概念
I/O模型分类
阻塞型、非阻塞型、复用型、信号驱动型、异步
I/O模型的具体实现
NGINX是免费,开源,高性能的HTTP和反向代理服务器,邮件代理服务器,通用TCP/UDP代理服务器
nginx高度模块化,1.9.11版本支持DSO机制
DSO:动态支持模块的加载或卸载
编译安装
[root@hai7-2 sbin]$wget http://nginx.org/download/nginx-1.14.1.tar.gz
[root@hai7-2 sbin]$tar xvf nginx-1.14.1.tar.gz
[root@hai7-2 sbin]$yum groupinstall "development tools"
[root@hai7-2 sbin]$yum install pcre-devel openssl-devel zlib-devel
[root@hai7-2 sbin]$useradd -r -s /sbin/nologin nginx
1. '进入解压目录'
[root@hai7-2 ~]$cd nginx-1.14.1/
2. '编辑如下文件,找到所示行'
[root@hai7-2 nginx-1.14.1]$vim src/core/nginx.h
版本信息
#define NGINX_VERSION "9.8.6"
服务名称
#define NGINX_VER "moli/" NGINX_VERSION
3. '修改禁用服务信息后,头部信息'
[root@hai7-2 nginx-1.14.1]$vim src/http/ngx_http_header_filter_module.c
配置文件中修改禁止显示版本信息后,头部显示的Server内容
static u_char ngx_http_server_string[] = "Server: moli" CRLF;
[root@hai7-2 nginx-1.14.1]$/configure --prefix=/usr/local/nginx / <==安装路径
--conf-path=/etc/nginx/nginx.conf / <==主配置文件安装位置
--sbin-path=/usr/sbin/nginx <==指明nginx程序文件安装路径
--error-log-path=/var/log/nginx/error.log / <==错误日志文件安装位置
--http-log-path=/var/log/nginx/access.log / <==访问日志文件安装位置
--pid-path=/var/run/nginx.pid / <==指明pid文件安装位置
--lock-path=/var/run/nginx.lock / <==锁文件安装位置
--http-client-body-temp-path=/var/cache/nginx/client_temp <==客户端body部分的临时文件存放路径,服务器允许客户端使用put方法提交大数据时,临时存放的磁盘路径
--http-proxy-temp-path=/var/cache/nginx/proxy_temp <==作为代理服务器,服务器响应报文的临时文件存放路径
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp <==作为fastcgi代理服务器,服务器响应报文的临时文件存放路径
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp <==作为uwsgi代理服务器,服务器响应报文的临时文件存放路径
--http-scgi-temp-path=/var/cache/nginx/scgi_temp <==作为scgi反代服务器,服务器响应报文的临时文件存放路径
--user=nginx / <==指明以那个身份运行worker进程,主控master进程一般由root运行
--group=nginx / <==指明组运行身份
--with-http_ssl_module / <==加密相关模块
--with-http_v2_module / <==是否支持http2.0版本
--with-http_dav_module / <==是否支持dav
--with-http_stub_status_module /
--with-threads / <==是否启用线程
--with-file-aio <==是否启用异步IO
[root@hai7-2 nginx-1.14.1]$make && make install
rpm包安装
[root@hai7-1 ~]$yum -y install nginx
[root@hai7-1 ~]$getent passwd
nginx:x:988:982:Nginx web server:/var/lib/nginx:/sbin/nologin
[root@hai7-1 ~]$ rpm -q --scripts nginx
1. 'nginx可以直接输入服务名来启动,以此方式启动,不受systemctl控制,不能以systemctl关闭,需要以选项-s控制载入或关闭等'
[root@hai7-1 ~]$nginx
[root@hai7-1 ~]$nginx -s stop
2. '传统方式启动'
[root@hai7-1 ~]$systemctl start nginx
文件说明
nginx命令说明
nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]
默认不加任何选项为启动nginx-h
:查看帮助选项-v
:只显示版本信息-V
:查看版本和编译选项-t
测试nginx语法错误-T
:检测并显示配置文件信息-q
:在检测语法时,压缩掉非错误信息-c filename
:指定配置文件(default: /etc/nginx/nginx.conf)-s signal
:发送信号给master进程,signal:stop, quit, reopen, reload-g directives
:在命令行中指明全局指令include /usr/share/nginx/modules/*.conf; <==此目录下的配置内容,可以生效
1. '主语句块'
main block: <==主配置段,即全局配置段,对http,mail都有效
event {
...
} <==事件驱动相关的配置
2. 'http语句块'
http {
...
} http/https 协议相关配置段
include /etc/nginx/conf.d/*.conf; <==关于http的配置文件,放在此目录也可以生效
3. '邮件语句块'
mail {
...
} mail 协议相关配置段,默认没有
4. 'stream语句块'
stream {
...
} stream 服务器相关配置段,默认没有
http {
...
... 各server的公共配置
server { 每个server用于定义一个虚拟主机
...
}
server {
...
server_name 虚拟主机名
root 主目录
alias 路径别名
location [OPERATOR] URL { 指定URL的特性
...
if CONDITION {
...
}
}
}
}
正常运行必备的配置:例如nginx以什么身份运行
优化性能相关的配置:例如并发连接数设置
用于调试及定位问题相关的配置:日志文件
事件驱动相关的配置:例如设置I/O模型
帮助文档
http://nginx.org/en/docs/
user username [group];
user nginx;
pid /PATH/TO/PID_FILE;
pid /run/nginx.pid;
include file | mask;
include mime.types;
include vhosts/*.conf;
load_module file ;
load_module modules/ngx_mail_module.so;
worker_processes number | auto;
worker进程的数量;通常应该为当前主机的cpu的物理核心数,auto表示自动匹配cpu核心数
支持环境: main
worker_processes auto;
worker_cpu_affinity auto [cpumask] ;
cpu亲源性设置,绑定cpu有利于使用cpu缓存
[cpumask] : 00000001(0号CPU)
支持环境: main
1. '8个cpu,分别绑定写法如下'
[root@hai7-1 ~]$vim /etc/nginx/nginx.conf
worker_cpu_affinity 0001 0010 0100 1000 10000 100000 1000000 10000000;
2. '查看绑定效果'
[root@hai7-1 ~]$watch -n1 'ps axo pid,cmd,psr |grep nginx'
3. '利用其它主机测试'
[root@hai7-2 ~]$ab -c 100 -n 2000 http://192.168.50.101
worker_priority number;
指定worker进程的nice值,设定worker进程优先级:[-20,19]
支持环境: main
1. '将nice值设置为-10'
[root@hai7-1 ~]$vim /etc/nginx/nginx.conf
worker_priority -10;
2. '查询优先级ni参数'
[root@hai7-1 ~]$watch -n1 'ps axo pid,cmd,psr,ni |grep nginx'
21518 nginx: worker process 0 -10
worker_rlimit_nofile number;
worker进程所能够打开的文件数量上限,如65535
支持环境: main
[root@hai7-1 ~]$vim /etc/nginx/nginx.conf
worker_rlimit_nofile number 51200;
worker_connections number;
worker_processes * worker_connections
[root@hai7-1 ~]$vim /etc/nginx/nginx.conf
events {
worker_connections 1024;
}
use method;
use epoll;
accept_mutex on | off;
daemon on|off;
1. '默认状态下开启进程状态'
[root@hai7-1 ~]$pstree -p |grep nginx
|-nginx(18721)-+-nginx(21518 <==18721为master进程
2. '设置为off'
[root@hai7-1 conf.d]$vim /etc/nginx/nginx.conf
master_process off
3. '修改后开启进程状态'
[root@hai7-1 ~]$pstree -p |grep nginx
|-nginx(27054) <==只有一层master,没有workter
error_log file [level] ;
--with-debug
选项时才有效/path/logfile
: 记录到文件中stderr
:发送到标准错误syslog
:server-address[,parameter=values] 发送到syslogmemory:size
:存到循环存储器中,可以通过size指定大小1. '设置虚拟机web页面'
[root@hai7-1 data]$mkdir websiter{1,2}
[root@hai7-1 data]$echo /data/website2/index.html > websiter2/index.html
[root@hai7-1 data]$echo /data/websiter/index.html > websiter1/index.html
2. '配置一个虚拟主机,在http块的子配置文件中设置,格式如下,不需要加http{,服务会自动匹配'
[root@hai7-1 ~]$vim /etc/nginx/conf.d/vhosts.conf
server {
listen 80;
server_name www.a.com www.b.com;
root /data/websiter1;
}
server {
listen 80 default_server; <==将主配置文件中默认页面删掉,在自定义虚拟机加上default_server,就会成为新的默认页,没有指定默认页将以配置文件顺序显示
server_name www.c.com ;
root /data/websiter2;
}
3. '在另外一台主机上测试'
'修改hosts文件,模拟DNS解析,DNS解析过程会带主机头,虽然最后都解析为同一个IP地址,但会根据主机头判断需要返回的页面结果'
[root@hai7-2 ~]$vim /etc/hosts
192.168.50.101 www.a.com www.b.com www.c.com
'测试'
[root@hai7-2 ~]$curl www.a.com
/data/websiter/index.html
[root@hai7-2 ~]$curl www.c.com
/data/websiter2/index.html
listen PORT|address[:port]|unix:/PATH/TO/SOCKET_FILE
listen address[:port] [default_server] [ssl] [http2 | spdy] [backlog=number] [rcvbuf=size] [sndbuf=size];
default_server
:设定为默认虚拟主机ssl
:限制仅能够通过ssl连接提供服务backlog=number
:超过并发连接数后,新请求进入后援队列的长度rcvbuf=size
: 接收缓冲区大小sndbuf=size
: 发送缓冲区大小server_name *.c.com www.c.* ;
支持~起始的字符做正则表达式模式匹配,性能原因慎用server_name ~^b.*\.a\.com$;
*
通配符 如:*.a.com
*
通配符 如:www.a.*
~^.*\.magedu\.com$
tcp_nodelay on | off;
sendfile on | off;
server_tokens on | off | build | string
root
1. '指定虚拟机web页面路径'
[root@hai7-1 ~]$vim /etc/nginx/conf.d/vhosts.conf
server {
...
root /data/website1;
}
2. '在目录下建立一个新的目录,并创建web页面,测试如下'
[root@hai7-1 ~]$mkdir /data/website1/news
[root@hai7-1 ~]$echo news > /data/website1/news/index.html
[root@hai7-2 ~]$curl www.a.com/news/
news
3. '在目录下建立一个软连接'
[root@hai7-1 websiter1]$ln -s /nginx/test bbs
4. '在另一台主机上测试,可以返回结果,支持软连接'
[root@hai7-2 ~]$curl www.a.com/bbs/
location [ = | ~ | ~* | ^~ ] uri { ... }
1. '定义配置文件'
server {
server_name www.a.com;
location /news { <==定义Uri为news
root /data2/newsdir; <==定义Uri的根目录
}
}
2. '建立测试页'
[root@hai7-1 ~]$mkdir -pv /data2/newsdir/news
[root@hai7-1 ~]$echo testnews > /data2/newsdir/news/index.html
3. '测试,访问news,实际访问地址为/data2/newsdir/news,也就是说可以单独定义每个url的根目录'
[root@hai7-2 ~]$curl www.a.com/news/
testnews
=
对URI做精确匹配;server {
server_name www.a.com;
location = /news { <==使用等号定义Uri为news
root /data2/newsdir; <==定义Uri的根目录
}
}
测试访问news目录下2018目录,会报错,精确匹配不会显示uri下的目录,只能
[root@hai7-2 ~]$curl www.a.com/news/2018
^~
对URI的最左边部分做匹配检查,不区分字符大小写~
对URI做正则表达式模式匹配,区分字符大小写~*
对URI做正则表达式模式匹配,不区分字符大小写location ~* \.(gif|jpg|jpeg)$ { <==以gif|jpg|jpeg结尾的资源
root /data2/newsdir ;
alias path;
设置示例,访问www.a.com/bbs相当于查看www.a.com/web/forum/
location /bbs {
alias /web/forum/;
}
index file ...;
error_page code ... [=[response]] uri;
1. '定义配置'
[root@hai7-1 conf.d]$vim /etc/nginx/conf.d/vhosts.conf
server {
listen 80;
server_name www.a.com ;
root /data/websiter1;
error_page 404 =302 /error_404.html; <==定义返回的错误页面,修改错误码为200
2. '创建错误页面内容'
[root@hai7-1 ~]$echo 404 error > /data/websiter1/error_404.html
3. '测试'
[root@hai7-2 ~]$curl -i http://www.a.com/xxx.html
HTTP/1.1 302 OK <==返回的错误码显示为302
404 error <==错误页面
try_files file ... uri;
访问/images时,搜索$uri路径,如果不存在则回退/images/fish.jpg,回退URI必须为uri路径
[root@hai7-1 ~]$vim /etc/nginx/conf.d/vhosts.conf
server {
server_name www.a.com www.b.com;
root /data/websiter1;
location /images {
try_files $uri /images/fish.jpg ;
}
}
keepalive_timeout ;
keepalive_timeout 0;
keepalive_requests number;
keepalive_disable none | browser ...;
send_timeout time;
client_body_buffer_size size;
client_body_temp_path path [level1 [level2 [level3]]];
1. '配置文件设置格式,表示设置三级目录, 1 2 2表示三级目录每级所占位数'
client_body_temp_path /var/tmp/client_body 1 2 2
2. '假设缓存数据为index.html,其哈希结果如下所示'
[root@hai7-1 websiter1]$md5sum index.html
0d6a914877e53e2957172f5e46bb5755 index.html
3. '存放目录为3级目录,共有16*256*256=1048576个目录'
一级目录取最后一位
5(一级目录占一个16位数,范围在0-f)
二级目录取倒数2-3位
75(二级目录占两个16位数,范围在00-ff)
三级目录取倒数4-5位
b5(三级目录占两个16位数,范围在00-ff)
limit_rate rate;
bytes/second
,默认值0表示无限制limit_rate 10240
limit_except method ... { ... }
,仅用于locationlocation / {
limit_except GET {
allow 192.168.1.0/24;
deny all;
}
}
aio on | off | threads[=pool];
directio size | off;
open_file_cache off; open_file_cache max=N [inactive=time];
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
open_file_cache_errors on | off;
open_file_cache_min_uses number;
open_file_cache_valid time;
可实现基于ip的访问控制功能
allow address | CIDR | unix: | all;
deny address | CIDR | unix: | all;
location / {
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
allow 2001:0db8::/32;
deny all;
}
实现基于用户的访问控制,使用basic机制进行用户认证
# comment
name1:password1
name2:password2:comment
name3:password3
1. '工具来源'
[root@hai7-1 websiter1]$rpm -qf /usr/bin/htpasswd
httpd-tools-2.4.6-80.el7.centos.x86_64
2. '生成第一个用户口令文件,需要加-c选项'
[root@hai7-1 websiter1]$htpasswd -cm /etc/nginx/conf.d/.httpuser user1
3. '查看生成的用户口令'
[root@hai7-1 websiter1]$cat /etc/nginx/conf.d/.httpuser
user1:$apr1$DwtBgJYJ$KW3UEzDSOtsC5jnHji6Yb.
4. '生成第二个用户口令,不能加-c,会覆盖前面的用户信息'
[root@hai7-1 websiter1]$htpasswd -m /etc/nginx/conf.d/.httpuser user2
location /admin/ {
auth_basic "Admin Area"; <==验证提示语句
auth_basic_user_file /etc/nginx/.ngxpasswd; <==提供用户口令文件
}
用于输出nginx的基本状态信息,默认情况下不生成此模块,应使用--with-http_stub_status_module
配置参数
stub_status;
location test_status { <==test_status可以自定义,查看信息的uri
stub_status; <==状态信息设置
allow 192.168.50.102/24; <==权限设置
deny all;
}
访问页面,192.168.50.101为测试机IP地址http://192.168.50.101/test_status
Active connections: 291
server accepts handled requests
16630948 16630948 31070465
Reading: 6 Writing: 179 Waiting: 106
log_format name string ...;
string可以使用nginx核心模块及其它模块内嵌的变量log_format combined '$remote_addr - $remote_user [$time_local] '
| 日志名 | 客户端地址 - 远程用户 【当前系统时间】
'"$request" $status $body_bytes_sent '
uri 状态码 回应报文body大小
'"$http_referer" "$http_user_agent" "$gzip_ratio"';
从哪个页面跳转来的 浏览器类型 压缩比
$time_iso8601
:本地时间(ISO 8601标准格式)$request_time
:请求处理时间(以秒为单位),分辨率为毫秒;从客户端读取第一个字节与发送最后一个字节后的日志写入之间的时间$request_length
:请求长度(包括请求行、标头和请求正文)$msec
:以毫秒表示写入时间$connection_requests
:通过一个连接提出的当前请求数(1.1.18)$connection
:连接序列号$bytes_sent
:发送给客户端的字节数`access_log` path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
`access_log off`
环境:http、server、location、if in location、limit_exceptpath
:日志文件路径format
: 日志格式名称buffer=size
:启用后日志文件中当时可能看不到,过一会写入后才可以显示flush=time
:buffer多久写入一次gizip
:压缩,要使gzip压缩工作,必须使用zlib库构建nginxlog_format testlog '$remote_addr - $remote_user [$time_local] '
调用格式放在http子配置文件中access_log /var/log/nginx/a.com.log testlog;
`open_log_file_cache` max=N [inactive=time] [min_uses=N] [valid=time];
`open_log_file_cache off;`
环境:http, server, locationmax
:缓存的最大文件描述符数量,超出后关闭最小最近使用(LRU)描述符min_uses
:在inactive指定的时长内访问大于等于此值方可被当作活动项inactive
:非活动时长valid
:验证缓存中各缓存项是否为活动项的时间间隔off
:禁用缓存open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;
用gzip方法压缩响应数据,节约带宽
gzip on | off;
gzip_comp_level
level;gzip_disable
regex …;gzip_min_length
length;gzip_http_version 1.0 | 1.1
;gzip_buffers
number size;gzip_types
mime-type …;gzip_types text/plain application/xml;
gzip_vary
on | off;gzip_proxied off | expired | no-cache | no-store | private | no_last_modified | no_etag | auth | any ...;
gzip on;
gzip_comp_level 6;
gzip_min_length 64;
gzip_proxied any;
gzip_types text/xml text/css application/javascript <==系统根据后缀识别类型
ssl on | off;
ssl_certificate
file;server {
listen 443 ssl;
server_name example.com;
ssl_certificate example.com.rsa.crt; <==主证书
ssl_certificate_key example.com.rsa.key;
ssl_certificate example.com.ecdsa.crt; <==中间证书
ssl_certificate_key example.com.ecdsa.key;
}
ssl_certificate_key
file;ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache off | none | [builtin[:size]] [shared:name:size];
ssl_session_cache none
ssl_session_timeout
time;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;
ssl_session_timeout 10m;
}
[root@hai7-1 ~]$vim /etc/pki/tls/certs/Makefile
%.key: <==找到此项
umask 77 ; \
/usr/bin/openssl genrsa -aes128 $(KEYLEN) > $@ <==修改前
/usr/bin/openssl genrsa $(KEYLEN) > $@ <==修改后
[root@hai7-1 certs]$make a.com.crt
Common Name (eg, your name or your server's hostname) []:www.a.com <==网站名要匹配nginx
[root@hai7-1 certs]$mv a.com.* /etc/nginx/conf.d/
[root@hai7-1 ~]$vim /etc/nginx/conf.d/vhosts.conf
server {
listen 80 default_server ;
listen 443 ssl; <==启用HTTPS protocol
server_name www.a.com ; <==服务名
root /data/websiter1;
ssl_certificate /etc/nginx/conf.d/a.com.crt; <==自签证书路径
ssl_certificate_key /etc/nginx/conf.d/a.com.key; <==私钥路径
}
1. 不加密访问
[root@hai7-2 ~]$curl http://www.a.com/
/data/websiter/index.html
2. 加密访问
[root@hai7-2 ~]$curl -k https://www.a.com
/data/websiter/index.html
将用户请求的URI基于regex(正则表达式)所描述的模式进行检查,匹配到时将其替换为
replacement指定的新的URI
指令rewrite用法
rewrite regex replacement [flag]
location /bbs {
rewrite ^/bbs/(.*)$ /forum/$1 last; <==$1表示后项引用,引用/bbs后的所有内容
}
测试,访问bbs,配置last或break后,bbs目录可以不存在,一样可以调度到地址,访问路径不会变;如果使用redirect或permanent,访问路径会改变,告诉用户重新发新RUI的请求[root@hai7-2 ~]$curl http://www.a.com/bbs/
/data/websiter1/forum/index.html <==返回forum目录下的文件
更换域名时重定向设置,例如访问www.a.com域名将要淘汰,使用新域名www.b.comlocation / { <==设置为访问/时跳转
rewrite / http://www.b.com permanent ;
}
如果只跳转特定后缀路径,写法如下location ~ \.txt$ {
rewrite (.*)\.txt$ $1.html;
}
官方示例,将media或audio替换为mp3,保留$1和$2,后缀替换为mp3或raserver {
...
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
return 403;
...
}
有http跳转到https第一个虚拟服务器,http服务监听80端口
server {
listen 80 default_server ;
server_name www.a.com ;
root /data/websiter1;
location / { <==location中指定访问根时,跳转到https
rewrite / https://www.a.com;
}
}
第二个虚拟服务器,https监听端口443
server {
listen 443 ssl;
server_name www.a.com ;
root /data2/newsdir;
ssl_certificate /etc/nginx/conf.d/a.com.crt;
ssl_certificate_key /etc/nginx/conf.d/a.com.key;
}
方法二,将http与https放在同一个虚拟服务上,通过if判断协议来打破循环出错,如果不指定if条件判断($scheme为控制协议的nginx系统变量),会跳转https后继续访问 / ,一次次匹配,直到报错server {
listen 80 default_server ;
listen 443 ssl;
server_name www.a.com ;
root /data/websiter1;
ssl_certificate /etc/nginx/conf.d/a.com.crt;
ssl_certificate_key /etc/nginx/conf.d/a.com.key;
location / {
if ( $scheme = http ){ <==通过if判断,协议为http时跳转至https
rewrite / https://www.a.com ;
}
}
}
指令return用法
停止处理,并返回给客户端指定的响应码,对 301, 302, 303, 307, 308跳转到URL
return code [text];
return code URL;
return URL;
location /admin {
return 403 "just do it!!!" ;
}
location /admin {
return 307 http://www.baidu.com ;
}
指令rewrite_log 用法,默认为off状态
是否开启重写日志, 发送至error_log(notice level)
rewrite_log on | off;
指令set用法
为变量赋值,value 可包含:文本,变量,或文本和变量的组合
set $variable value;
指令if用法
指定判断条件condition,如果为真则执行{…}中指定的模块指令,并且将括号内的配置应用到 HTTP 请求上
if (condition) { ... }
=
:相同!=
:不同~
:模式匹配,区分字符大小写~*
:模式匹配,不区分字符大小写!~
:模式不匹配,区分字符大小写!~*
:模式不匹配,不区分字符大小写-e,!-e
:存在与否(包括文件,目录,软链接)-f,!-f
:文件-d,!-d
:目录-x,!-x
:执行if ( $scheme = http ){ <==通过if判断,协议为http时跳转至https
rewrite / https://www.a.com ;
}
用来阻止Referer首部无有效值的请求访问,可防止盗链
valid_referers none|blocked|server_names|string ...;
$invalid_referer
:nginx变量,表示无效的首部valid_referers none block server_names *.b.com b.* ~\.baidu\. ~\.google\.;
if ($invalid_referer) {
return 301 http://www.b.com;
}
反向代理, 转发请求至另一台主机
proxy_pass URL;
location / {
proxy_pass http://192.168.50.104/ ;
}
1. 'location只转发部分固定类型文件写法,使用正则表达时,转发地址结尾不能带/,否则属于语法错误'
location ~ \.txt$ {
proxy_pass http://192.168.50.104 ;
}
2, 'location只转发部分目录写法'
location /bbs {
标准端口写法
proxy_pass http://192.168.50.104 ; <==结尾没有/
非标准端口写法
proxy_pass http://192.168.50.104:8080; <==支持端口映射
}
语法:proxy_set_header field value;
支持环境:http, server, location
在后端服务器日志中显示真实访问客户端IP地址
修改后端服务器日志记录格式,增加客户端ip地址项%{clientip}i
[root@hai7-2 ~]$vim /etc/httpd/conf/httpd.conf
LogFormat "... \"%{clientip}i\"" combined
默认情况下,X-Forwarded-For请求头不会自动添加到请求头中,即Nginx Backend的$http_x_forwarded_for输出为空,所以需要通过proxy_set_header X-Real-IP $remote_addr;
把真实客户端IP写入到X-Real-IP中
在代理服务器上修改配置,将remote_addr追加至clientip中,此时remote_addr为客户端IP,所以clientip显示的值为客户端IP
remote_addr:代表客户端的IP,但它的值不是由客户端提供的,而是服务端根据客户端的ip指定的,当你的浏览器访问某个网站时,假设中间没有任何代理,那么网站的web服务器(Nginx,Apache等)就会把remote_addr设为你的机器IP,如果你用了某个代理,那么你的浏览器会先访问这个代理,然后再由这个代理转发到网站,这样web服务器就会把remote_addr设为这台代理机器的IP
location / {
proxy_pass http://192.168.50.104 ;
proxy_set_header clientip $remote_addr; <==clientip为日志变量,将真实IP写入其中
}
使用客户端访问代理服务器,查看后端服务器日志记录,会生成,访问客户端的IP地址记录,示例中的192.168.50.102
[root@hai7-2 ~]$tail -f /var/log/httpd/access_log
192.168.50.101 - - [14/Nov/2018:07:56:58 +0800] "GET / HTTP/1.0" 200 14 "-" "curl/7.29.0" "192.168.50.102"
根据用户请求分别调度到对应后台服务器上
server {
listen 80 default_server ;
server_name www.a.com ;
root /data/websiter1;
location / {
proxy_pass http://192.168.50.104 ;
proxy_set_header host $host; <==追加主机名头部信息
}
}
server {
listen 80 ;
server_name mobi.a.com ;
location / {
proxy_pass http://192.168.50.104 ;
proxy_set_header host $host;
}
}
server {
listen 80 ;
server_name app.a.com ;
location / {
proxy_pass http://192.168.50.104 ;
proxy_set_header host $host;
}
}
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
X-Forwarded-For
与$remote_addr
用逗号合起来,如果请求头中没有X-Forwarded-For
则$proxy_add_x_forwarded_for
为$remote_addr
X-Forwarded-For: client1, proxy1, proxy2
同构代理动静分离设置
location ~ \.php$ { <==访问php结尾的页面,代理发送至105
proxy_pass http://192.168.50.105 ;
proxy_set_header host $host;
}
location / { <==其他没有指定的内容代理发送至104
proxy_pass http://192.168.50.104 ;
proxy_set_header clientip $remote_addr;
proxy_set_header host $host;
}
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];
levels
表示生成3级目录,每一级占1个16位数可以生成16个目录;keys_zone
表示起名为v9并将请求URI哈希值放在缓存中最大为20M;max_size=1g
指磁盘存入文件内容的缓存空间最大值;inactive表示缓存有效期1. '在主配置文件中http语句块中定义缓存'
[root@hai7-1 ~]$vim /etc/nginx/nginx.conf
proxy_cache_path /var/cache/nginx/cache levels=1:1:1 keys_zone=v9:20m inactive=120s max_size=1g;
2. '在子配置文件中修改虚拟主机设置,启用缓存功能'
[root@hai7-1 ~]$vim /etc/nginx/conf.d/vhosts.conf
proxy_cache v9 <==在主配置中定义的缓存名,表示启用缓存
proxy_cache_key $request_uri <==在主配置中定义的缓存名
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_key $scheme $proxy_host $request_uri;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ...
proxy_cache_use_stale off;
proxy_cache_methods GET | HEAD | POST ...;
proxy_cache_methods GET HEAD;
proxy_hide_header field;
[root@hai7-2 ~]$curl -i http://app.a.com
ETag: "e-57a8bc4ef60a2"
Accept-Ranges: bytes
在反向代理服务器上设置,再次产看,ETag会被隐藏location / {
proxy_hide_header ETag;
}
proxy_connect_timeout time;
proxy_send_timeout time;
proxy_read_timeout time;
向由代理服务器响应给客户端的响应报文添加自定义首部,或修改指定首部的值
1. '在代理服务器上修改配置文件'
add_header X-Via $server_addr;
add_header X-Cache $upstream_cache_status( nginx内部变量,用来显示缓存状态);
add_header X-Accel $server_name;
2. '客户端测试'
[root@hai7-2 ~]$curl -i www.a.com
X-Via: 192.168.50.101 <==头部信息新添加的部分
X-Cache: HIT
X-Accel: www.a.com
add_trailer name value [always];
转发请求到FastCGI服务器,nginx不支持php模块方式
fastcgi_pass address;
fastcgi_index name;
fastcgi_index index.php;
配置语法
fastcgi_param parameter value [if_not_empty];
支持环境
http, server, location
对于PHP最少需要设置的变量,$fastcgi_script_name表示脚本文件请求的路径,也就是说当访问www.a.com/index.php的时候,需要读取网站根目录下面的index.php文件,如果没有配置这一配置项时,nginx不会去网站根目录下访问.php文件,所以返回空白
fastcgi_param SCRIPT_FILENAME /home/www/scripts/php$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
示例:搭建fastcgi
方法一:独立设置php服务器
• 配置php服务器
安装php服务器,这里测试,不安装数据库
[root@hai7-2 ~]$yum install php-fpm
修改php服务器配置,使其可以对外提供服务器
[root@hai7-2 ~]$vim /etc/php-fpm.d/www.conf
listen = 0.0.0.0:9000 <==修改为监听本地所有地址的9000端口
#listen.allowed_clients = 127.0.0.1 <==注释掉此项,默认为允许所有人访问
pm.status_path = /status <==启用此项,可以通过/status了解php工作情况
ping.path = /ping <==测试此php服务器是否是活跃的
ping.response = pong <==如果活跃,回应pong
建立php服务器测试页面,启动服务
[root@hai7-2 ~]$mkdir /data/php -pv
[root@hai7-2 ~]$vim /data/php/test.php
<?php
phpinfo();
?>
[root@hai7-2 ~]$systemctl start php-fpm.service
• 配置代理服务器nginx
设置fastcgi专用模块
[root@hai7-1 ~]$vim /etc/nginx/conf.d/php.conf
server {
listen 80 default_server ;
server_name www.a.com ;
root /data/website1;
index index.php; <==定义默认主站点为php
location ~ \.php$ {
fastcgi_pass 192.168.50.105:9000; <==指定fastcgi服务器地址及端口
fastcgi_index text.php; <==指定fastcgi默认的主页资源
fastcgi_param SCRIPT_FILENAME /data/php$fastcgi_script_name; <==指定fastcgi服务器php程序存放路径
include fastcgi_params; <==调用协调参数文件
}
'通过/status和/ping来获取fpm server状态信息'
location ~* ^/(status|ping)$ {
include fastcgi_params;
fastcgi_pass 192.168.50.105:9000;
fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
}
location / {
proxy_pass http://192.168.50.104 ;
}
}
测试,获取fpm server状态信息
[root@hai7-2 ~]$curl http://www.a.com/ping
pong
[root@hai7-2 ~]$curl http://www.a.com/status <==查看详细信息可以写成status?full
方法二:将fastcgi和nginx放在同一台服务器中
不需要监听9000端口了,可修改为监听socket文件,在nginx服务器上安装php-fpm,修改配置文件
[root@hai7-2 ~]$vim /etc/php-fpm.d/www.conf
listen=/run/php-fcgi.sock
修改nginx配置文件
location ~ \.php$ {
fastcgi_pass unix:/run/php-fcgi.sock; <==将地址修改为监听套接字
fastcgi_index text.php;
fastcgi_param SCRIPT_FILENAME /data/php$fastcgi_script_name;
include fastcgi_params;
}
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_cache zone | off;
fastcgi_cache_key string;
fastcgi_cache_key $request_rui;
fastcgi_cache_methods GET | HEAD | POST ...;
fastcgi_cache_methods GET HEAD;
fastcgi_cache_min_uses number;
fastcgi_cache_min_uses 1;
fastcgi_keep_conn off;
http {
fastcgi_cache_path /var/cache/nginx/fcgi_cache levels=1:2:1
keys_zone=fcgicache:20m inactive=120s;
server {
location ~* \.php$ {
...
fastcgi_cache fcgicache;
fastcgi_cache_key $request_uri;
fastcgi_cache_valid 200 302 10m;
fastcgi_cache_valid 301 1h;
fastcgi_cache_valid any 1m;
...
}
}
用于将多个服务器定义成服务器组,而由proxy_pass, fastcgi_pass等指令进行引用,常用于配置反向代理调度器
upstream name { ... }
unix:/PATH/TO/SOME_SOCK_FILE
IP[:PORT]
HOSTNAME[:PORT]
weight=number
:权重,默认为1server 192.168.50.104 weight=3;
max_conns
: 连接后端报务器最大并发活动连接数,1.11.5后支持max_fails=number
:失败尝试最大次数;超出此处指定的次数时,server将被标记为不可用,默认为1fail_timeout=time
:后端服务器标记为不可用状态的连接超时时长,默认10sbackup
: 将服务器标记为“备用”,即所有服务器均不可用时才启用down
: 标记为“不可用”,调度服务器就不会将请求发送至标记的后端服务器,可以用来实现灰度发布server 192.168.50.104 down;
[root@hai7-1 ~]$vim /etc/nginx/nginx.conf
http { <==主配置文件中的http语句块中
upstream httpserver { <==自定义组名,本次实验命名为httpserver
server 192.168.50.104; <==后端服务器地址,server为固定格式
server 192.168.50.105;
server 127.0.0.1:8080 backup; <==定义备用服务器,当后端服务器都宕机时,备用服务器登场,端口需要独立指定,不能与后端服务器相同
}
在http子配置文件中设置虚拟机[root@hai7-1 ~]$vim /etc/nginx/conf.d/vhosts.conf
server { <==设置备用虚拟服务器
listen 8080; <==端口设置,与主配置文件中定义的端口项匹配
root /data/websiter1;
}
server {
listen 80 default_server ;
server_name www.a.com ;
root /data/websiter1;
location / {
proxy_pass http://httpserver ; <==代理调度地址为后端服务器组(在主配置中自定义的组名)
}
}
backup
不兼容,二者只能设置一个;缺陷在于局域网中使用同一个公网IP,导致调度不合理,支持的语句块Context: upstream
upstream httpserver { <==在定义的upstream语句块中
ip_hash; <==在upstream中添加即可启用
}
upstream httpserver {
least_conn;
consistent
参数,将使用ketama一致性hash算法,适用于后端是Cache服务器(如varnish)时使用
hash key [consistent]
$request_uri
(nginx系统变量,表示请求URI)进行哈希运算取模,调度到响应缓存服务器upstream httpserver {
hash $request_uri; <==权重hash算法
hash $uri; <==使用变量$uri也可以
hash $request_uri consistent <==一致性hash算法
如果指定为ip地址,功能与ip_hash相同upstream httpserver {
hash $remote_addr;
keepalive connections;
keepalive 32;
health_check [parameters];
2^32
个点,缓存服务器IP地址哈希运算后对2^32
进行取模当做node,将需要放在缓存服务器的文件名进行哈希运算对2^32
进行取模作为键(后端服务器IP哈希值+随机数)/2^32
,得到9个虚拟节点,一次类推;理论上节点越多模拟反代基于tcp或udp的服务连接,即工作于传输层的反代或调度器
stream {
upstream mysqlsrvs {
server 192.168.22.2:3306;
server 192.168.22.3:3306;
least_conn;
}
server {
listen 10.1.0.6:3306;
proxy_pass mysqlsrvs;
}
}
listen address:port [ssl] [udp] [proxy_protocol] [backlog=number] [bind]
[ipv6only=on|off] [reuseport]
[so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];
可实现代理基于TCP,UDP (1.9.13), UNIX-domain sockets的数据流
proxy_pass address;
proxy_timeout timeout;
proxy_connect_timeout time;
stream {
upstream mysqlsrvs {
server 192.168.0.10:3306;
server 192.168.0.11:3306;
hash $remote_addr consistent;
}
server {
listen 172.16.100.100:3306;
proxy_pass mysqlsrvs;
proxy_timeout 60s;
proxy_connect_timeout 10s;
}
}
由于默认的Linux内核参数考虑的是最通用场景,这明显不符合用于支持高并发访问的Web服务器的定义,所以需要修改Linux内核参数,是的Nginx可以拥有更高的性能,根据业务特点来进行调整,当Nginx作为静态web内容服务器、反向代理或者提供压缩服务器的服务器时,期内核参数的调整都是不同的,这里针对最通用的、使Nginx支持更多并发请求的TCP网络参数做简单的配置,修改/etc/sysctl.conf来更改内核参数
fs.file-max = 999999
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_rmem = 10240 87380 12582912
net.ipv4.tcp_wmem = 10240 87380 12582912
net.core.netdev_max_backlog = 8096
net.core.rmem_default = 6291456
net.core.wmem_default = 6291456
net.core.rmem_max = 12582912
net.core.wmem_max = 12582912
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_tw_recycle = 1
net.core.somaxconn=262114
net.ipv4.tcp_max_orphans=262114
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_tw_recycle = 1
net.core.somaxconn=262114
net.ipv4.tcp_max_orphans=262114