实用手册:https://wizardforcel.gitbooks...
1 nginx基础操作
1.1 nginx安装
# yum快速安装
yum -y install pcre pcre-devel zlib zlib-devel openssl openssl-devel
# 编译安装
wget http://nginx.org/download/nginx-1.14.1.tar.gz
tar -zxvf nginx-1.14.1.tar.gz
./configure --prefix=/usr/local/nginx \
--with-http_stub_status_module \
--with-http_gzip_static_module\
--with-http_realip_module\
--with-http_sub_module \
--with-http_ssl_module\
--with-http_realip_module \
--with-http_sub_module \
--with-http_gunzip_module\
--with-http_gzip_static_module\
--with-http_auth_request_module\
--with-http_random_index_module \
--with-http_slice_module \
--with-http_stub_status_module
make && make install
# 查看加载的模块及版本信息
nginx -V
1.2 nginx常用命令
# 查看Nginx的版本号
nginx -V
# 停止
nginx -s stop
# 退出
nginx -s quit
# 重启加载配置
nginx -s reload
# 配置文件启动
nginx -c </path/to/config>
# </path/to/config> 为 Nginx 指定一个配置文件,来代替缺省的
# 不运行,而仅仅测试配置文件
nginx -t
# nginx 将检查配置文件的语法的正确性,并尝试打开配置文件中所引用到的文件。
1.3 nginx控制信号
再次回过头看看nginx的原理图,我们还可以通过信号去操作nginx
,默认情况下nginx
将其主进程的pid
写入到/usr/local/nginx/nginx.pid
文件中。
# nginx 停止命令,等所有请求结束后关闭服务。(从容关闭)
Kill -QUIT nginx 主进程号
# 重新载入配置。用新的配置开始新的工作进程,从容关闭旧的工作进程
kill -HUP nginx 主进程号
# 快速关闭
kill -TERM nginx 主进程号
# 或
kill -INT nginx 主进程号
# 重新打开日志文件
kill -USR1 nginx 主进程号
# 平滑升级可执行程序
kill -USR2 nginx 主进程号
# 从容关闭工作进程
kill -WINCH nginx 主进程号
2 nginx配置说明
2.1 基础配置说明
配置语法说明:
1、配置文件由指令与指令块构成
2、每条指令以;分号结尾,指令与参数间以空格符号分隔
3、指令块以{}大括号将多条指令组织在一起
4、使用#符号添加注释,提高可读性
5、include语句允许组合多个配置文件以提升可维护性
6、使用$符号使用变量
7、部分指令的参数支持正则表达式
Nginx的各种指令以及配置繁多,有些配置可以在如下的链接 https://tengine.taobao.org/nginx_docs/cn/docs/ 或者在官方文档上查看
为了对配置功能进行可扩展化,并对相关配置能进行明确的区分,让配置看见就能很明了。采用了模块化配置。
nginx常用模块
http模块
http标准核心模块,http服务的相应配置
server模块
接收请求的服务器需要将不同的请求按规则转发到不同的后端服务器上,在 nginx 中我们可以通过构建虚拟主机(server)的概念来将这些不同的服务配置隔离。
server_name
由于IP地址的数量有限,因此经常存在多个主机域名对应着同一个IP地址的情况,这时在 nginx.conf
中就可以按照server_name(对应用户请求中的主机域名)
并通过server块来定义虚拟主机,每个server
块就是一个虚拟主机,它只处理与之相对应的主机域名请求。这样,一台服务器上的 Nginx 就能以不同的方式处理访问不同主机域名的HTTP
请求了。
语法:
主机名称
语法: server_name name[...];
默认: server_name"";
配置块: server
虚拟主机名可以使用确切的名字,通配符,或者是正则表达式来定义,在开始处理一HTTP
请求时, Nginx
会取出header
头中的Host
,与每个server
中的server_name
进行匹配,以此决定到底由哪一个server
块来处理这个请求。有可能一个Host
与多个server
块中的server_name
都匹配,这时就会根据匹配优先级来选择实际处理的server
块。
注意:优先级问题,所导致的配置不生效
server_name与Host的匹配优先级如下:
1)首先选择所有字符串完全匹配的server_name,如 nginx.2367.com 。
2)其次选择通配符在前面的server_name,如 *.2367.com。
3)再次选择通配符在后面的server_name,如nginx.2367.* 。
4)最后选择使用正则表达式才匹配的server_name,如 ~^\.testweb\.com$
如果都不匹配
1、优先选择listen配置项后有default或default_server的
2、找到匹配listen端口的第一个server块
location(URL匹配特定位置后的设置)
location
部分用于匹配网页位置(比如,根目录“/”,“/images”,等等),server
是对应一个域名进行的配置,而location
是在一个域名下对更精细的路径进行配置
语法:
语法: location[=|~|~*|^~|@]/uri/{...}
配置块: server
location会尝试根据用户请求中的URI来匹配上面的/uri表达式,如果可以匹配,就选择
location{}块中的配置来处理用户请求。当然,匹配方式是多样的,下面介绍location的匹配
规则。
location表达式类型:
~ 表示执行一个正则匹配,区分大小写;
~* 表示执行一个正则匹配,不区分大小写;
^~ 表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其他location;
= 进行普通字符精确匹配。也就是完全匹配;
@ 它定义一个命名的 location,使用在内部定向时,例如 error_page, try_files
优先级:
(location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径)
等号类型(=)的优先级最高。一旦匹配成功,则不再查找其他匹配项。
前缀普通匹配(^~)优先级次之。不支持正则表达式。使用前缀匹配,如果有多个location匹配的话,则使用表达式最长的那个。
正则表达式类型(~ ~*)的优先级次之。一旦匹配成功,则不再查找其他匹配项。
常规字符串匹配,如果有多个location匹配的话,则使用表达式最长的那个。
root(文件路径的定义)和alias(以别名方式设置资源路径)
以root方式设置资源路径
语法:
语法: root path;
配置块: http、server、location、if
以别名方式设置资源路径
语法:
语法: alias path;
配置块: location
alias也是用来设置文件资源路径的,它与root的不同点主要在于如何解读紧跟location后面的uri参数
注意: location中使用root指令和alias指令的意义不同
- root,相当于追加在root目录后面 。比如访问的是 xxx/test=>/www/test
- alias,相当于对location中的uri进行替换,比如访问的是 xxx/test,想要访问到/www/test就必须设置 alias /www/test
2.2 nginx内置变量说明
Nginx
同Apache
和Lighttpd
等其他 Web 服务器的配置记法不太相同,Nginx
的配置文件使用语法的就是一门微型的编程语言。可以类似写程序一般编写配置文件,可操作性很大。既然是编程语言,一般也就少不了“变量”这种东西。
所有的Nginx
变量在Nginx
配置文件中引用时都须带上$
前缀在Nginx
配置中,变量只能存放一种类型的值,有且也只存在一种类型,那就是字符串类型
使用 set 配置指令对变量 $a 进行了赋值操作set $hello "hello world" ;
Nginx
变量一旦创建,其变量名的可见范围就是整个Nginx
配置,甚至可以跨越不同虚拟主机的server
配置块Nginx
变量名的可见范围虽然是整个配置,但每个请求都有所有变量的独立副本,或者说都有各变量用来存放值的容器的独立副本,彼此互不干扰Nginx
内置变量存放在ngx_http_core_module
模块中
3 常用模块配置或者实践案例
3.1 IP和目录权限访问控制配置
IP访问控制模块
用来对特定IP的进行访问控制。默认是允许所有ip访问,若部分允许需定义deny all
allow
语法: allow address | CIDR | unix: | all;
默认值: —
区块: http, server, location, limit_except
允许某个ip或者一个ip段访问
deny
语法: deny address | CIDR | unix: | all;
默认值: —
区块: http, server, location, limit_except
allow、deny实例
对IP的访问的控制
location / { deny 192.168.1.1; # 拒绝IP访问 allow 192.168.1.0/24; # 允许IP段访问 allow 47.98.147.49; # 允许IP访问 deny all; # 启用IP控制 }
对目录文件的访问
比如可以限制某些目录下的某些文件的访问,具体可以自己组合。# 禁止访问所有目录下的 sql|log|txt|jar|sh|py 后缀的文件, location ~.*\.(sql|log|txt|jar|war|sh|py|php) { deny all; }
3.2 限流模块
场景:抢购的场景,下载限速下就会有涉及运用
限流:主要是当访问量达到一个限制量的时候可以选择以服务器为主要,而选择对用户访问请求的量做限制,对于超出限制的用户请求会采取丢弃或者延迟处理等方式处理,来保证更多用户来访问处理。
比如:某一服务器正常在高峰期上能支持的访问量是1w,但是突然某一时刻在访问量上突然暴增一下子超过3w,5w则可能会导致服务器宕机,这个时候我们就可以通过设置最大的访问如1分钟访问8000次。也可以防止攻击(对同一个ip每秒访问多少次)如:30min/次
原理:令牌桶算法
对应模块:
ngx_http_limit_conn_module
限制连接数ngx_http_limit_reg_module
限制请求频率
3.2.1 ngx_http_limit_req_module限制请求频率
https://tengine.taobao.org/ng...
基本示例:
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
# 使用$binary_remote_addr【这是一个二进制的信息记录 $remote_addr(非二进制的)】(nginx本身存在的,保存客户端的ip地址)变量,可以将每条状态记录的大小减少到64个字节,这样1M的内存可以保存大约1万6千个64字节的记录。如果限制域的存储空间耗尽了,对于后续所有请求,服务器都会返回 503 (Service Temporarily Unavailable)错误。
# zone=one:10m 表示设置了名为“one”,大小为10兆字节,也可以理解为设置的限流名为one
# rate=10r/s 的意思是允许1秒钟不超过10个请求。速度可以设置为每秒处理请求数和每分钟处理请求数,其值必须是整数。如果请求频录不到每秒1次,你可以设置每分钟几次(r/m)。比如每秒半次就是30r/m。
limit_req_log_level notice;
# 如果你说希望的日志级别,当访问因为频录过高拒绝或延迟处理请求时可以记下相应级别的日志。延迟记录的日志级别比拒绝的低一个级别;比如,如果设置“limit_req_log_level notice",延迟的日志就是info级别。
# 语法:limit_req_log_level info | notice | warn | error;
# 默认值:limit_req_log_level error;
# 上下文:http、server、location
# 版本要求0.8.18+
...
server {
...
location /search /{
limit_req zone=one burst=5;
# 使用了上方名字为”one"的限流。
# burst=5 允许超过频率限制的请求数不多于5个,假设1、2、3、4秒请求为每秒9个,那么第5秒内请求15个是允许的,反之,如果第一秒内请求15个,会
将5个请求放到第二秒,第二秒内超过10的请求直接503,类似多秒内平均速率限制。
这里多出来的5个请求是被放到10m的哪个缓存中,等待下一秒的处理。
# nodelay 超过的请求不被延迟处理,设置后15个请求在1秒内处理。这里回有5个超出,超出的5个会直接503。写法:limit_req zone=one burst=5 nodelay;
}
}
}
3.2.2 ngx_http_limit_conn_module限制请求连接数
https://tengine.taobao.org/ng...
基本示例:
http {
limit_conn_zone $binary_remote_addr zone=addr:10m;
# 区域名称为addr,大小为10m,键值是客户端IP。
# 用于限制每个已定义键的连接数,特别是来自单个IP地址的连接数。并不是所有的连接都被计算在内。只有当服务器处理了一个请求,并且整个请求头已经被读取时,才会计算连接。
# 语法: limit_conn_zone $binary_remote_addr zone=addr:10m;
# 默认值: none
# 上下文:http
# 如果限制域的存储空间耗尽了,对于后续所有请求,服务器都会返回 503 (Service Temporarily Unavailable)错误。
...
server {
...
location /download/{
limit_conn addr 1;
# 限制每个IP只能发起1个连接。(addr 要跟 limit_conn_zone 的变量对应)
}
}
}
下载限速设置
http {
# ....
limit_conn_zone $binary_remote_addr zone=addr:10m;
# ....
server {
location / {
# root html;
autoindex on;
# 是限制每个IP只能发起1个连接 (addr 要跟 limit_conn_zone 的变量对应)
limit_conn addr 1;
limit_rate 10k; #限速为 10KB/秒
root /redis_2004;
# index index.html index.htm;
}
}
}
测试下载文件
3.2.3 IP黑白名单
连接限制跟请求限制,会对所有的ip进行限制,我们不希望自己的测试的ip,或者搜索引擎蜘蛛受到限制。
根据上面的速率限制的问题:
limit_req_zone $binary_remote_addr zone=testz:10m rate=1r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;
目前的情况是针对于所有的请求均会有做限制,而在业务中可能会存在这对于某一些ip是不做限制的需求;在nginx的配置中并不能直接对于变量编辑相应的逻辑计算因此我们不得不需要换一个方式。
3.2.3.1 ngx_http_geo_module
http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_geo_module.html ngx_http_geo_module
模块创建变量,并根据客户端IP地址对变量赋值.
语法: geo [$address] $variable { ... }
默认值: —
上下文: http
其实这个操作就有点类似于枚举变量,会根据我们传递的参数然后匹配并返回相应的参数。
基础体验:
http {
// ..
geo $whiteIpList {
default 1;
192.168.169.139 0;# 如果访问IP=192.168.169.139,下方$whiteIpList就返回0
192.168.169.160 0;
include ip/whiteIp.conf;# 可以设置ip列表
}
server {
// ..
location /geo {
return 200 '$whiteIpList';
# 访问http://xxxx/geo =》浏览器页面输出1或0
}
}
}
3.2.3.2 ngx_http_map_module
ngx_http_map_module
可以根据我们传递的参数。
语法: map string $variable { ... }
默认值: —
上下文: http
使用方面和geo的方式类似.需要值得注意的是
limit_req_zone $binary_remote_addr zone=testz:10m rate=1r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;
如果binary_remote_addr为空则限制失败。
操作测试:
map $whiteIpList $limit_ip {
0 "";
1 $remote_addr;
}
最后配合geo实现白名单的操作
http {
// ..
limit_req_zone $limit_ip zone=testz:10m rate=1r/s;
limit_conn_zone $limit_ip zone=addr:10m;
// ..
geo $whiteIpList {
default 1;
192.168.169.139 0;# 如果访问IP=192.168.169.139,下方$whiteIpList就返回0
include ip/whiteIp.conf;# 可以设置ip列表
}
map $whiteIpList $limit_ip {
0 "";
1 $binary_remote_addr;
}
server {
// ..
location / {
root html;
limit_conn addr 1;
limit_rate 10k; #限速为 100KB/秒
index index.html index.htm;
# 这里192.168.169.139和whiteIp.conf中的都可以是白名单;如果是这些IP,geo返回的都是0,0在map中对应的值为"",所以上方的limit_req_zone和limit_conn_zone中设置的$limit_ip对应的值就是"",限制等功能无用,就实现了白名单功能了。
}
}
}
3.3 rewrite模块(ngx_http_rewrite_module)
rewrite
的主要功能是实现URL地址的重定向。Nginx
的rewrite
功能需要PCRE软件的支持,即通过perl兼容正则表达式语句进行规则匹配的。默认参数编译nginx
就会支持rewrite
的模块,但是也必须要PCRE的支持。
使用场景:
1、可以调整用户浏览的URL,看起来更规范,合乎开发及产品人员的需求。
2、为了让搜索引擎搜录网站内容及用户体验更好,企业会将动态URL地址伪装成静态地址提供服务。
3、网址换新域名后,让旧的访问跳转到新的域名上。例如,访问京东的360buy.com会跳转到jd.com
4、根据特殊变量、目录、客户端的信息进行URL调整等。
3.3.1 if指令
# 语法:if(condition){…}
# 上下文:server,location
# 该指令用于检查一个条件是否符合,如果条件符合,则执行大括号内的语句。if指令不支持嵌套,不支持多个条件&&和||处理。
# 其中,condition中可以包含的判断标识如下
# ~为区分大小写匹配
# ~*为不区分大小写匹配
# -f和!-f用来判断是否存在文件
# -d和!-d用来判断是否存在目录
# -e和!-e用来判断是否存在文件或目录
# -x和!-x用来判断文件是否可执行
if ($http_user_agent~*(mobile|nokia|iphone|ipad|android|samsung|htc|blackberry)) {
rewrite ^(.*) http://peter.23673.com$1 permanent;
}
3.3.2 return指令
# 语法:return code [text]
# return code URL;
# return URL;
# 上下文:server,location,if
# 该指令用于结束规则的执行并返回状态吗给客户端。
# 状态码包括:
# 204(No Content)、
# 400(Bad Request)、402(PaymentRequired)、403(Forbidden)、404(Not Found)、405(Method Not Allowed)、406(Not Acceptable)、408(Request Timeout)、410(Gone)、411(Length Required)、413(Request Entity Too Large)、416(Requested Range Not Satisfiable)、
# 500(Internal Server Error)、501(Not Implemented)、502(Bad Gateway)、503(Service Unavailable)和504(Gateway Timeout)。
# 例如,示例,如果访问的URL以.sh .bash 结尾,返回状态码403
location ~ .*\.(sh|bash)?$ {
return 403;
}
3.3.3 Rewrite语法
# 语法:rewrite regex replacement [flag];
# 默认值:—
# 上下文:server, location, if
# rewrite是实现URL重写的关键指令,根据regex(正则表达式)部分内容,重定向到replacement,结尾是flag标记。
# 正则:perl兼容正则表达式语句进行规则匹配
# 替代内容:将正则匹配的内容替换成replacement
# flag标记:rewrite支持的flag标记[last...]
3.3.4 last、break、redirect、permane标记说明
last
# 后面不填写的话默认的就是这个;
# 本条规则匹配完成后,继续向下匹配新的location URI规则。
# 结束当前的请求处理,用替换后的URI重新匹配location;
# 可理解为重写(rewrite)后,发起了一个新请求,进入server模块,匹配locaton;
# 如果重新匹配循环的次数超过10次,nginx会返回500错误;
break
# 本条规则匹配完成即终止,不再匹配后面的任何规则
# 结束当前的请求处理,使用当前资源,不在执行location里余下的语句
redirect
# 返回302临时重定向,浏览器地址会显示跳转后的URL地址。
permane
返回301永久重定向, 地址栏显示重定向后的url,爬虫更新url
3.4 nginx图片防盗链实现(referers模块)
- 场景:某网站通过url引用了你的页面,当用户在浏览器上点击url时,http请求的头部中会通过referer头部,将该网站当前页面的url带上,告诉服务器本次请求是由这个页面发起的
- 目的:拒绝非正常的网站访问我们站点的资源
- 思路:通过referer模块,用
invalid_referer
变量根据配置判断referer头部是否合法
# 语法: valid_referers none | blocked | server_names | string ...;
# 默认值: —
# 上下文: server, location
# “Referer”请求头为指定值时,内嵌变量$invalid_referer被设置为空字符串,否则这个变量会被置成“1”。查找匹配时不区分大小写。
# 该指令的参数可以为下面的内容:
# none:缺少“Referer”请求头;
# blocked:“Referer” 请求头存在,但是它的值被防火墙或者代理服务器删除; 这些值都不以“http://” 或者 “https://”字符串作为开头;
# server_names:“Referer” 请求头包含某个虚拟主机名;
# 防止别人直接从你网站引用图片等链接,消耗了你的资源和网络流量,那么我们的就可以设置防盗链策略下面的方法是直接给予404的错误提示,或者是显示一个图片。
# 案例1
location ~* ^.+\.(jpg|gif|png|swf|flv|wma|wmv|asf|mp3|mmf|zip|rar)$ {
valid_referers www.23673.com;
# 设置头部必须为www.23673.com开头。
if ($invalid_referer) { # 上面指定valid_referers,这里可以通过$invalid_referer变量来获取结果。如果头部含有www.23673.com,就返回空字符串,否则返回"1"。
# 不是指定的头部(不是www.23673.com)的情况
return 403 "这里是错误信息内容";
break;
}
}
# 案例1
location ~* ^.+\.(jpg|gif|png|swf|flv|wma|wmv|asf|mp3|mmf|zip|rar)$ {
valid_referers none blocked www.23673.com 23673.com;
# 缺少“Referer”请求头的情况下;或者“Referer” 请求头存在,但是它的值被防火墙或者代理服务器删除; 这些值都不以“http://” 或者 “https://”字符串作为开头;或者以域名www.23673.com;或23673.com的时候请求符合情况。$invalid_referer就返回空,否则返回1
if ($invalid_referer) {# 返回1的情况,给他报404错误。
# return 302 http://nginx.23673.com/img/nolink.jpg;
return 404;
break;
}
}
3.5 负载均衡
实现负载均衡,只要通过在 http 指令下配置 upstream 即可。
# 语法: upstream name { ... }
# 默认值: —
# 上下文: http
# upstream 指令当中包含server指令
# 语法: server address [parameters];
# 默认值: —
# 上下文: upstream
# 可以定义下面的参数(parameters):
# weight=number 设定服务器的权重,默认是1,权重越大被访问机会越大,要根据机器的配置情况来配置
# max_fails=number 设定Nginx与服务器通信的尝试失败的次数。在fail_timeout参数定义的时间段内,如果失败的次数达到此值,Nginx就认为服务器不可用。在下一个fail_timeout时间段,服务器不会再被尝试。失败的尝试次数默认是1。可以通过指令proxy_next_upstream 和memcached_next_upstream来配置什么是失败的尝试。 默认配置时,http_404状态不被认为是失败的尝试。
# fail_timeout=time 统计失败尝试次数的时间段。在这段时间中,服务器失败次数达到指定的尝试次数,服务器就被认为不可用。默认情况下,该超时时间是10秒。
# backup 标记为备用服务器。当主服务器不可用以后,请求会被传给这些服务器,配置这个指令可以实现故障转移。
# down 标记服务器永久不可用,可以跟ip_hash指令一起使用。
# 当访问Nginx时,会将请求反向代理到backend配置的upstream server。
# 例子:
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com:8080;
}
server {
location / {
proxy_pass http://backend;
}
}
3.5.1 普通轮询
默认轮训方式
每一个来自网络中的请求,轮流分配给内部的服务器,从1到N然后重新开始。此种负载均衡算法适合服务器组内部的服务器都具有相同的配置并且平均服务请求相对均衡的情况。
upstream swo_http_up { # 设置的负载均衡名
# 设置的轮询服务列表
server example1.com:9001;# 域名写法
server 192.168.1.120:9002;# IP写法
...
}
server {
location / {
proxy_pass http://swo_http_up;# 使用了上面的负载均衡为swo_http_up的负载均衡
}
}
3.5.2 加权轮询
通过weight
参数控制权重
根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。例如:服务器A的权值被设计成1,B的权值是3,C的权值是6,则服务器A、B、C将分别接受到10%、30%、60%的服务请求。此种均衡算法能确保高性能的服务器得到更多的使用率,避免低性能的服务器负载过重。
upstream swo_http_up { # 设置的负载均衡名
# 设置的轮询服务列表
server example1.com:9001 weight 6;# 域名写法,设置权为6。表示10个里面会有6个到这个服务
server 192.168.1.120:9002 weight 4;# IP写法,设置权为4。表示10个里面会有4个到这个服务
}
server {
location / {
proxy_pass http://swo_http_up;# 使用了上面的负载均衡为swo_http_up的负载均衡
}
}
3.5.3 IP Hash
在upstream
当中配置ip_hash
;
这种方式通过生成请求源IP的哈希值,并通过这个哈希值来找到正确的真实服务器。这意味着对于同一主机来说他对应的服务器总是相同。使用这种方式,你不需要保存任何源IP。 将客户端会话"沾住"或者"持久化",以便总是能选择特定服务器,那么可以使用 ip-hash 负载均衡机制。
使用ip-hash
时,客户端IP地址作为hash key
使用,用来决策选择服务器集群中的哪个服务器来处理这个客户端的请求。这个方法保证从同一个客户端发起的请求总是定向到同一台服务器,除非服务器不可用。
upstream swo_http_up { # 设置的负载均衡名
ip_hash;#设置哈希,同一个用户永远只会到列表中一个固定的服务上
# 设置的服务列表
server example1.com:9001;# 域名写法
server 192.168.1.120:9002;# IP写法
}
server {
location / {
proxy_pass http://swo_http_up;# 使用了上面的负载均衡为swo_http_up的负载均衡
}
}
3.5.4 最少连接数
在upstream
当中配置least_conn
实现最少连接数。
客户端的每一次请求服务在服务器停留的时间可能会有较大的差异,随着工作时间加长,如果采用简单的轮循或随机均衡算法,每一台服务器上的连接进程可能会产生极大的不同,并没有达到真正的负载均衡。最少连接数均衡算法对内部中需负载的每一台服务器都有一个数据记录,记录当前该服务器正在处理的连接数量,当有新的服务连接请求时,将把当前请求分配给连接数最少的服务器,使均衡更加符合实际情况,负载更加均衡。
# 建议用这个
upstream swo_http_up { # 设置的负载均衡名
least_conn;#最少连接数,查看哪个服务的连接最少就连接到哪个
# 设置的服务列表
server example1.com:9001;# 域名写法
server 192.168.1.120:9002;# IP写法
}
server {
location / {
proxy_pass http://swo_http_up;# 使用了上面的负载均衡为swo_http_up的负载均衡
}
}
3.5.5 负载均衡产生的session问题
除了哈希,其他的负载均衡方式就没法保持session的一致性,所以得让这些服务的session进行共享。可以用nfs同步文件的方式;也可以用redis保持的方式来处理,建议使用redis。不同的框架有不同的配置实现方式,请具体解决。这里暂时不处理。
3.5 失败重试
通过配置上游服务器max_fails
和fail_timeout
,指定每个上游服务器,当fail_timeout
时间内失败了max_fails
次请求,则认为该上游服务器不可用/不存活,然后这段时间将不会访问这台上游服务器,fail_timeout
时间后会再次进行重试。max_fails=2
fail_timeout=30s
这2个一起搭配使用,表示:当失败2次的时候,就停止使30秒。
3.5.1 proxy_next_upstream 指令
在nginx的配置文件中,proxy_next_upstream
项定义了什么情况下进行重试。
# 语法: proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 http_503 | http_504 |http_404 | off ...;
# 默认值: proxy_next_upstream error timeout;
# 上下文: http, server, location
# 参数说明:
# error:表示和后端服务器建立连接时,或者向后端服务器发送请求时,或者从后端服务器接收响应头时,出现错误。
# timeout:表示和后端服务器建立连接时,或者向后端服务器发送请求时,或者从后端服务器接收响应头时,出现超时。
# invalid_header:表示后端服务器返回空响应或者非法响应头
# http_500:表示后端服务器返回的响应状态码为500
# .............
# off 表示停止将请求发送给下一台后端服务器
# 重试不能无限制进行,因此,需要如下两个指令控制重试次数和重试超时时间。
# proxy_next_upstream_tries number:设置重试次数,默认0表示不限制,注意此重试次数指的是所有请求次数(包括第一次和之后的重试次数之和)。
# proxy_next_upstream_timeout time: 设置重试最大超时时间,默认0表示不限制。
# 即在 proxy_next_upstream_timeout 时间内允许 proxy_next_upstream_tries 次重试。如果超过了其中一个设置,则 Nginx 也会结束重试并返回客户端响应(可能是错误码)。
# proxy_send_timeout 后端服务器数据回传时间(代理发送超时时间)
# proxy_read_timeout 连接成功后,后端服务器响应时间(代理接收超时时间)
# proxy_connect_timeout nginx连接后端的超时时间,一般不超过75s
upstream swo_http_up { # 设置的负载均衡名
# 设置的轮询服务列表
server example1.com:9001;# 域名写法
server 192.168.1.120:9002 max_fails=2 fail_timeout=30s;# IP写法。max_fails=2 fail_timeout=30s;表示重试失败2次后,这个服务停止30秒不被使用。
...
}
server {
location / {
proxy_next_upstream timeout;
# 设置为与代理通信发生超时的处理。
proxy_next_upstream_tries 2;
# 设置重试次数为2次,这里第一次的请求也算里面的。
proxy_next_upstream_timeout 10;
# 设置重试最大超时时间为10秒。
# proxy_send_timeout 1;
# 后端服务器数据回传时间(代理发送超时时间),这个是代理端服务用。
proxy_read_timeout 1;
# 连接成功后,后端服务器响应时间(代理接收超时时间)
proxy_connect_timeout 10;
# nginx连接后端的超时时间,一般不超过75s。这里是10秒
proxy_pass http://swo_http_up;
# 使用了上面的负载均衡为swo_http_up的负载均衡
}
}
4 图形化压测工具:jmeter在nginx中使用
4.1 下载安装
这个工具是需要jdk 1.8 以上。
自行百度下载。
下载后双击 apache-jmeter-5.3binjmeter.bat 即可运行
4.2 实现类似ab这种功能
测试计划->right click ->add ->线程(用户)->线程组
线程组->right click ->add ->取样器->http请求
http请求->right click ->add->监听器->查看结果树
http请求->HTTP请求栏目中填写路径(http://xxxx)
线程组->线程属性下->线程数填写(表示几个客户端发起请求)和Ramp-Up填写(0表示并发)
查看结果树->点击上方”三角形“启动
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。