草庐IT

Nginx 实战-负载均衡

阳仔的屁仔 2023-05-05 原文

一、负载均衡

今天学习一下Nginx的负载均衡。由于传统软件建构的局限性,加上一台服务器处理能里的有限性,在如今高并发、业务复杂的场景下很难达到咱们的要求。但是若将很多台这样的服务器通过某种方式组成一个整体,并且将所有的请求平均的分配给这些机器处理,那么这个“系统”就能处理尽可能多的请求,这就是负载均衡最初的设计思想。

当然可以使用的技术包含软件、硬件,咱们本次就着重谈谈Nginx的负载均衡。下图是一个四层 + 七层的负载均衡。采用lvs+nginx的拓扑结构。

二、负载均衡概念

1、什么是负载均衡

负载均衡,简称LB(Load Balancing),是一种计算机技术。用来在多个计算机(计算机集群)、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到最优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的。宏观上的意思是将负载(工作任务,访问请求)进行平衡、分摊到多个操作单元(服务器,组件)上进行执行以解决高性能,单点故障(高可用),扩展性(水平伸缩)等高流量下常见的问题。

2、负载均衡分类

由于载均衡技术是要对网络传输中的报文进行控制,涉及到网络七层模型,因此负载均衡分类可以按照网络层次进行分类,比如二层、三层、四层、七层负载均衡。其中最常见的是四层和七层负载均衡。此外,还有其他方面进行分类的,有软衡、硬件负载均衡等,比如SpringCloud全家桶中的Eureka组件、各种分库分表的中间件都属于负载均衡的范畴。二层、三层、四层、七层负载均衡都都工作在OSI模型,接下来会对做一个简单的解释。业界已经有很多开源的负载均衡工具,大部分是工作在第四层和第七层的。代表的开源工具有Nginx、LVS、Haproxy。LVS 主要用来做四层负载均衡,Nginx 和 Haproxy 主要是做七层的负载均衡,但它们都支持四层的负载均衡,例如在 Nginx 中的 stream 模块除了支持四层的反向代理功能,也支持四层负载均衡功能。

2.1 二层负载均衡

负载均衡服务器对外提供一个VIP(虚拟IP),集群中不同的机器采用相同IP地址,但是机器的MAC地址不一样。当负载均衡服务器接受到请求之后,通过改写报文的目标MAC地址的方式将请求转发到目标机器实现负载均衡。二层负载均衡发生在数据链路层,所以也称为“数据链裤层负载均衡”它是属于OSI模型。

2.2 三层负载均衡

负载均衡服务器对外提供一个VIP(虚拟IP),但是集群中不同的机器采用不同的IP地址。当负载均衡服务器接受到请求之后,根据不同的负载均衡算法,通过IP将请求转发至不同的真实服务器。三层负载均衡发生在网络层故又称为“网络层负载均衡”,同样的它也是属于OSI模型。

2.3 四层负载均衡

四层负载均衡工作在OSI模型的传输层,由于在传输层,只有TCP/UDP协议,这两种协议中除了包含源IP、目标IP以外,还包含源端口号及目的端口号。四层负载均衡服务器在接受到客户端请求后,以后通过修改数据包的地址信息(IP+端口号)将流量转发到应用服务器。

2.4 七层负载均衡

七层负载均衡工作在 OSI 模型的应用层,应用层协议较多,常用 http、dns 等。七层负载就可以基于这些协议来负载。这些应用层协议中会包含很多有意义的内容。比如同一个 Web 服务器的负载均衡,除了根据 IP 加端口进行负载外,还可根据七层的 URL、浏览器类别、语言来决定是否要进行负载均衡。

3、负载均衡算法

负载均衡算法可以分成两大类,一类是静态的负载均衡算法,常见的有轮询、权重等;另一大类动态的负载均衡算法,常见的有最少的连接、最快响应、服务类型、服务质量等等。下面就着重记录几种常用的负载均衡算法。

3.1 轮询 (默认)

每一个来自网络中的请求,轮流分配给内部的服务器,从 1 到 N 然后重新开始。此种负载均衡算法适合服务器组内部的服务器都具有相同的配置并且平均服务请求 相对均衡的情况。

3.2 加权轮询(weight)

根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。例如:服务器 A 的权值被设计成 1,B 的权值是 3,C 的权值是6,则服务器 A、B、C 将分别接受到 10%、30%、60% 的服务请求。此种均衡算法能确保高性能的服务器得到更多的使用率,避免低性能的服务器负载过重。

3.2 ip-hash(ip_hash)

我们都知道,每个请求的客户端都有相应的 ip 地址,该均衡策略中,nginx 将会根据相应的 hash 函数,对每个请求的 ip 作为关键字,得到的 hash 值将会决定将请求分发给相应 Server 进行处理。iphash算法的情况下,每一个IP在不变的情况下都会路由到首次请求的服务上。

3.2 最少连接数(least_conn)

最少连接,也就是说 nginx 会判断后端集群服务器中哪个 Server 当前的 Active Connection 数是最少的,那么对于每个新进来的请求,nginx 将该其分发给对应的 Server。

4. Nginx中的负载均衡配置

Nginx 的 stream 模块和 http 模块分别支持四层和七层模块的负载均衡。其用法和支持的负载均衡策略大致相同。首先使用 upstream 指令块 和 server 指令指定上游的服务,upstream 指令的用法如下

upstream name { ... }

官网示例如下:下面定义了4台服务器,分别是域名、IP+端口、socket形式指定地址,默认情况下upstream指令块中采用的是加权轮训的方式轮询配置得服务,当然我们可以指定一些服务的静态配置,比如注定服务的权重、server的最大并发连接max_conns,(max_fails 和 fail_timeout)失败几次之后将服务标记为故障服务,在设置的时间内不在路由到标记为故障的服务。

upstream backend {
    server backend1.example.com weight=5;
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server unix:/tmp/backend3;
    server backup1.example.com  backup;
}

三、 负载均衡实践

基础知识梳理完毕,接下来进行实践来感受一下相关的概念,俗话说的:好纸上得来终觉浅,绝知此事要躬行!希望可以通过这些实验让咱们更加巩固这些技术点。

1、Nginx中负载均衡

环境准备:mac,我这边使用的是docker安装的nginx,安装教程可以根据我的这篇文章:传送门:Nginx教程,两给SpringBoot服务。首先咱们搭建环境。因为我们之前学习过docker挂载,所以这次修改Nginx文件就方便很多,需要的同学可以参考:docker 挂载、修改文件,如果没有进行挂载想要修改文件的可以参考这篇文章。废话不多说直接上case.

1.1 两个微服务

首先提供两个微服务模拟一份代码两台机器。两个服务都有一个路径相同的对外接口。

@RestController
@Slf4j
public class Demo1LBController {

    @GetMapping("/lb/start")
    public String demo1() {
        String str = "demo1 lb start ...";
        log.info(str);
        System.out.println(str);
        return str;
    }
}

@RestController
@Slf4j
public class Demo2LBController {

    @GetMapping("/lb/start")
    public String demo2() {
        String str = "demo2 lb start ...";
        log.info(str);
        System.out.println(str);
        return str;
    }
}

1.2 Nginx配置修改

upstream 块在http块中,用于设置一系列的后端服务器,设置反向代理及后端服务器的负载均衡。咱们定义负载均衡的服务叫做:myserver,然后在 server 块里的 location 配置代理:proxy_pass http://myserver;。

nginx.config里的配置
    # ######## 负载均衡开始 ########
    upstream myserver {
       server 10.33.148.23:8081;
       server 10.33.148.23:8082;

       # server backend1.example.com weight=5;
       # server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
       # server unix:/tmp/backend3;
       # server backup1.example.com  backup;
   }
    # ######## 负载均衡结束 ########
    
default.config里的配置
   location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        proxy_pass http://myserver;

    }

1.2 验证

咱们启动NG之后,在浏览器输入:http://localhost:8010/lb/start,即可得到请求到不同服务的返回,默认走的轮询所以都是规律性的返回。

2、轮询

轮询的配置就是不设置任何静态参数,采用 Nginx 默认的负载均衡策略,上面的验证就是,我这边就做赘述。

3、加权轮询

顾名思义就是根据服务器的不同处理能力,给每个服务器分配不同的权值。具体配置如下,8081的服务权重占4/5,大家可以在浏览器操作感受一下。

4、ip_hash

每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 的问题。配置上ip hash之后即使有权重也不会重新请求其他的服务上。大家可以操作感受。

ip_hash;

5、参数说明

weight=number 设定服务器的权重,默认是1,权重越大被访问机会越大,可以根据机器的配置情况来配置。

max_fails=number 设定Nginx与服务器通信的尝试失败的次数。在fail_timeout参数定义的时间段内,如果失败的次数达到此值,Nginx就认为服务器不 可用。在下一个fail_timeout时间段,服务器不会再被尝试。 失败的尝试次数默认是1。

默认配置时,http_404状态不被认为是失败的尝试。 可以通过指令proxy_next_upstream 和memcached_next_upstream来配置什么是失败的尝试。

fail_timeout=time
统计失败尝试次数的时间段。在这段时间中,服务器失败次数达到指定的尝试次数,服务器就被认为不可用。默认情况下,该超时时间是10秒。 

backup
标记为备用服务器。当主服务器不可用以后,请求会被传给这些服务器,配置这个指令可以实现故障转移。

down 标记服务器永久不可用,可以跟ip_hash指令一起使用。

负载均衡的相关知识就梳理完毕啦,本次对 Nginx 中的负载均衡的相关配置指令,实战 Nginx 的负载均衡功能,同时测试多种负载均衡算法的学习和记录希望可以帮助大家更好的里解Nginx。

有关Nginx 实战-负载均衡的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  3. ruby-on-rails - 如何用不同的用户运行nginx主进程 - 2

    A/ctohttp://wiki.nginx.org/CoreModule#usermaster进程曾经以root用户运行,是否可以以不同的用户运行nginxmaster进程? 最佳答案 只需以非root身份运行init脚本(即/etc/init.d/nginxstart),就可以用不同的用户运行nginxmaster进程。如果这真的是你想要做的,你将需要确保日志和pid目录(通常是/var/log/nginx&/var/run/nginx.pid)对该用户是可写的,并且您所有的listen调用都是针对大于1024的端口(因为绑定(

  4. ruby-on-rails - Websocket-rails 不适用于 Nginx 和 Unicorn 的生产环境 - 2

    我有带有gemwebsocket-rails0.7的Rails3.2应用程序。在开发机上,一切正常在生产环境中,我使用Nginx/1.6作为代理服务器,Unicorn作为http服务器。Thin用于独立模式(在https://github.com/websocket-rails/websocket-rails/wiki/Standalone-Server-Mode之后)。nginx配置:location/websocket{proxy_passhttp://localhost:3001/websocket;proxy_http_version1.1;proxy_set_headerUp

  5. ruby - 没有 nginx 的 Puma - 同一 IP 上的多个 ruby​​ 应用程序 :PORT - 2

    Nginx在生产中的重要性通常基于它为慢速客户端提供服务的能力;在RESTfulAPI的设置中,它似乎是生产堆栈的一个不必要的层,尤其是Puma(不像广泛使用的unicorn可以处理nginx工作)。Pumacanallowmultipleslowclientstoconnectwithoutrequiringaworkertobeblockedontherequesttransaction.Becauseofthis,Pumahandlesslowclientsgracefully.HerokurecommendsPumaforuseinscenarioswhereyouexpect

  6. ruby-on-rails - EC2 实例在负载均衡器中停止服务 - 2

    我有一个EC2实例正在运行。我有一个负载均衡器,它与EC2实例相关联。PingTarget:HTTP:3001/healthCheckTimeout:5secondsInterval:24secondsUnhealthythreshold:2Healthythreshold:10现在该实例显示为OutofService。我什至尝试更改监听端口等等。一切正常,直到重新启动我的EC2实例。任何帮助将不胜感激。仅供引用:我有一个在端口3001上运行的Rails应用程序,我有一个用于HTTP:80(loadbalancer)到HTTP:3001的监听器。我还在终端中通过ssh检查了正在运行的应

  7. ruby-on-rails - Foreman无法启动Nginx,但我可以手动启动。为什么? - 2

    我目前正在运行Foreman在暂存(Ubuntu)上,一旦我开始工作,就会切换到使用upstart。我的Procfile.staging看起来像这样:nginx:sudoservicenginxstartunicorn:bundleexecunicorn-c./config/unicorn.rbredis:bundleexecredis-serversidekiq:bundleexecsidekiq-v-C./config/sidekiq.yml我可以使用以下方法成功启动nginx:$sudoservicenginxstart然而,当我运行$foremanstart时,当其他三个进程成

  8. ruby-on-rails - 负载测试期间 Unicorn CPU 使用率激增,优化方法 - 2

    我对为我的RubyonRails3.1.3应用优化我的Unicorn设置的方法很感兴趣。我目前正在高CPU超大实例上生成14个工作进程,因为我的应用程序在负载测试期间似乎受CPU限制。在模拟负载测试中,每秒大约20个请求重放请求,我的实例上的所有8个内核都达到峰值,盒子负载飙升至7-8个。每个unicorn实例使用大约56-60%的CPU。我很好奇可以通过哪些方式对其进行优化?我希望能够每秒将更多请求汇集到这种大小的实例上。内存和所有其他I/O一样完全正常。在我的测试过程中,CPU越来越低。 最佳答案 如果您受CPU限制,您希望使用

  9. 你真正了解什么是接口测试么?接口实战一“篇”入魂 - 2

    最近在工作中,看到一些新手测试同学,对接口测试存在很多疑问,甚至包括一些从事软件测试3,5年的同学,在聊到接口时,也是一知半解;今天借着这个机会,对接口测试做个实战教学,顺便总结一下经验,分享给大家。计划拆分成4个模块跟大家做一个分享,(接口测试、接口基础知识、接口自动化、接口进阶)感兴趣的小伙伴记得关注,希望对你的日常工作和求职面试,带来一些帮助。注:文章较长有5000多字,希望小伙伴们认真看完,当然有些内容对小白同学不是太友好,如果你需要详细了解其中的一些概念或者名词,请在文章之后留言,后续我将针对大家的疑问,整理输出一些大家感兴趣的文章。随着开发模式的迭代更新,前后端分离已不是新的概念,

  10. Linux操作系统CentOS7安装Nginx[详细版] - 2

    Nginx安装1.官网下载Nginx2.使用XShell和Xftp将压缩包上传到Linux虚拟机中3.解压文件nginx-1.20.2.tar.gz4.配置nginx5.启动nginx6.拓展(修改端口和常用命令)(一)修改nginx端口(二)常用命令1.官网下载Nginxhttp://nginx.org/en/download.html这里我下载的是1.20.2版本,大家按需下载对应稳定版即可2.使用XShell和Xftp将压缩包上传到Linux虚拟机中没有XShell可以参考《Linux操作系统CentOS7连接XShell》3.解压文件nginx-1.20.2.tar.gz1)检查是否存

随机推荐