一、基本原理
1.linux上安装nginx:
(1)官网下载gz文件
(2)tar -xzvf xx.gz
(3)进入解压后的文件
(4)执行./configure 命令, 成功的话会展示以下提示
....
checking for zlib library ... found
creating objs/Makefile
Configuration summary
+ using system PCRE library
+ OpenSSL library is not used
+ using system zlib library
nginx path prefix: "/usr/local/nginx"
....
(5)make 编译源码
(6)make install 安装
(7)如果需要其他模块 比如tcp的负载均衡,可以使用
./configure --with-stream=dynamic
然后将/usr/local/nginx/objs 下的带有新模块的nginx 文件复制到/usr/local/nginx/sbin/ 目录下,cp /usr/local/nginx/objs/nginx /usr/local/nginx/sbin/nginx
参考官网: http://nginx.org/en/docs/configure.html
然后重复 make 和 make install 命令
2.如果正常启动后无法访问,那有可能是linux系统防火墙开启着
3.nginx支持高并发的原因(架构) :
(1)架构图
(2)主进程:
Nginx启动后会生成两种进程,一种是主进程(master),一种是工作进程(worker),工作进程是主进程的子进程 主进程不负责网络通信,只是管理worker进程,主要做三件事:
i.加载配置;ii.启动workers;iii.非停重启即./nginx -s reload
至少两个进程
(3)worker进程
i.每个worker进程中只有一个主线程,采用的是异步非阻塞的方式处理请求,要处理请求就是建立连接,接收发送数据,其实就是读写事件,如果是阻塞调用,那事件没准备好,线程就得一直等待,对于单线程,如果网络事件越来越多,那可能很多都没准备好,cpu就空余了出来,使用率上不去;
(3)nginx的做法是采用异步非阻塞事件驱动模型,
nginx 不会为每个连接fork一个进程或线程,而是使用了有限的单线程进程(workers),也节省了CPU周期,因为减少了很多线程的创建和销毁和切换同
时监控很多事件,单线程在请求之间不断地切换而已,切换也是因为异步事件未准备好,而主动让出的。这里的切换是没有任何代价,因为实际上是循环处理多个准备好的事件,好处是:不用创建很多线程占用内存资源,不用线程间上下文切换,并发再多也不用担心切换问题,只是会多占用一点内存而已;.多进程单线程的工作方式;参考:https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/
(4)worker的数量跟cpu核数一般相等,一个worker能够同时处理成百上千同时活跃的连接数(原因如3所描述)
(5)更新配置升级时 主线程指挥worker做两件事:
i.重新加载配置文件,并配置一组新的worker(进程号跟之前的完全不同),新的worker会马上开始工作
ii.指示旧的工作进程正常退出 ,工作进程停止接受新连接,但是会直到http发送数据完毕,一旦所有连接都关闭,则工作进程就退出
4.nginx常用命令 :
nginx -c /usr/local/nginx/conf/nginx.conf ,-c指定配置文件路径,如果不加则默认路径
nginx -s reload 重新加载配置文件
nginx -t 测试配置文件
nginx -s stop 停止nginx
nginx -V 显示nginx版本和配置参数
参考 https://mp.weixin.qq.com/s/55poBxwC6LxZ4jecSAxuyA
5.nginx从容停止
ps -ef |grep nginx
kill -QUIT nginx主进程号
6.nginx平滑重启
(1)nginx -s reload 需要一定的nginx版本支持
(2)kill -HUP 主进程号 通过信号量平滑重启
(3)ng平滑启动的过程:
i.向master发送HUP信号
ii.master收到信号之后校验语法
iii.创建新的worker进程来处理新的连接
iv.向之前的进程发送关闭监听的命令,之前的老进程会继续处理已经接收的请求,不再接收新的连接,处理完请求后关闭
7.惊群效应
accept惊群效应:以多进程为例,在主进程创建socket描述符listenfd后,子进程能够继承该描述符,那当主进程 创建了socket后,子进程会监听同一个端口,即都会调用accept()阻塞,当该端口接收到请求时,所有子进程都会被唤醒, 但竞争资源的情况下分最终只有一个子进程会处理请求,其他的子进程又会回到阻塞状态太,这中间进程状态的切换资源白白浪费,cpu占用会瞬间升高
8.nginx中对惊群效应的解决
在继承socket描述符之前先竞争互斥锁,抢到互斥锁的最终会确定处理请求,其他的子进程依然保持阻塞状态
9.信号控制 :通过kill 命令 向master进程发送信号
TERM, INT 快速关闭
QUIT 从容关闭
HUP 平滑重启,重新加载配置文件
USR1 重新打开日志文件,在切割日志时用途较大
USR2 平滑升级可执行程序
WINCH 从容关闭工作进程
二、基本配置
完整配置示例:
#运行用户
#user nobody;
# multiple workers works !工作进程
# 官网给的设置建议:最佳值取决于许多因素,包括(但不限于)CPU内核数,存储数据的硬盘驱动器数以及加载模式。如有疑问,将其设置为可用的CPU内核数将是一个不错的开始
worker_processes 1;
#全局错误日志及pid文件
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid指令 指定一个pid文件记录nginx的主进程,默认是logs文件夹内
pid logs/ nginx.pid;
#工作模式及连接数上限
events {
#epoll是多路复用IO中的一种方式
#use epoll
#单个后台work process最大的并发连接数
#并发总数(最大客户端连接数)= worker_processes 和 worker_connections 的乘积<=系统可操作的最大文件数
#worker_connections与内存大小有关系
#并发受IO约束,因此最大的并发数小于最大可打开的文件数,一般一G能打开10w文件
#如何查看系统能打开的文件句柄数:cat /proc/sys/fs/file-max
#综上:connections的值要根据worker_processes(一般等于CPU核数)和系统能操作的最大文件句柄数(VALUE)调整 使得
#connection*processes约等于最大VALUE
worker_connections 32768;
# max value 32768, nginx recycling connections+registry optimization =
# this.value * 20 = max concurrent connections currently tested with one worker
# C1000K should be possible depending there is enough ram/cpu power
# multi_accept on;
}
http {
#include /nginx/conf/naxsi_core.rules;
#设置mime类型,由mime.type决定
include mime.types;
#include指令 能够方便的增加符合语法的文件进来,方便用于多环境配置,该文件包含的内容就是一个包含多个upstream 的文件,类似还可以增加不同环境的location.conf
include custom_upstream.conf;
default_type application/octet-stream;
#设置日志格式
log_format main '$remote_addr $remote_port - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" $upstream_addr $upstream_status ';
#access_log logs/access.log main;
#指定nginx是否调用sendfile函数来输出文件(?)
sendfile on;
#tcp_nopush on;
server_names_hash_bucket_size 128;
请求体大小设置,默认1MB,一般上传文件等得改
client_max_body_size 100m;
## Start: Timeouts 请求超时时间 ##
client_body_timeout 30;
client_header_timeout 30;
keepalive_timeout 100;
send_timeout 30;
keepalive_requests 30;
#各种超时时间配置的解释说明 超时时间有点迷 https://blog.csdn.net/qq_29663071/article/details/80759098
## End: Timeouts ##
#开启gzip压缩
#gzip on;
#设置虚拟主机配置
# server {
# listen 80;
# server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
## Caching Static Files, put before first location
#location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
# expires 14d;
# add_header Vary Accept-Encoding;
#}
# For Naxsi remove the single # line for learn mode, or the ## lines for full WAF mode
# location / {
#include /nginx/conf/mysite.rules; # see also http block naxsi include line
##SecRulesEnabled;
##DeniedUrl "/RequestDenied";
##CheckRule "$SQL >= 8" BLOCK;
##CheckRule "$RFI >= 8" BLOCK;
##CheckRule "$TRAVERSAL >= 4" BLOCK;
##CheckRule "$XSS >= 8" BLOCK;
# root html;
# index index.html index.htm;
# }
# For Naxsi remove the ## lines for full WAF mode, redirect location block used by naxsi
##location /RequestDenied {
## return 412;
##}
# HTTPS server
#虚拟主机1
server {
listen 8030;
#主机名多个时 直接空格分开;
##格式1 全名称
##格式2 *.server2.com
##格式3 nginx.server2.*
##正则表达式配置时要加~,eg:server_name ~ ^www\.\d+\.com$
##以上几种匹配的优先级依次降低
#NGINX虚拟主机方式有三种:基于域名、基于端口、基于IP
#1)基于端口,即监听的端口不一样时,则是以端口为准(以往的配置)
#2)基于域名的配置,即当两个虚拟主机都监听80端口(即端口号一样),这是则会根据配置的域名不同,请求不同server
#3)基于ip配置server_name 没试过 不常用
server_name nginx.server1.com; #监听域名,这里的域名在windows的host里要映射一下ip地址
include customer_location.conf
#location /{
# proxy_pass http://serverswitch;
# }
location / {
proxy_pass http://serverswitch;
#定义服务器默认网站根路径的位置,相对路径,相对于nginx根路径
root html; #这个意思是说在nginx跟路径下需要创建一个html目录
index index.html; #默认跳转的路径,这里index.html就会在nginx根路径/html下寻找
}
}
# location / {
# root html;
# index index.html index.htm;
# }
upstream serverswitch { #upstream的命名不能有下划线,否则到RS中400错误
server 127.0.0.1:8070 weight=5;
server 127.0.0.1:8080 weight=5;
server 127.0.0.1:8060 weight=5;
keepalive 10;
}
#虚拟主机2配置
server {
listen 8040; #监听8040端口
error_log logs/8040error.error error;
#主机名多个时 直接空格分开;
#格式1 全名称
#格式2 *.server2.com
#格式3 nginx.server2.*
#正则表达式配置时要加~,eg:server_name ~ ^www\.\d+\.com$
#以上几种匹配的优先级依次降低
server_name localhost nginx.server2.com *.server2.com; #监听域名
location /{
root html;
index index.html;
proxy_pass http://serverswitch;
}
# error_page 500 502 503 504 /50x.html;#错误页
location /test/ {
rewrite ^/(.*) /test2.js break;
# proxy_pass http://serverswitch;
#定义服务器默认网站根路径的位置,相对路径,相对于nginx根路径
root html; #这个意思是说在nginx跟路径下需要创建一个html目录
index index.html; #默认跳转的路径
}
location /test2.js { #测试last和break区别用
if ( $server_port = 8030 ) {
return 404;
}
# default_type application/json;
return http://www.qq.com;
}
#配置nginx的状态监控
# location /nginx_status {
#stub_status on;
#access_log on;
# }
# #设定本虚拟主机的访问日志,main是上面定义的格式
access_log logs/nginx.access.log main;
}
#设置禁止访问的资源
#location ~/.ht{
#deny all
#}
}
custom_upstream.conf
upstream ascc_monitor_gw {
server 10.206.173.198:8082;
# check interval=3000 rise=2 fall=5 timeout=1000 type=http;
# check_http_send "HEAD /ascc-monitor-gw/check HTTP/1.0\r\n\r\n";
# check_http_expect_alive http_2xx http_3xx;
}
upstream dwss_gw{
server open-sss-new-apis.intsit.sfcloud.local:8000;
}
ps:nginx的监控stub_status需要特殊的模块
监控页面指标说明参考:http://www.ttlsa.com/nginx/nginx-status-detail/;
ps:nginx连接超时的配置:
https://www.bbsmax.com/A/WpdK4QxMzV/
10.nginx虚拟主机配置
(1)虚拟主机:虚拟主机,就是把一台物理服务器划分成多个"虚拟"的服务器,每一个虚拟主机都可以有独立的域名和独立的目录;体现在nginx.conf配置中就是多个server;为nginx提供了在同一台服务器,同一组nginx进程运行多个网站的功能,虚拟主机从外部访问的角度来看,跟独立的物理主机没有任何区别
(2)主机名的配置以及转发路径配置见配置文件注释
11.设置参考官网文档:
http://nginx.org/en/docs/beginners_guide.html
http://nginx.org/en/docs/
12.日志配置与切割
(1)访问日志揭露客户端访问nginx的每个请求,可以看到用户地域来源、跳转来源、使用终端、某个URL访问量等相关信息
(2)指令主要有两条,log_format 设置日志格式,access_log用来指定日志文件的存放格式、路径和缓存大小
(3)log_format配置解释见上面配置文件,允许的变量有:
日志格式允许包含的变量注释,如下所示
$remote_addr, $http_x_forwarded_for 记录客户端IP地址
$remote_user 记录客户端用户名称
$request 记录请求的URL和HTTP协议
$status 记录请求状态
$body_bytes_sent 发送给客户端的字节数,不包括响应头的大小; 该变量与Apache模块mod_log_config里的“%B”参数兼容。
$bytes_sent 发送给客户端的总字节数。
$connection 连接的序列号。
$connection_requests 当前通过一个连接获得的请求数量。
$msec 日志写入时间。单位为秒,精度是毫秒。
$pipe 如果请求是通过HTTP流水线(pipelined)发送,pipe值为“p”,否则为“.”。
$http_referer 记录从哪个页面链接访问过来的
$http_user_agent 记录客户端浏览器相关信息
$request_length 请求的长度(包括请求行,请求头和请求正文)。
$request_time 请求处理时间,单位为秒,精度毫秒; 从读入客户端的第一个字节开始,直到把最后一个字符发送给客户端后进行日志写入为止。
$time_iso8601 ISO86——01标准格式下的本地时间。
$time_local 通用日志格式下的本地时间。
(4)access_log 设置路径,见配置文件
access_log path(存放路径) [format(自定义日志格式名称) [buffer=size | off]],这个属性可以放在某个server中,每个server配置自己单独的日志
(5)日志切割,其实就是类似于log4j的每隔一旦时间定时备份旧日志文件
i.总体方法步骤;mv将原本的日志重新命令,然后Kill USR1向nginx主进程发命令,重新生成一个日志文件,使用crontab -e生成定时任务执行脚本
ii.sh脚本为:
#!/bin/bash
echo 开始执行脚本$0
date=`date +%Y-%m-%d_%H:%M:%S`
path=/usr/local/nginx/logs
mv ${path}/server1.log ${path}/${date}_server1.log
#发送kill -USR1信号给Nginx的主进程号,让Nginx重新生成一个新的日志文件
kill -USR1 `cat ${path}/nginx.pid`
echo 脚本$0执行结束===
iii.定时任务:执行上述脚本
crontab -e
25 21 * * * /bin/bash /home/shtest/nginx_log_config.sh
13.压缩输出配置
(1)压缩的原因是如果不压缩,大量的前台返回会占用很多带宽,导致传输和响应速度下降
(2)nginx具体配置如上所示,基本就是上面的配置,图片和视频一般不压缩,太耗cpu,解压效果也不稳定
(3)压缩前后对比,主要由压缩比控制
(4)判断网站是否有压缩 查看response head,有gzip标志则意味着有压缩
三、负载均衡策略
1.什么是负载均衡?
在存在提供多个相同服务的服务器情况下,即集群环境中,负载均衡设备比如nginx在大量请求访问来临时,根据配置的负载均衡算法,将流量
均衡的分配给后台的服务器,防止在总体能力有结余的情况下发生某台服务器因请求过多而导致响应变慢,甚至宕机;在存在负载均衡的情况下,对
客户端而言,RS(实际服务器)的地址即是负载均衡设备的虚拟IP地址,RS对于客户端是不可见且为止的
2.什么是反向代理和正向代理?
正向代理的过程,它隐藏了真实的请求客户端,服务端不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替来请求,某些科学上网工具扮演的就是典型的正向代理角色。用浏览器访问狗哥时,被残忍的block,于是你可以在锅外搭一台server,让proxy帮我去请求狗哥,代理把请求返回的相应结构再返回给我。
反向代理是代理的服务端,正向代理是代理的客户端
3.nginx负载均衡的方式
参考 https://mp.weixin.qq.com/s/EdmQQEXn2AGxu91g_uDYSA
(1)轮询(默认)
请求按照时间顺序逐一分发到配置的后端真实的服务器上,如果有down掉则剔除
i.配置:
upstream serverswitch {
server 127.0.0.1:8070;
server 127.0.0.1:8080;
server 127.0.0.1:8060 ;
}
ii.测试结果
直接kill掉8080的进程之后:
(2)按照权重分配
使用场景:weight和服务器被访问的几率成正比,用于解决后端服务器性能不均的情况
测试结果:
(3)ip_hash,对客户端ip进行hash,以后只要是同一个ip的访问都定位到一个后台服务器上,这样能避免session无法共享的问题出现
i.配置:
upstream serverswitch {
server 127.0.0.1:8070 ;
server 127.0.0.1:8080 ;
server 127.0.0.1:8060 ;
ip_hash; //ip_hash
}
ii.测试:当改配置并热重启后会发现后面来自同一个ip的请求都会被转发到同一个后台服务器上
iii.ip_hash的负载均衡方式有局限性:要求nginx必须为最前端的服务器,同时后端必须直接连接真是服务器,不能有其他代理机器;
如果不是最前端,那进行hash的ip始终是同一个,即代理机前面的代理机,那所有的请求最终都会请求到同一个服务器上,失去了负载均衡的作用;
如果后面不是真实的服务器,那经过hash的同一个ip会因为后面的代理机配置的负载均衡方式的不同而导致无法始终访问到同一个服务器
(4)fair模式,第三方模块,一般正常下载了nginx之后,还要再另外下载
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream backserver {
server server1;
server server2;
fair;
}
(5)url_hash 通过将url进行hash之后一般请求固定的RS,适用于服务器做了缓存的场景,不太理解
配置:
效果跟ip hash 有点像,都是同一个url请求同一个服务器
4.关于每个RS设备状态的配置:
(1)down 标记该RS暂时不参与负载均衡
配置
upstream serverswitch {
# hash $request_uri;
server 127.0.0.1:8070 down;
server 127.0.0.1:8080 backup;
server 127.0.0.1:8060 ;
}
测试结果:此时少了一台down掉的服务器
(2)backup
官网上的解释:只有当非backup的RS不可用时,才会使用该RS,配置类似于down,效果也类似
(3)weight=number,默认都是1,设置访问频率
(4)max_conns=number
限制number到代理服务器的同时活动连接的最大数量(1.11.5)。默认值为零,表示没有限制。如果服务器组未驻留在共享内存中,则此限制在每个工作进程中均有效。
(5)max_fails=number,未测试,来自官网说明
请求失败的次数,默认情况下,未成功尝试的次数设置为1,当超过最大次数时,则返回 proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream, memcached_next_upstream和 grpc_next_upstream 指令定义。
(6)fail_timeout=time
在指定次数的不成功尝试与服务器通信的时间内应该碰巧认为服务器不可用;
以及服务器将被视为不可用的时间段。默认情况下,该参数设置为10秒,会暂停服务
(7)官网 参考http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server
5.nginx的作用和优势
6. Location配置
ps:两种404的区别
(1)四种可选择标识符
i.= 精确匹配 要求请求的字符串和配置的uri严格匹配,匹配后则返回
eg:location = /test/ {}
请求为 http://192.168.1.108:8040/test/50x.html报apach的404
该精确匹配只能访问个默认的主页了,因为路径后面不能加别的,否则访问不到;
目前测试这种location = /test/ {} 配置精确匹配时,应该是由于自己又追加了一个默认的主页的原因导致无法请求到
ii.~表示区分大小写的正则匹配
eg:
location ~ /inner/{} //只要路径中出现inner就能匹配进去,
location ~ /[A-Za-z]nner{} // 请求:http://192.168.1.108:8040/test/Anner/ 可以匹配
location ~ /inner/.+\.(gif|css|png|js)$ {} //匹配路径中含有inner以及结尾必须是那几个的请求 http://192.168.1.108:8040/test/inner/1.js 能进去
http://192.168.1.108:8040/test/inner/.js 进不去,因为.js前面要求至少一个字符
iii. ~ 不区分大小写的正则匹配*
location ~* /inner/ {} 请求 :http://192.168.1.108:8040/tesA/INNer/ 可以匹配 匹配成功后立即结束
iv. ^~ 不进行正则,只匹配以关键字开头的uri,大小写敏感
location ^~ /inner/ {} 请求:http://192.168.1.108:8040/inner/50.html 可以进
http://192.168.1.108:8040/Inner/ 不能匹配
v 普通匹配
location /inner/ { 请求:http://192.168.1.108:8040/inner/test/50.html 可以匹配
http://192.168.1.108:8040/test/inner/50.html 无法匹配
# 与location顺序无关
# 若完全匹配成功,就不在继续匹配,否则还会进行正则匹配
}
(2)结合标识符,匹配顺序如下:
- =精确匹配>^~头字符匹配 >正则表达式 >前缀匹配, location ~ /test/{} //正则
location /test/{} 和 location ^~/test/{}不能同时存在 nginx检查不通过
location ^~/test/test{} 头字符匹配
location /test/{} 前缀匹配
eg:location ~/{} 和 location /{} 这第一个是正则,第二个是前缀,同时存在的话只会进第一个正则,因为正则>前缀
2)正则表达式都能匹配则按location配置的顺序进行,匹配成功后结束匹配
3)正则没匹配到,而前缀匹配匹配到的话,则使用前缀匹配,先匹配正则,匹配完****后没有成功则配前缀,匹配到则进前缀
4)都是前缀匹配,则匹配最长为原则
location /{} 和location /test/{} 这两个,请求为host/test/时 进第二个,因为第二个前缀比第一个长
(3)root和alias配置,alias暂时没成功实验出
(4)备注
备注;root test/; 这个表示nginx的主目录下的test/文件夹里找
root /test/;这个表示从linux服务器根路径下找test文件夹中的文件
index index.html ;表示默认主页为index.html
备注:location = /test/inner/{} 匹配后面一定要加上最后的斜杠,即最后一个斜杠必须有,否则请求进不来
ps:配置为root时 location中的路径会算到真实物理路径中去
location = /test/inner/{root html;} 这种最终找的是 nginx/html/test/inner中的文件
如果转发到RS的请求,那么location的路径会算到真实请求路径中去
location = /cluster1/{ proxy_pass http://serverswitch;root html;}后台请求的根路径就是cluster1
ps:location配置代理转发同时也配置nginx目录,那对于同一个(请求路径上啊完全相同)资源会先在RS上寻找,找到则直接返回,找不到才会去nginx指定的目录下去寻找
(5)nginx前后端分离,动静分离,ajax请求后端时仍可以写相对路径,因为仍是同一台服务器,/斜杠开始的就表示只到端口号,即根路径
location ~/test/{}
请求前端文件:
<script src="/test/js/test.js"></script> //在html页面请求js时路径也要满足location的配置,才能请求到,与后端的请求是一样的,都是以server端口号为跟路径
请求后端:
$(document).ready(function(){
$.ajax({
type: "GET",
url: "/cluster1/cluster", //相当于http://192.168.43.152:8040/cluster1/cluster,这个根路径是相对于nginx根路径而言的
success: function(data) {
alert("request success")
// $("#get_data").html(data)
},
error: function() {
alert("fail!!,请刷新再试!");
}
});
});
(5)实际使用时的配置至少有三个匹配规则定义:
#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。
#这里是直接转发给后端应用服务器了,也可以是一个静态首页
# 第一个必选规则
location = / {
proxy_pass http://tomcat:8080/index
}
# 第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项
# 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用
location ^~ /static/ {
root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
root /webroot/res/;
}
#第三个规则就是通用规则,用来转发动态请求到后端应用服务器
#非静态文件请求就默认是动态请求,自己根据实际把握
#毕竟目前的一些框架的流行,带.php,.jsp后缀的情况很少了
location / {
proxy_pass http://tomcat:8080/
}
proxy_pass可通过带路径进行路径替换
如下配置带路径dwss:
请求:http://localhost/ascc-web-gw/dwss/hello -->http://dwss_gw/dwss/hello
location /ascc-web-gw/dwss{
proxy_pass http://dwss_gw/dwss;
}
如下配置不带路径,只到服务器端口:
请求:http://localhost/ascc-web-gw/dwss/hello -->http://dwss_gw/ascc-web-gw/dwss/hello
location /ascc-web-gw/dwss{
proxy_pass http://dwss_gw;
}
7.nginx的rewrite规则
(1)作用:总体作用就是重定向
i.场景一 网址换新域名后,旧的访问跳转到新域名上
ii.动态url伪装成绩静态地址
(2)语法: rewrite ‘<regex’> <'replacement> flag ;
i.关键字rewrite 不可修改
ii.正则,即匹配的url模式,但凡符合该正则的url都会被重定向
iii.替代内容是当正则匹配成功之后,用来替换原本的url并跳转的新地址
iv.flag标记:last和break的区别见下面,都能拦截来自客户端的请求,然后重新发起替换之后的新请求;redirect 返回302临时重定向,浏览器url会跳转;permanent 返回301永久重定向,浏览器会跳转url显示;
v.301和302的区别 301永久重定向是响应会缓存,一般都使用301永久重定向符合url规定;302临时重定向,响应不会缓存,除非设置catche-control,默认是不缓存的
(3) 案例:
location /test/ {
rewrite ^/(.*) /test2/ break(或者last);
}
location /test2/ {
default_type application/json;
return 200 '{"status":"success"}';
}
//如果是break/last,可以通过浏览器请求 http://192.168.43.152:8040/test/,网络中显示的是直接请求的http://192.168.43.152:8040/test/,页面返回的是test2中的信息,不改url只改内容
//如果是redirect, 则浏览器网络中查看能看到发起了两个请求,第一个返回302,第二个200,页面显示test2内容,url发生重定向
//如果是permanent 则浏览器网络中查看能看到发起了两个请求,第一个返回301,第二个200,页面显示test2内容,url发生重定向
(4)rewrite只能放在server{},location{},if{}中
i.执行顺序:先执行server中的rewrite,再执行匹配到的location,最后再执行匹配到的location中的rewrite
i.last一般写在server和if中,break一般在location中
(5)if指令和内容如下
i.if指令的内容:表达式为变量时,值为空或者以0开头,则为fasle;
ii.使用=和!=比较值和内容大小;
iii. 正则表达式匹配,*不区分大小写的匹配,!~区分大小写的不匹配
iv.-f和!-f用来判断是否存在文件;-d和!-d用来判断是否存在目录;-e和!-e用来判断是否存在文件或目录
v举例:
location /test2/ {
if ( $server_port = 8030 ) { //此处的if后面一定要有空格,变量左右也要有空格,rewrite的语法要求非常严格
return 200 'dfd';
}
return 404; // 请求urlhttp://192.168.43.152:8040/test2/,页面会显示404
}
(6)nginx全局变量:
下面是可以用作if判断的全局变量
$args :#这个变量等于请求行中的参数,同$query_string;$content_length :请求头中的Content-length字段。
$content_type :请求头中的Content-Type字段。;$document_root :当前请求在root指令中指定的值。
$host :请求主机头字段,否则为服务器名称。
$http_user_agent :客户端agent信息;$http_cookie :客户端cookie信息
$limit_rate :这个变量可以限制连接速率。;$request_method :客户端请求的动作,通常为GET或POST。
'$remote_addr :客户端的IP地址。;$remote_port :客户端的端口。
'$remote_user :已经经过Auth Basic Module验证的用户名。;$request_filename :当前请求的文件路径,由root或alias指令与URI请求生成。
$scheme :HTTP方法(如http,https)。;$server_protocol :请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
$server_addr :服务器地址,在完成一次系统调用后可以确定这个值。;$server_name :服务器名称。
$server_port :请求到达服务器的端口号。;$request_uri :包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。;$uri :不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
$document_uri :与$uri相同。
(7)**return指令的用法**:
i.语法: return code [text];return code URL;return URL
ii.3xx系列响应码,url定义了重定向的路径; (1xx | 2xx | 4xx | 5xx) ["text"]需要定义返回的文本
iii.其他系列 如4xx系列 2xx系列,可以定义状态码加http标准文本进行正文返回,对于404,有些是浏览器已经定好了页面
eg:return http://www.qq.com ; // 这样直接重定向,返回的状态码为302,必须加请求协议,否则会当成返回码处理,然后报错
return 301 www.qq.com //返回的状态码为301
return 200 '{"status":"success"}'
iv.参考:https://hacpai.com/article/1543136511525
(9)last和break的区别
i.只在location中有区别,在server中没区别,都可以进行重定向
ii.break能够阻止进一步重定向发起新请求到location中,而last会进行重定向
eg:
location /test/ {
rewrite ^/(.*) /index.html break(last);
root html; #这个意思是说在nginx跟路径下需要创建一个html目录
index index.html; #默认跳转的路径
}
location /index.html {
if ( $server_port = 8030 ) {
return 404;
}
break时请求 http://192.168.43.152:8040/test/ 会跳转到root/test/index.html页面,不会发起新的请求,进入后面的location
last时,请求同样的则会跳转并请求新的location /index.html.返回页面404
iii.经测试,如果rewrite中是以下的配置,则break无法阻止发起新的请求匹配location
eg:
location /test/ {
rewrite ^/(.*) /index break;
root html; #这个意思是说在nginx跟路径下需要创建一个html目录
index index.html; #默认跳转的路径
}
location /index {
if ( $server_port = 8030 ) {
return 404;
}
//请求的 http://192.168.43.152:8040/test/ 会重新匹配到location /index 返回404页面
iv.总结 当rewrite替换的路径是文件的话,break起效果,直接请求本location中对应的文件,如上述第一个例子;如果是路径,则break跟last效果一样,目前测试的结论,未必准确
v.区别参考:https://blog.csdn.net/qq_37369726/article/details/102805695
(8)参考https://mp.weixin.qq.com/s/w_wuwdEzx5HPST0fsB5Dyg
ps:upstream的命名不能有下划线,否则到RS中400错误,类似其他的location等也不能有下划线
8 nginx的stream模块做tcp连接负载均衡
(1)安装stream模块
在解压的目录下执行
./configure --with-stream=dynamic
然后将/usr/local/nginx/objs 下的带有新模块的nginx 文件复制到/usr/local/nginx/sbin/ 目录下,cp /usr/local/nginx/objs/nginx /usr/local/nginx/sbin/nginx
参考官网: http://nginx.org/en/docs/configure.html
然后重复 make 和 make install 命令
(2)配置简单stream模块
其余配置可参考官网
#user nobody;
worker_processes auto;
#error_log logs/error.log;
error_log logs/error.log notice;
error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
#tcp负载均衡
stream {
upstream backend {
hash $remote_addr consistent;
server 10.206.20.16:3000 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3000;
}
server {
listen 12345;
proxy_connect_timeout 10s;
proxy_timeout 30s;
proxy_pass backend;
}
}
(3)重启nginx
sbin/nginx -s restart
(4)客户端tcp连接端口12345 就会发现负载均衡生效
(5)原理
nginx做tcp负载均衡时,后端连接断掉时,ng与客户端连接也会断掉,然后重新连后端,客户端与单机模式一样要有重连机制,当后端无可用服务时,nginx会拒绝客户端连接,负载均衡解决了单机故障的问题
支持的连接多 主要是只转发,每个连接占用内存极少,同时处理速度极快