一、环境准备
1、gcc安装
安装 nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境,如果没有 gcc 环境,则需要安装:
yum install gcc gcc-c++
2、pcre pcre-devel 安装
PCRE(Perl Compatible Regular Expressions) 是一个Perl库,包括 perl 兼容的正则表达式库。Nginx的http 模块使用pcre来解析正则表达式,所以需要在Linux上安装pcre库,pcre-devel 是使用pcre开发的一个二次开发库。Nginx也需要此库。命令:
yum install -y pcre pcre-devel
3、 zlib安装
zlib 库提供了很多种压缩和解压缩的方式, Nginx使用zlib对http包的内容进行gzip,所以需要在Linux Centos 7上安装zlib库。
yum install -y zlib zlib-devel
4、openssl安装
OpenSSL是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。
Nginx不仅支持http协议,还支持https(即在ssl协议上传输http),所以需要在Linux Centos 7安装OpenSSL库。
yum install -y openssl openssl-devel
二、安装Nginx
1、下载
用wget命令下载(推荐)。确保系统已经安装了wget,如果没有安装,执行 yum install wget 安装。
#下载,这里也可以去官网下载
wget -c https://nginx.org/download/nginx-1.22.1.tar.gz
#解压
tar -zxf nginx-1.22.1.tar.gz -C ./
cd nginx-1.22.1
2、检查配置并指定安装参数
./configure --prefix=/usr/local/nginx --conf-path=/usr/local/nginx/nginx.conf --with-http_stub_status_module --with-http_ssl_module
- ./configure 是编译前检查的命令,
- —prefix=/usr/local/nginx 是安装到指定目录,
- —with-http_stub_status_module —with-http_ssl_module 是安装ssl证书的两个模块
3、编译安装
make&&make install
4、操作
#进入目录
cd /usr/local/nginx/sbin/
./nginx #启动
./nginx -s quit # 此方式停止步骤是待nginx进程处理任务完毕进行停止。
./nginx -s stop # 此方式相当于先查出nginx进程id再使用kill命令强制杀掉进程。
./nginx -t #校验配置文件是否正确
./nginx -s reload #重新加载
5、查看进程
ps -ef|grep nginx
root 4337 1 0 06:13 ? 00:00:00 nginx: master process ./nginx
nobody 4338 4337 0 06:13 ? 00:00:00 nginx: worker process
root 4340 1494 0 06:13 pts/0 00:00:00 grep --color=auto nginx
6、关闭防火墙或者打开80端口
启动: systemctl start firewalld
停止: systemctl stop firewalld
查看所有打开的端口: firewall-cmd --permanent --list-port
开启端口:firewall-cmd --zone=public --add-port=80/tcp --permanent
关闭端口:firewall-cmd --zone=public --remove-port=80/tcp --permanent
更新防火墙规则: firewall-cmd --reload
我这里选择的是开启80端口
开启端口:firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --reload
[root@localhost sbin]# firewall-cmd --permanent --list-port
80/tcp
7、浏览器访问
这里我linux服务器的地址是192.168.192.11 ,访问
三、nginx使用
1、反向代理
所谓反向代理就是nginx接受到请求后,将请求转发给内部的一台服务器处理,比如我们启动了一个tomcat是8081端口,但是我们防火墙不会开放8081端口,只会开放nginx的80端口,那么我们需要再nginx上进行反向代理配置,让到80端口的请求转发给8081端口处理,这样安全性也有很大的提高,并且后续可以进行负载均衡:80端口进来,从代理的多台服务器按策略选一台处理。
1.1、8081端口服务搭建
我们这里就不启动tomcat来模拟服务了,直接在nginx上配置个8081端口的server即可,nginx配置文件做如下处理
server {
listen 8081;
server_name localhost;
location / {
root html;
index index8081.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
这里的意思是,请求从8081进来,会返回index8081.html的页面,这个页面会在nginx目录下面的html里面,内容如下
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to 8081!</h1>
</body>
</html>
到这里就相当于有一个新的服务了。
1.2、nginx反向代理配置
下面我们来配置负载均衡,我们在nginx.conf的http配置里面新增upstream.
upstream first {
server localhost:8081;
}
然后,在80的server进行代理配置
server {
listen 80;
server_name localhost;
location / {
#反向代理配置
proxy_pass http://first;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
1.3、重新启动nginx
我们可以先用-t命令校验下配置文件是否正确
./nginx -t
检查正确后,进行重新加载
./nginx -s reload
1.4、访问测试
我们访问80端口,然后可以看到返回了index8081.html的页面内容,表面反向代理成功。
1.5、proxy_set_header
我们看到,反向代理设置的时候,有进行proxy_set_header设置,那这个的作用是什么呢?
即允许重新定义或添加字段传递给代理服务器的请求头,简而言之,proxy_set_header 就是可设置请求头-并将头信息传递到服务器端,不属于请求头的参数中也需要传递时,重定义下即可!
主要有三个参数需要设置
Host
若客户端发过来的请求header中有HOST这个字段,$http_host和$host表示的就是原始请求
X-Real-IP
是指客户端的真实IP,如果设置了$remote_addr这个值,后端服务器就能获取到客户端的真实IP
X-Forwarded-For
这个变量的值有$proxy_add_x_forwarded_for,可以真实的显示出客户端原始ip。
我们这里来测试下
环境搭建
在本机搭建一个springboot应用,springboot应用搭建方法参考:从官网开始用IDEA在JDK1.8环境搭建springboot2.7.14项目,然后代码如下
@RestController
public class DemoController {
@GetMapping("/hello")
public Map<String,Object> hello(HttpServletRequest request){
Map<String,Object> result = new TreeMap<String,Object>();
result.put("hello","Hello World");
String scheme = request.getScheme();
String xForwardedFor = request.getHeader("X-Forwarded-For");
String xRealIp = request.getHeader("X-Real-IP");
String host = request.getHeader("Host");
String serverName = request.getServerName();
int serverPort = request.getServerPort();
String remoteName = request.getRemoteAddr();
int remotePort = request.getRemotePort();
result.put("scheme",scheme);
result.put("serverName",serverName);
result.put("serverPort",serverPort);
result.put("remoteName",remoteName);
result.put("remotePort",remotePort);
result.put("xForwardedFor",xForwardedFor);
result.put("xRealIp",xRealIp);
result.put("host",host);
return result;
}
}
我本机的ip为:192.168.192.1
nginx所在的ip:192.168.192.11
nginx的反向代理的配置为
upstream first {
server 192.168.192.1:8080;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://first;
#proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
这样客户端通过访问nginx暴露的80服务就是反向代理到我本机启动的springboot应用。下面我们来测试proxy_set_header的作用
不配置proxy_set_header的测试
我们上面是把proxy_set_header都注释了,此时在浏览器上访问
http://192.168.192.11/hello
返回了
{"hello":"Hello World","host":"first","remoteName":"192.168.192.11","remotePort":35058,"scheme":"http","serverName":"first","serverPort":80,"xForwardedFor":null,"xRealIp":null}
可以看到完全没有拿到任何客户端的信息.
配置proxy_set_header的测试
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://first;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
在浏览器上访问
http://192.168.192.11/hello
返回了
{"hello":"Hello World","host":"192.168.192.11","remoteName":"192.168.192.11","remotePort":35060,"scheme":"http","serverName":"192.168.192.11","serverPort":80,"xForwardedFor":"192.168.192.1","xRealIp":"192.168.192.1"}
request.getRemoteAddr():获取的永远都是代理对象的IP
X-Forwarded-For和X-Real-IP:都获取了客户端的真实IP
X-Forwarded-For和X-Real-IP有什么区别呢
我们上面的例子发现,这两个获取的都是客户端的真实IP地址,其实如果只有一个反向代理服务器,那结果都是一样的,但是如果有多个,这里可以就用一个nginx来模拟一下。配置如下
我们首先在nginx配置一个服务,代理到我们的springboot应用.
upstream second {
server 192.168.192.1:8080;
}
server {
listen 8081;
server_name localhost;
location / {
proxy_pass http://second;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
这里相当于我们的应用被一个nginx服务器代理了,端口是8081,我们再配置一个80端口代理到8081,就模拟了两台代理服务器的情况
upstream first {
server localhost:8081;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://first;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
我们再尝试在本机的浏览器请求:http://192.168.192.11/hello,返回了
{"hello":"Hello World","host":"192.168.192.11","remoteName":"192.168.192.11","remotePort":35086,"scheme":"http","serverName":"192.168.192.11","serverPort":80,"xForwardedFor":"192.168.192.1, 127.0.0.1","xRealIp":"127.0.0.1"}
可以看到X-Real-IP获取的就不是客户端的地址了,而是第一次代理发起的地址,但是我们的X-Forwarded-For却有全部的客户端IP地址,我们想要获取真实客户端,只需要获取X-Forwarded-For第一个即可。
总结:X-Forwarded-For记录服务器的地址,会把记录添加到结尾,X-Real-IP用来记录服务器的地址,它不把记录添加到结尾,而是直接替换。所以用X-Forwarded-For就不会错。
1.6、localtion匹配规则
location的使用语法规则如下
location关键字 + 匹配方式符号(可省略)+匹配规则+如何处理
匹配方式符号可选有:= | ~ | ~* | ^~
location [ = | ~ | ~* | ^~ ] uri { ... }
通常我们配置的时候会使用两种配置方式:普通匹配和正则匹配
1.6.1、普通匹配
普通匹配主要有如下三种配置方式
= : 这代表精准匹配全路径, 命中它后直接返回, 不再进行后续匹配, 优先级最高.
^~ : 这代表精准匹配开头, 命中开头后直接返回, 不再进行后续匹配, 优先级第二.
无匹配方式符号 : 这代表通用性匹配, 命中后还会继续后续匹配, 最后选取路径最长的匹配, 并储存起来, 优先级第四.
举例
#这是精准匹配, 只有请求路径完全匹配`/hello.html`才会命中它
location = /hello.html {
...
}
#这是精准匹配开头, 只要请求路径的开头是`/hello/`, 就会命中并立即返回
location ^~ /hello/ {
...
}
#这是无匹配方式符号的普通匹配, 如果请求路径开头是`/hello/`, 则会命中, 但是不会立即返回还会接着进行普通匹配
location /hello/ {
...
}
#这是无匹配方式符号的普通匹配, 如果请求路径开头是`/hello/a`, 则会命中, 但是不会立即返回还会接着进行普通匹配, 同时会舍弃掉上面那个匹配
location /hello/a {
...
}
#我们通常配置的/也是无匹配方式符号的普通匹配
location / {
...
}
1.6.2、正则匹配
正则匹配有如下两种匹配模式
~: 这是区分大小写的正则匹配, 命中后则不进行后续匹配, 立即返回, 优先级第三.
~*: 不区分大小写的正则匹配, 命中后则不进行后续匹配, 立即返回, 优先级第三.
这里有个很重要点点, 也就是正则匹配中~和~*优先级一样, 它们按照从上到下的顺序进行匹配, 最先命中的立即返回, 后续的不会进行匹配, 所以精细的正则匹配规则往前放, 通用的正则匹配规则往后放.
举例
#区分大小写的正则匹配, 如果路径包含 /a/ 则立即返回, 注意这里并不需要开头命中, 因为这是正则表达式
location ~ /a/ {
...
}
#区分大小写的正则匹配, 如果路径包含 /A(不分大小写)/ 则立即返回, 注意这里并不需要开头命中, 因为这是正则表达式, 但由于上面一个正则匹配规则在前面, 所以如果路径包含 /A/ 则会被挡下来, 匹配不到这里.
location *~ /A/ {
...
}
1.6.3、正则表达式
*:重复前面的字符0次或多次
?:重复前面的字符0次或1次
+:重复前面的字符1次或多次
.:匹配除换行符以外的任意一个字符
(a|b):匹配a或b
^:以...开头
$:以...结尾
{n}:重复前面的字符n次
{n,}:重复前面的字符n次或更多次
{n,m}:重复前面的字符n-m次
*?:重复前面的字符0次或多次,但尽可能少重复
+?:重复前面的字符1次或多次,但尽可能少重复
??:重复前面的字符0次或1次,但尽可能少重复
{n,m}?:重复前面的字符n-m次,但尽可能少重复
{n}?:重复前面的字符n次以上,但尽可能少重复
1.6.4、正则表达式补充
\W:匹配任意不是字母,数字,下划线,汉字的字符(特殊符号)
\S:匹配任意不是空白符的字符
\D:匹配任意非数字的字符
\B:匹配任意不是单词开头或结尾的位置
[a]:匹配单个字符a
[a-z]:匹配a-z小写字符的任意一个
[^a]:匹配除了a以外的任意字符
[^abc]:匹配除了abc这几个字母以外的任意字符
1.6.5、正则表达式匹配举例
#匹配所有以.jpg,.xml或者.txt结尾的请求
location ~ \.(jpg|xml|txt)$ {
proxy_pass http://first;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
1.7、Rewrite
Rewrite主要的功能是实现URL重写,Nginx 的 Rewrite 规则采用 PCRE Perl 兼容正则表达式的语法进行规则匹配,如果使用 Nginx 的 Rewrite 功能,在编译 Nginx 前要编译安装 PCRE 库。Rewrite主要实现url地址重写,以及重定向,就是把传入web的请求重定向到其他url的过程。
1.7.1、rewrite介绍
rewrite和location的功能有点相像,都能实现跳转,主要区别在于rewrite常用于同一域名内更改获取资源的路径,而location是对一类路径做控制访问和反向代理,可以proxy_pass到其他服务器。
Nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向。
rewrite只能放在server{},location{},if{}中,
并且只能对域名后边的除去传递的参数外的字符串起作用。
1.7.2、rewrite语法
指令语法: rewrite regex(正则) replacement(替代内容) [flag](flag标记)
关键字:rewrite是实现URL重写的关键指令,不变
正则:perl兼容正则表达式语句进行规则匹配
替代内容:将正则匹配的内容替换成replacement
flag标记:rewrite支持的flag标记
应用位置:server、location、if
1.7.3、例子
rewrite ^/(.) http://www.suibibk.com/$1 permanent;
说明:
rewrite为固定关键字,表示开始进行rewrite匹配规则
regex部分是 ^/(.) ,这是一个正则表达式,匹配完整的域名和后面的路径地址
replacement部分是http://www.suibibk.com/$1 $1,是取自regex部分()里的内容。匹配成功后跳转到的URL。
flag部分 permanent表示永久301重定向标记,即跳转到新的 http://www.suibibk.com/$1 地址上
假设我们再nginx如下进行配置
server {
listen 80;
server_name localhost;
rewrite ^/(.*) http://www.suibibk.com/$1 permanent;
...
}
当我们访问:http://192.168.192.11/hello/a/b?id=12345 的时候,就会自动重定向到https://www.suibibk.com/hello/a/b?id=12345
我们也可以用if条件判断,符合if条件判断的才进行处理
server {
listen 80;
server_name localhost;
if ( $host != 'www.suibibk.com' ) {
rewrite ^/(.*) http://www.suibibk.com/$1 permanent;
}
...
}
1.7.4、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相同。
1.7.5、rewrite 中常用的正则
. 匹配换行符以外任意字符
? 重复0次或者1次
+ 重复1次或多次
* 重复0次或者多次
\d 匹配数字
^ 匹配开始
$ 匹配结束
{n} 重复 n 次
{n,} 重复 n 次或更多次
[c] 匹配单个字符c
[a-z] 匹配 a-z 任意一个小写字母
使用 () 可以将匹配内容括起来,后面使用 $1 来引用,当然,第二个 () 就是 $2。
1.7.6、rewrite应用场景
可以调整用户浏览的URL,看起来更规范,合乎开发及产品人员的需求。
为了让搜索引擎搜录网站内容及用户体验更好,企业会将动态URL地址伪装成静态地址提供服务。
网址换新域名后,让旧的访问跳转到新的域名上。例如,访问京东的360buy.com会跳转到jd.com
根据特殊变量、目录、客户端的信息进行URL调整等
1.7.6、例子实战:让短连接更短
背景:我们公司前端框架用的是struts2,并且是很老的一个框架,请求格式大概是这样:https://www.suibibk.com/u!u.do?u=ke469i57m ,然后运营就说这个短连接还是太长了,有没有办法再变短,比如变为:https://www.suibibk.com/u/ke469i57m
这怎么办呢,struts2又不支持这种格式,并且两个链接都是可以用的,正常用长的就够了!
解决方案,通过rewrite重新
if ( $request_uri ~ /u/ ){
rewrite ^/(u)/(.*) https://www.suibibk.com/u!u.do?u=$2 permanent;
}
完美解决!
注:$1和$2对应的就是前面的正则括号,比如上面$2对应的就是https://www.suibibk.com/u/ke469i57m 中的ke469i57m
1.7.8、if语句中的判断条件
正则表达式匹配:
==:等值比较;
~:与指定正则表达式模式匹配时返回“真”,判断匹配与否时区分字符大小写;
~*:与指定正则表达式模式匹配时返回“真”,判断匹配与否时不区分字符大小写;
!~:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时区分字符大小写;
!~*:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时不区分字符大小写;
反向代理的学习就到这里先,下面进行负载均衡的实战学习
2、负载均衡
2.1、负载均衡概念
负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。
在服务器集群中,Nginx起到一个代理服务器的角色(即反向代理),为了避免单独一个服务器压力过大,将来自用户的请求转发给不同的服务器。我们通过负载均衡,可以启动多个应用服务器来缓解服务端的压力,提高并发能力。
2.2、Nginx搭建负载均衡
这里直接在nginx进行测试即可,用端口进行区分,先见建两个服务8081和8082
8081
server {
listen 8081;
server_name localhost;
location / {
root html;
index index8081.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
index8081.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to 8081!</h1>
</body>
</html>
8082
server {
listen 8082;
server_name localhost;
location / {
root html;
index index8082.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
index8082.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to 8082!</h1>
</body>
</html>
配置upstream和代理
upstream first {
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://first;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
请求测试
http://192.168.192.11/
可以看到结果在【Welcome to 8081!】和【Welcome to 8082!】轮流显示,这是因为我们默认的负载均衡策略是【轮询】
2.3、Nginx负载均衡策略
2.3.1、策略分类
目前Nginx服务器的upstream模块支持6种方式的分配:
策略 | 描述 |
---|---|
轮询 | 默认方式 |
weight | 权重方式 |
ip_hash | 依据ip分配方式 |
least_conn | 最少连接方式 |
fair(第三方) | 响应时间方式 |
url_hash(第三方) | 依据URL分配方式 |
在这里,只详细说明Nginx自带的负载均衡策略,第三方不多描述。
2.3.2、轮询
最基本的配置方法,默认的就是轮询的方式,它是upstream模块默认的负载均衡默认策略。每个请求会按时间顺序逐一分配到不同的后端服务器。
参数 | 意义 |
---|---|
fail_timeout | 与max_fails结合使用 |
max_fails | 设置在fail_timeout参数设置的时间内最大失败次数,如果在这个时间内,所有针对该服务器的请求都失败了,那么认为该服务器会被认为是停机了 |
fail_time | 服务器会被认为停机的时间长度,默认为10s。 |
backup | 标记该服务器为备用服务器。当主服务器停止时,请求会被发送到它这里 |
down | 标记服务器永久停机了 |
注意:
在轮询中,如果服务器down掉了,会自动剔除该服务器。
缺省配置就是轮询策略。
此策略适合服务器配置相当,无状态且短平快的服务使用。
2.3.3、weight
权重方式,在轮询策略的基础上指定轮询的几率。例子如下:
#动态服务器组
upstream first {
server localhost:8080 weight=2;
server localhost:8081;
server localhost:8082 backup;
server localhost:8083 max_fails=3 fail_timeout=20s;
}
在该例子中,weight参数用于指定轮询几率,weight的默认值为1,;weight的数值与访问比率成正比,比如8080被访问的几率为其他服务器的两倍。
注意:
权重越高分配到需要处理的请求越多。
此策略可以与least_conn和ip_hash结合使用。
此策略比较适合服务器的硬件配置差别比较大的情况。
2.3.4、ip_hash
指定负载均衡器按照基于客户端IP的分配方式,这个方法确保了相同的客户端的请求一直发送到相同的服务器,以保证session会话。这样每个访客都固定访问一个后端服务器,可以解决session不能跨服务器的问题。
#动态服务器组
upstream first {
ip_hash; #保证每个访客固定访问一个后端服务器
server localhost:8080 weight=2;
server localhost:8081;
server localhost:8082; #backup;
server localhost:8083 max_fails=3 fail_timeout=20s;
}
注意:
在nginx版本1.3.1之前,不能在ip_hash中使用权重(weight)。
此策略适合有状态服务,比如session。
当有服务器需要剔除,必须手动down掉。
ip_hash不能与backup同时使用。否则会报如下错误。
[root@localhost sbin]# ./nginx -t
nginx: the configuration file /usr/local/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/nginx.conf test is successful
2.3.5、least_conn
把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。
#动态服务器组
upstream first {
least_conn; #把请求转发给连接数较少的后端服务器
server localhost:8080 weight=2;
server localhost:8081;
server localhost:8082 backup;
server localhost:8083 max_fails=3 fail_timeout=20s;
}
注意:
此负载均衡策略适合请求处理时间长短不一造成服务器过载的情况。
2.3.6、第三方策略
第三方的负载均衡策略的实现需要安装第三方插件。
fair
按照服务器端的响应时间来分配请求,响应时间短的优先分配。
#动态服务器组
upstream first {
server localhost:8080;
server localhost:8081;
server localhost:8082;
server localhost:8083;
fair; #实现响应时间短的优先分配
}
url_hash
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,要配合缓存命中来使用。同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。而使用url_hash,可以使得同一个url(也就是同一个资源请求)会到达同一台服务器,一旦缓存住了资源,再此收到请求,就可以从缓存中读取。
#动态服务器组
upstream first {
hash $request_uri; #实现每个url定向到同一个后端服务器
server localhost:8080;
server localhost:8081;
server localhost:8082;
server localhost:8083;
}
总结
以上便是6种负载均衡策略的实现方式,其中除了轮询和轮询权重外,都是Nginx根据不同的算法实现的。在实际运用中,需要根据不同的场景选择性运用,大都是多种策略结合使用以达到实际需求。
待续