Fork me on GitHub

Nginx常见使用场景总结

背景

  • HTTP服务器(含动静分离)
  • 负载均衡
  • 反向代理
  • 正向代理
  • 跨域请求

第一部分 HTTP服务器(含动静分离)

Nginx本身是一个静态资源的服务器,当只有静态资源的时候,就可以使用Nginx来做服务器,如下,我们使用Nginx来部署一个打包好的vue项目

1
2
3
4
5
6
7
8
#vue项目
server
{
listen 8081; #监听端口
server_name 209.250.235.145;
root /app/vue/dist/; # 我们的资源在服务器中的路径
index index.html; #指定资源的入口文件
}复制代码

完成后我们nginx -s reload一下,然后访问209.250.235.145:8081,只要路径没错静态资源就访问的到了

第二部分 正向代理

第三部分 反向代理

反向代理应该是Nginx做的最多的一件事了,什么是反向代理呢,以下是百度百科的说法:反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。简单来说就是真实的服务器不能直接被外部网络访问,所以需要一台代理服务器,而代理服务器能被外部网络访问的同时又跟真实服务器在同一个网络环境,当然也可能是同一台服务器,端口不同而已。 下面贴上一段简单的实现反向代理的代码

server{

listen80;

server_namelocalhost;

client_max_body_size1024M;

location/{

proxy_passhttp://localhost:8080;

proxy_set_headerHost$host:$server_port;

}

}

保存配置文件后启动Nginx,这样当我们访问localhost的时候,就相当于访问localhost:8080了

第四部分 负载均衡

在线上生产环境,为了承载较大流量,通常需要以集群方式并发处理,这就需要有代理服务对流量进行智能负载。通过算法将流量合理的分配给集群中各个处理节点。实现方式有硬件和软件两种,硬件常见的是F5专用设备,成本较高。如果流量不大可以由软件来实现。

而Nginx就是常见的软负载组件。利用upstream定义集群服务器。负载均衡配置一般都需要同时配置反向代理,通过反向代理跳转到负载均衡。

Nginx目前支持自带3种负载均衡策略,还有2种常用的第三方策略。

4.1 配置

首先需要在http节点中,配置upstream,例如:

1
2
3
4
upstream upstreamTest { 
server 192.168.88.1:9200;
server 192.168.88.2:9200;
}

将server节点下的location节点中的proxy_pass配置为:http:// + upstream名称,即

1
2
3
4
5
location / { 
root html;
index index.html index.htm;
proxy_pass http://upstreamTest;
}

4.2 负载模式

4.2.1 轮询 (round-robin)(默认方式)

轮询为负载均衡中最为朴素的算法,不需要配置额外参数。假设共有N台服务器,算法将遍历服务器节点列表,并按节点次序每轮选择一台服务器处理请求。当所有节点均被调用过一次后,算法将从第一个节点开始重新一轮遍历。如果列表中服务有下宕的,算法能主动将服务器从轮询列表中去除。

这个算法前提需要服务器列表中每台服务器的处理能力是均衡的,否则会有分配不均的问题。

配置案例:

1
2
3
4
upstream upstreamTest { 
server 192.168.88.1:9200;
server 192.168.88.2:9200;
}

4.2.2 加权轮询

但后端负载集群性能不均的时候,可以通过加权方式分配流量,这就是加权轮询。例如:

1
2
3
4
upstream upstreamTest { 
server 192.168.88.1:9200 weight=5;
server 192.168.88.2:9200 weight=10;
}

上面的配置给每一台服务指定了weight值,weight 的值越大意味着该服务器的性能越好,可以承载更多的请求。也可以从概率角度去理解,192.168.88.2的流量分配概率比192.168.88.1大一倍。

4.2.3 IP 哈希(IP hash)

轮询和加权轮询,每次访问后端是随机不同的机器,对于一些场景就不太适应。当程序有状态的时候,例如采用了session保存数据,把登录信息保存到了session中,那么跳转到另外一台服务器的时候就需要重新登录。所以这时候需要原IP客户端固定访问同一台服务器。

ip hash函数将每个请求按访问ip的hash结果分配,同一个IP客户端访问的负载后端服务不变。配置如下:

1
2
3
4
5
upstream upstreamTest {
ip_hash;
server 192.168.88.1:9200;
server 192.168.88.2:9200;
}

4.2.4 fair(第三方)

对于上面的负载算法没有动态的考虑服务器的性能变化。fair算法根据负载后端服务器的响应时间来动态分配请求,响应时间短优先分配流量。配置参考:

1
2
3
4
5
upstream upstreamTest {
fair;
server 192.168.88.1:9200;
server 192.168.88.2:9200;
}

4.2.5 url_hash(第三方)

按訪问url的hash结果来分配请求,使每一个url定向到同一个后端服务器。后端服务器为缓存时有效。静态资源缓存,节约存储,加快速度。配置参考:

1
2
3
4
5
6
upstream upstreamTest {
server 192.168.88.1:9200;
server 192.168.88.2:9200;
hash $request_uri;
hash_method crc32;
}

其中hash_method crc32配置为指定hash算法为crc32

4.3 补充

upstream还能够为每一个设备设置状态值,这些状态值的含义分别例如以下:

  • down

    后端节点不参与负载;

  • max_fails和fail_timeout

    Nginx基于连接探测,如果发现后端异常,在单位周期为fail_timeout设置的时间,中达到max_fails次数,这个周期次数内,如果后端同一个节点不可用,那么接将把节点标记为不可用,并等待下一个周期(同样时常为fail_timeout)再一次去请求,判断是否连接是否成功。如果成功,将恢复之前的轮询方式,如果不可用将在下一个周期(fail_timeout)再试一次。

  • backup

    backup 不能和ip_hash一起使用,backup 参数是指当所有非备机都宕机或者不可用的情况下,就只能使用带backup标准的备机。

  • max_conns

    允许最大连接数。

  • slow_start

    当节点恢复,不立即加入

例如下面的案例:

1
2
3
4
5
6
upstream upstreamTest {
server 192.168.88.1:9200 down;
server 192.168.88.2:9200 backup;
server 192.168.88.3:9200 max_fails=2 fail_timeout=60s;

}

如上配置表明如果后端节点60秒内出现2次不可用情况,判定节点不可用。判定不可用后10秒内请求不会转发到此节点,直到60秒后重新检测节点健康情况。

第五部分 跨域请求

前后端分离的项目中由于前后端项目分别部署到不同的服务器上,我们首先遇到的问题就是跨域,在这个场景我们下nginx可以帮助我们很好地解决这个问题

1
2
3
4
5
6
7
8
9
10
11
12
13
#跨域请求server
server{
listen 9000;
server_name 209.250.235.145;
root /app/crossDomain/;
index index.html;

location /douban/ { #添加访问目录为/apis的代理配置
rewrite ^/douban/(.*)$ /$1 break;
proxy_pass https://m.douban.com;
}
}
复制代码

在我的服务器下我写了一个

index.html请求豆瓣接口,模拟跨域

1
2
3
4
5
6
7
8
9
10
11
12
function nginxClick(){
$.ajax({
url: '/douban/rexxar/api/v2/muzzy/columns/10018/items?start=0&count=3',
dataType: 'json',
type: 'get',
data: "",
success:(res)=>{
console.log(res)
}
})
}
复制代码

当我们访问点击请求时,匹配到location下的/douban/

1
rewrite   ^/douban/(.*)$ /$1 break;复制代码

这段配置将请求路径重写为/rexxar/api/v2/muzzy/columns/10018/items?start=0&count=3,其中$1代表正则模糊匹配到的第一个参数,

1
proxy_pass   https://m.douban.com;复制代码

这段配置是将请求域名代理到豆瓣的域名下面,所以从本地服务器发出去的请求将被重新重写为:

https://m.douban.com/rexxar/api/v2/muzzy/columns/10018/items?start=0&count=3,我们就能拿到豆瓣api提供的数据。详情可以看看这篇[文章](https://www.jianshu.com/p/10ecc107b5ee)

演示地址:http://209.250.235.145:9000/

参考文献及资料

[1] Orange官网,链接:http://orange.sumory.com/

[2] Orange网关官网docker,链接:https://hub.docker.com/r/syhily/orange

0%