Nginx负载均衡配置、限流配置、Https配置详解
创始人
2024-02-11 15:23:18

一. 负载均衡

1. 用法

 通过proxy_pass 可以把请求代理至后端服务,但是为了实现更高的负载及性能, 我们的后端服务通常是多个, 这个是时候可以通过upstream 模块实现负载均衡。

使用的模块为:【ngx_http_upstream_module】,具体配置可以根据模块名去查找文档。

负载均衡的算法有:

  • ll:轮询
  • ll+weight: 轮询加权重
  • ip_hash : 基于Hash 计算,用于保持session 一至性 该算法下权重失效
  • url_hash: 静态资源缓存,节约存储,加快速度(第三方) 该算法下权重配置失效
  • least_conn :最小链接数
  • least_time :最小的响应时间,计算节点平均响应时间,然后取响应最快的那个,分配更高权重

2. 参数

upstream 相关参数如下:

  • server 反向服务地址加端口
  • weight 权重,默认是1,越大权重就越大
  • max_fails 失败多少次认为主机已挂掉则,踢出 (默认配置10s,即服务器宕掉,会自动剔除)
  • fail_timeout 踢出后重新探测时间
  • backup 备用服务,当其他非backup的机器全部宕机或者繁忙的时候,才会启动这台机器。
  • down 表示当前Server不参与负载
  • max_conns 允许最大连接数
  • slow_start 当节点恢复,不立即加入,而是等待 slow_start 后加入服务对列。
upstream myApiTest {server localhost:9001 weight=10;server localhost:9002 weight=5;server localhost:9003  max_fails=3 fail_timeout=30s;server localhost:9004 backup;server localhost:9005 down;}

3. 案例

事先准备:

  有三个同样的api服务,分别部署在9001、9002、9003端口下,比如:访问 http://localhost:9001/Home/GetMsg,会返回 【 获取成功,当前端口为:9001】,其它端口类似。

要求:

 Nginx监听8080端口,接收到8080端口的请求,按照响应的算法进行转发到9001-9003端口。 

(1). 轮询

 访问地址:http://localhost:8080/Home/GetMsg ,会依次转发到9001、9002、9003端口上。【最新版本测试,轮询的时候一个服务器连续沦陷两次,才到下一个服务器,继续连续两次】??

配置如下:

worker_processes  1;
events {worker_connections  1024;
}
http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;upstream myApiTest {server localhost:9001;server localhost:9002;server localhost:9003;}server {listen       8080;server_name   xxx;    #随意配置一个即可,优先走代理地址location / {proxy_pass http://myApiTest;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}}
}

补充其他参数说明:

 下面配置,当请求 http://localhost:8080/Home/GetMsg 时候,只会被转发到9003端口上,此时把9003端口的服务关掉,再次请求,则会被转发到9001端口上,其中9002端口,全程不参与负载。

upstream myApiTest {server localhost:9001 backup;server localhost:9002 down;server localhost:9003;
}

(2).轮询+权重

  下面配置,被转发到9001 9002端口的概率要大于9003端口。

配置如下:

worker_processes  1;
events {worker_connections  1024;
}
http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;upstream myApiTest {server localhost:9001 weight=10;server localhost:9002 weight=5;server localhost:9003;}server {listen       8080;server_name   xxx;    #随意配置一个即可,优先走代理地址location / {proxy_pass http://myApiTest;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}}
}

(3). ip_hash

 同一个ip永远会被分配到同一个Server上,主要用来解决Session不一致的问题,但该策略也有弊端,weight权重无效,所以该方案会导致某个Server压力可能过大,请求分配不均匀问题。

配置如下:

worker_processes  1;
events {worker_connections  1024;
}
http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;upstream myApiTest {ip_hash;   #开启ip_hash策略server localhost:9001;server localhost:9002;server localhost:9003;}server {listen       8080;server_name   xxx;    #随意配置一个即可,优先走代理地址location / {proxy_pass http://myApiTest;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}}
}

(4). url_hash

 主要用于节省空间,比如我有9G的图片资源,服务器集群有三台,因为不确定请求会被转发到哪一台上,所以每台服务器都存放9G,显然这样是不合理的。

 我们可以在存储的时候,将图片进行urlhash算法,分别存放到三台服务器上,这样请求的时候也是用urlhash,去指定服务器请求即可,节省了服务器空间,也就是3台服务器总共用了9G。

PS:上面只是举例方便理解,生产中,大量图片资源存放cdn第三方,然后在自己的服务器上做一层临时缓存,为了提高缓存的命中率,通常用urlhash算法。

更多C++后台开发技术点知识内容包括C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,MongoDB,ZK,流媒体,音视频开发,Linux内核,TCP/IP,协程,DPDK多个高级知识点。

C/C++Linux服务器开发高级架构师/C++后台开发架构师​免费学习地址

【文章福利】另外还整理一些C++后台开发架构师 相关学习资料,面试题,教学视频,以及学习路线图,免费分享有需要的可以点击领取

二. 限流配置

1. 说明

(1). 限流的作用

限流主要用作安全目的,比如可以减慢暴力密码破解的速率。

通过将传入请求的速率限制为真实用户的典型值,并标识目标URL地址(通过日志),

还可以用来抵御DDOS攻击。更常见的情况,该功能被用来保护上游应用服务器不被同时太多用户请求所压垮。

(2). 原理

令牌桶算法

漏桶算法

(3). 涉及到的模块

A. 用来限制同一时间连接数,即并发限制 【不常用】

【ngx_http_limit_conn_module】 对应文档:http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html

B. 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 【推荐使用】

【ngx_http_limit_req_module】 对应文档:http://nginx.org/en/docs/http/ngx_http_limit_req_module.html

2. 环境准备

(1). Api接口

启动指令如下:

【dotnet NginxTest.dll --urls="http://*:7061" --ip="127.0.0.1" --port=7061】

【dotnet NginxTest.dll --urls="http://*:7062" --ip="127.0.0.1" --port=7062】

接口地址为: http://localhost:7061/api/Home/GetNowTime 【Post请求】

接口代码如下:

[Route("api/[controller]/[action]")][ApiController]public class HomeController : ControllerBase{[HttpPost]public string GetNowTime(){string nowTime = DateTime.Now.ToString();Console.WriteLine($"当前时间为:{nowTime}");return $"当前时间为:{nowTime}";}}

(2). nginx服务

使用到的指令

启动服务:【start nginx】

 强制关闭服务:【nginx -s stop】

 重载服务:【nginx -s reload】 

nginx监听7000端口,然后进行代理配置,这里重点测试的是限流,只用7061一个api端口即可。

worker_processes  1;
events {worker_connections  1024;
}http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;server {listen       7000;        #监听端口server_name  xxx;         #随意配置一个地址即可,优先走代理location / {proxy_pass http://localhost:7061;   #代理地址}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}  }
}

通过post请求访问:http://localhost:7000/api/Home/GetNowTime ,返回当前时间,表示配置成功。

(3). jmeter测试工具

添加线程组,然后在线程组的基础上添加:http请求、察看结果树、聚合报告、用表格查结果。

配置请求的并发数、请求地址。

 测试结果:10个请求全部成功。

3. 限流-限制并发连接数【不常用】

声明格式:

limit_conn_zone $server_name zone=myLimit0:10m;
limit_conn_zone $binary_remote_addr zone=myLimit1:10m;

(1). $server_name:表示虚拟主机(server) 同时能处理并发连接的总数。 (数量在启用时配置)

(2). $binary_remote_addr:表示限制每个客户端IP(单个ip)连接到服务器的链接数量。 (数量在启用时配置)

(3). zone=myLimit1:10m :表示内存区域名称 和 空间大小。

调用格式:

limit_conn myLimit1 2;	 #启用限流

(1). myLimit1 :表示用上述声明的哪个配置进行限制,myLimit1与上述声明的名称相对应。

(2). 2: 表示配置的数量限制。

(1). 限制-虚拟主机同时能处理的并发链接总数

分析:

虚拟主机(server) 同时能处理并发连接的总数为5.

测试条件:

worker_processes  1;
events {worker_connections  1024;
}
http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;# 限流配置声明limit_conn_zone $server_name zone=myLimit0:10m;server {listen       7000;        #监听端口server_name  xxx;         #随意配置一个地址即可,优先走代理location / {limit_conn myLimit0 5;  #启用限流proxy_pass http://localhost:7061;   #代理地址}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}  }
}

测试结果:

忽略

(2). 限制-单个ip链接到服务器的数量

剖析:

单个IP同时最多能持有8个连接

测试条件:

worker_processes  1;
events {worker_connections  1024;
}
http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;# 限流配置声明limit_conn_zone $binary_remote_addr zone=myLimit1:10m;server {listen       7000;        #监听端口server_name  xxx;         #随意配置一个地址即可,优先走代理location / {limit_conn myLimit1 8;	 #启用限流proxy_pass http://localhost:7061;   #代理地址}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}  }
}

测试结果:忽略

4. 限流-限制速率【推荐使用】

声明格式:

limit_req_zone $binary_remote_addr zone=myLimit2:10m rate=5r/s;

(1). $binary_remote_addr : 表示限制同一客户端ip地址,即限制速率是以ip为分类的,限制每个ip的速度

(2). zone=myLimit2:10m: myLimit2表示内存区域的名称,10m表示内存空间的大小。

(3). rate=5r/s : 表示1s允许5个请求, 注意这里需要拆分理解,即200ms允许1个请求,当第一个请求处理完成,如果200ms内又进来一个请求,该请求将被拒绝处理,只有过了200ms后,才会处理第2个请求,一次类推。

调用格式 :

limit_req zone=myLimit2 burst=5 nodelay;

(1). zone=myLimit2:表示用上述声明的哪个配置进行限制,myLimit2与上述声明的名称相对应。

(2). burst=5 :设置一个大小为5的缓冲区,当有大量请求(瞬间爆发)过来时,超过了上述配置的访问频次限制的请求,可以先放到这个缓冲区内。

注:burst的作用是让多余的请求可以先放到队列里,慢慢处理。如果不加nodelay参数,队列里的请求不会立即处理,而是按照rate设置的速度,以毫秒级精确的速度慢慢处理。

(3). nodelay : 设置后,burst缓冲区中排队的请求立即被处理,超过频次限制 并且 缓冲区满了的情况下,直接返回503状态码;如不设置,那么额外的请求将进入等待排队的状态

注:通过设置burst参数,我们可以允许Nginx缓存处理一定程度的突发,多余的请求可以先放到队列里,慢慢处理,不报错,这起到了平滑流量的作用。

但是如果队列设置的比较大,请求排队的时间就会比较长,从用户角度看来就是响应变长了,这对用户很不友好,所以引入nodelay参数。

  nodelay参数允许请求在排队的时候就立即被处理,也就是说只要请求能够进入burst队列,就会立即被后台处理,请注意,这意味着burst设置了nodelay时,系统瞬间的QPS可能会超过rate设置的阈值。

所以:nodelay参数要跟burst一起使用才有作用。

(1). 实操1-限制速率

分析:

 使用jmeter发送10个请求进行测试,nginx的限制速率设置为 2r/s,意味着第1个请求处理完后,500ms内接收的请求都将拒绝,过了500ms后,才能处理下一个请求。 详见下面的测试结果。

测试条件:

worker_processes  1;
events {worker_connections  1024;
}
http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;# 限流配置声明limit_req_zone $binary_remote_addr zone=myLimit2:10m rate=2r/s;server {listen       7000;        #监听端口server_name  xxx;         #随意配置一个地址即可,优先走代理location / {limit_req zone=myLimit2;	 #启用限流	 proxy_pass http://localhost:7061;   #代理地址}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}  }
}

测试结果:

第1个成功的请求的是008ms,接下来第 2-6个请求,由于是在500ms内,所有都请求失败; 第2个成功的请求为608ms,正好过了500ms了,所以成功了。

(2). 限制速率+设置缓冲区

分析:

使用jmeter发送10个请求进行测试,nginx的限制速率设置为 2r/s,burst=5,意味着第1个请求处理完后,接下来的5个请求都是存放到缓存中,第7个请求如果在第1个的500ms后,则请求成功,反之失败。

测试条件:

worker_processes  1;
events {worker_connections  1024;
}
http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;# 限流配置声明limit_req_zone $binary_remote_addr zone=myLimit2:10m rate=2r/s;server {listen       7000;        #监听端口server_name  xxx;         #随意配置一个地址即可,优先走代理location / {limit_req zone=myLimit2 burst=5;	  #启用限流proxy_pass http://localhost:7061;   #代理地址}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}  }
}

测试结果:

  第1个成功的请求为343ms,接下来第2-6个加入到缓存区,依次执行成功; 第7个请求为944,与第一个成功的请求相比,已经超过了500ms,所以执行成功,接下来的8-10个请求,均在第7个成功后的500ms内,所以均失败。

(3). 限制速率+设置缓冲区+立即处理

分析:

使用jmeter发送10个请求进行测试,nginx的限制速率设置为 2r/s,burst=5 nodelay,意味着第1个请求处理完后,接下来的5个请求立即执行,第7个请求如果在第1个的500ms后,则请求成功,反之失败。

测试条件:

worker_processes  1;
events {worker_connections  1024;
}
http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;# 限流配置声明limit_req_zone $binary_remote_addr zone=myLimit2:10m rate=1r/s;server {listen       7000;        #监听端口server_name  xxx;         #随意配置一个地址即可,优先走代理location / {limit_req zone=myLimit2 burst=5 nodelay;	#启用限流	 proxy_pass http://localhost:7061;   #代理地址}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}  }
}

测试结果:

  第1个成功的请求为278ms,接下来2-6个立即执行,第7个请求为879,距离第一个成功的已经超过500ms,所以执行成功,接下来的8-10个请求,均在500ms内,所以执行失败。

三. Https配置

1. 准备

(1). 生成证书

OpenSSL工具下载地址:http://slproweb.com/products/Win32OpenSSL.html 【这里以3.0.5为例】

OpenSSL生成证书步骤:https://jingyan.baidu.com/article/6c67b1d6be538c2787bb1e06.html

(2). 相关模块

【ngx_http_rewrite_module】 参考文档:http://nginx.org/en/docs/http/ngx_http_rewrite_module.html

2. 实操

(1). 配置https的Server

开启一个新的虚拟主机,用来配置https监听8000端口,配置证书的物理地址即可,就可以通过 https://localhost:8000/api/Home/GetNowTime ,访问代理地址下7061的api了。

(PS:下面配置同时开启了 http的主机,所以通过 http://localhost:7000/api/Home/GetNowTime,也可以访问)

worker_processes  1;
events {worker_connections  1024;
}
http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;#http主机server {listen       7000;          #监听端口server_name  test1;         #随意配置一个地址即可,优先走代理location / {	 proxy_pass http://localhost:7061;   #代理地址}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}  }#https主机server {listen       8000 ssl;server_name  test2;#证书目录ssl_certificate      D:/cert/server-cert.pem;ssl_certificate_key  D:/cert/server-key.pem;ssl_session_cache    shared:SSL:1m;ssl_session_timeout  5m;location / {proxy_pass http://localhost:7061;}}
}

(2). 将http跳转到https

上述http监听的7000端口,https监听的8000端口,如何让http请求自动跳转到https请求上呢?

加个 return 301 xxxxx 跳转即可。

worker_processes  1;
events {worker_connections  1024;
}
http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;#http主机server {listen       7000;          #监听端口server_name  test1;         #随意配置一个地址即可,优先走代理location / {	 proxy_pass http://localhost:7061;   #代理地址#跳转到https (test2是https主机的server_name)return 301 https://test2$request_uri;#或者#return 301 https://$host:8000$request_uri;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}  }#https主机server {listen       8000 ssl;server_name  test2;#证书目录ssl_certificate      D:/cert/server-cert.pem;ssl_certificate_key  D:/cert/server-key.pem;ssl_session_cache    shared:SSL:1m;ssl_session_timeout  5m;location / {proxy_pass http://localhost:7061;}}
}

原文链接:第二节:Nginx负载均衡配置、限流配置、Https配置详解 - Yaopengfei - 博客园

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...