写点什么

一文读懂网关中间件 -Nginx

  • 2022 年 3 月 19 日
  • 本文字数:4440 字

    阅读完需:约 15 分钟

一、Nginx 介绍

1.nginx 是一个高性能 HTTP 服务器,反向代理服务器,邮件代理服务器,TCP/UDP 反向代理服务器.

2.nginx 处理请求是异步非阻塞的,在高并发下 nginx 能保持低资源低消耗高性能,主要用在集群系统中用于支持负载均衡.

3.nginx 对静态文件的处理速度也相当快,也可以用于前端站点的服务器.

相关视频讲解:

C++后台开发架构师学习视频

网站被攻击了,Nginx是不是该背这个锅?

网络穿透,NAT,打洞,了解p2p的秘密

二、为什么要使用 Nginx?

单个系统主要用于处理客户端请求,一个系统处理客户端的请求量是有限的,当客户端的并发量超过了系统的处理能力的时候,就会导致服务器性能降低,速度变慢,直接影响用户体验,所以为了提升性能,我们会创建多个服务实例,形成集群系统用于保证高可用

那么什么样的系统业务适合使用集群系统呢?我觉得主要从 2 个方面来看,第一请求人数多,导致次数多,第二请求量密集,例如我们近两年常用的防疫健康码查询,我们排除与其他的业务系统接入的因素,可以说他的 99%针对用户的业务其实就是查询,而且并发量和请求数也是非常庞大的,所以就很适合使用集群系统。

三、查询分流 Nginx 原理

1.模块化设计

高度模块化的设计是 Nginx 的架构基础。在 Nginx 中,除了少量的核心代码,其他一切皆为模块,所有模块间是分层次、分类别的,Nginx 官方共有五大类型的模块:核心模块、配置模块、事件模块、HTTP 模块、mail 模块,5 种模块中,配置模块和核心模块是与 Nginx 框架密切相关的。而事件模块则是 HTTP 模块和 mail 模块的基础。HTTP 模块和 mail 模块的“地位”类似,它们都是更关注于应用层面并且引用基础核心模块。

2.多进程模型

与 Memcached 的经典多线程模型相比,Nginx 是经典的多进程模型,Nginx 启动后在后台运行,后台进程包含一个 master 进程和多个 worker 进程,可以在配置中设置工作进程数,一般根据服务器的 Cpu 核心数,来决定工作进程数是多少,例如我的电脑核心数是 12,那可以在配置文件中设置 worker_processes 为 12,那么在进程中可以看到 一个 13 个 nginx 运行实例。


3.事件驱动架构

处理请求事件时,Nginx 的事件消费者只是被事件分发者进程短期调用而已,这种设计使得网络性能、用户感知的请求时延都得到了提升,每个用户的请求所产生的事件会及时响应,整个服务器的网络吞吐量都会由于事件的及时响应而增大。当然,这也带来一定的要求,即每个事件消费者都不能有阻塞行为,否则将会由于长时间占用事件分发者进程而导致其他事件得不到及时响应,Nginx 的非阻塞特性就是由于它的模块都是满足这个要求,其实 Nginx 最佳的部署应该在 linux ,linux 的 io 及事件驱动优于 windows,我们可以通过配置文件中设置 events 的数量表示当前的 nginx 能处理多少个请求,这个没有一个绝对的标准,可以基于服务的性能和本身业务需求而定。

4.虚拟主机、反向代理、负载均衡

1.虚拟主机就是为了对所有应用系统进行反向代理。2.反向代理是指代理后端服务器,正向代理代表代理客户端。3.负载均衡将流量均分到指定后端实例。

四、落地 Nginx

我们首先结合实际业务场景分析,然后对不同的业务用例进行落地实践的方案选择。

1.负载均衡业务实践

1.首先我们应该准备一个业务系统,在这就用上面说的“健康码查询”业务,模拟一个查询的服务,注意在这仅仅只是引用场景示例,不代表健康码真实场景如此, 因为我没有参与真正的防疫健康码的开发和设计,也不了解它业务和技术架构上真正的复杂度,单纯只是由此引入业务场景而已,如果您在阅读时觉得这样不合适,您可以把他当做你想当做的任何系统,或者忘记这件事,都是可以的接下来我们应该下载 Nginx 作为我们的服务器,在这里我使用的是在 Windows 环境下的演示,其实不管在 Linux 或者 Docker 中部署都可以,但是开发在 windows,所以基于 Windows 比较方便。

  • 1.创建健康码服务


2.我们应该创建服务集群,在这为了演示创建 2 个服务实例,然后使用 nginx 来进行负载均衡查询分流

  • 1.命令行启动 2 个服务实例模拟集群,分别绑定端口 8081 和 8082,其实真实环境不会只有 2 个实例或者在同一台服务器上部署。

  • 2.配置 nginx 的反向代理和负载均衡

worker_processes  1;   error_log  logs/error.log  info;   events {       worker_connections  1024;   }   http {    include       mime.types;    default_type  application/octet-stream;    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '    access_log  logs/access.log  main;    sendfile        on;    keepalive_timeout  65;        #虚拟主机    server{      listen       8080;      server_name  localhost;      #配置反向代理      location / {               proxy_pass  http://HealthCode;           }      error_page   500 502 503 504  /50x.html;     }   }   #负载均衡配置   upstream HealthCode{           server localhost:8081;           server localhost:8082;   }
复制代码
  • 3.启动 nginx,并访问虚拟服务器

2.负载均衡业务场景分析

针对上面的业务,我们使用到 nginx 实现负载均衡,那对于我们来说,应该知道 Nginx 虚拟主机,是如何将我们的请求转发到各个不同的服务实例的,下面结合业务用例来介绍 Nginx 中的各种负载均衡算法,并设置对应的配置文件节点。

1.轮训算法

根据字面理解就是轮训处理 1 2 3 4 周而复始,它是 upstream 模块默认的负载均衡默认策略,适合服务器处理能力相同的实例,在轮询中,如果某个服务实例宕机了,会自动剔除该服务器。,也可以加入权重,指定轮询几率,weight 和访问比率成正比,用于服务器性能不均的情况下,权重越高,在被访问的概率越大,如下面分别是 20%,80%。

#负载均衡配置upstream HealthCode{    server localhost:8081;    server localhost:8082;
#server localhost:8081 weight=2; #server localhost:8082 weight=8;}
复制代码

2.最小连接数算法 least_conn

当客户端给 Nginx 发送查询健康码的请求时,Nginx 把请求转发给 8081 和 8082 ,如果 8082 处理请求比较慢,会导致请求堆积在 8082,那我们就需要解决请求堆积的问题,在这种场景下,我们可以把请求转发给连接数较少的服务器处理,能够达到更好的负载均衡效果,使用 least_conn 算法,在 nginx 配置文件中,负载均衡节点加入配置 least_conn

#负载均衡配置upstream HealthCode{    #配置最小连接数算法    least_conn;    server localhost:8081;    server localhost:8082;}
复制代码

3. hash 一致性算法 ip_hash

由于查询压力过大,为了提升可用性,我们在服务端加入缓存,例如 3 分钟之内请求,就直接将缓存的信息丢出去,客户端给 Nginx 发送查询健康码的请求时,Nginx 把请求转发给 8081 和 8082,甚至更多实例,使用轮训或者最小连接数时,会导致在缓存的情况下命中率下降,基于这种缓存状态丢失的情况,请求依然会给到没有缓存的服务实例,并去数据库中去查询数据,导致性能下降。

(当第一次请求发送到 8081 去查询了数据库,但是在 8082 或者其他的节点没有缓存,如果使用轮训算法及其他算法,会导致下次请求时,并不会访问缓存,所以叫缓存命中率下降)在这种场景下我们应该使用 Hash 一致性算法,将某一个请求客户端的 ip 地址与 nginx 的负载均衡中的某一个实例绑定。

#负载均衡配置upstream HealthCode{  #配置iphash算法    ip_hash;    server localhost:8081;    server localhost:8082;}
复制代码

4.容灾策略

重试机制

1.当客户端给 Nginx 发送查询请求时,Nginx 把请求转发给 8081 和 8082 ,如果转发到 8081 的时候,8081 服务器被人拉闸,临时宕机了,会导致请求失败。如何保证请求成功?在这种场景下我们应该使用 nginx 的失败重试机制,将某一个请求客户端的 ip 地址与 nginx 的负载均衡中的某一个实例绑定。

#动态负载均衡配置upstream HealthCode{     ip_hash;     #设置最大失败次数2次,超时时间10s钟     server localhost:8081 max_fails=2 fail_timeout=10s;     server localhost:8082 max_fails=2 fail_timeout=10s;}
复制代码

主机备份 backup1.查询时请求转发给 8081 和 8082 ,假设此时两个实例同时宕机了,会导致系统不可用,在这种异常业务情况下,我们可以使用主机备份来解决,注意在正常节点在运行时 ,备份节点是不工作的,如果使用 ip_hash 将不会生效,因为 ip 和主机已经绑定。

#动态负载均衡配置upstream HealthCode{    ip_hash;    server localhost:8081 max_fails=2 fail_timeout=10s;    server localhost:8082 max_fails=2 fail_timeout=10s;    #主机备份    server localhost:8083 backup;}
复制代码

五、配置 HTTPS

我们要保证我们的请求的安全,所以需要使用 Https 通信,同样需要对我们的虚拟主机设置 https,设置 https 的前提需要证书,一个是秘钥(server-key.pem),一个是证书(server-cert.pem)。

1.基本设置

1.下载 openSSL,然后使用 openSSL 工具生成,教程连接 2.找到证书生成路径 3.然后在 nginx 配置文件添加对应的虚拟主机节点,然后配置 Https

# https 虚拟主机    server {        listen       4435 ssl;        server_name  localhost;
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;
# ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on;
location / { proxy_pass http://HealthCode; } }
复制代码

2.http 转 https

系统当中总是有很多默认的 Http 请求,我们需要使用 nginx 的 ngx_http_rewrite_module 模块来将 http 请求转换成 https

worker_processes  1;    error_log  logs/error.log  info;    events {        worker_connections  1024;    }    http {     include       mime.types;     default_type  application/octet-stream;     log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '     access_log  logs/access.log  main;     sendfile        on;     keepalive_timeout  65;          #虚拟主机     server{       listen       8080;       server_name  localhost;
#默认重定向到https if($scheme = http) { return 301 https://$host:4435$request_url }
#配置反向代理 location / { proxy_pass http://HealthCode; } error_page 500 502 503 504 /50x.html; } }#负载均衡配置upstream HealthCode{ server localhost:8081; server localhost:8082; }
复制代码

想学习 C++工程化、高性能及分布式、深入浅出。性能调优、TCP,协程,Nginx 源码分析 Nginx,ZeroMQ,MySQL,Redis,MongoDB,ZK,Linux 内核,P2P,K8S,Docker,TCP/IP,协程,DPDK 学习资料视频获取点击:C++架构师学习资料

C++后台开发视频链接:C/C++Linux服务器开发高级架构师/Linux后台架构师​


用户头像

Linux服务器开发qun720209036,欢迎来交流 2020.11.26 加入

专注C/C++ Linux后台服务器开发。

评论

发布
暂无评论
一文读懂网关中间件-Nginx_nginx_Linux服务器开发_InfoQ写作平台