Nginx作为负载均衡服务

一、Nginx负载均衡

1、示意图

Nginx作为负载均衡服务

2、好处

均摊请求,让服务端整体吞吐率提高,满足不断增长的业务需求。

相比于单点服务,当其中一台服务器挂掉后,还可以继续让剩下的服务器继续服务,提高了容灾性。

二、负载均衡的分类

1、GSLB(全局负载均衡)

一般是以国家或省为单位进行全局负载的。

示意图如下:

Nginx作为负载均衡服务

2、SLB

示意图:

Nginx作为负载均衡服务

三、基于LVS的中间件架构

LVS(Linux Virtual Server )Linux 虚拟服务器

1、四层负载均衡

即在OSI七层模型中的传输层。因为第四层支持TCP/IP协议。四层负载均衡只需要对客户端的请求进行TCP/IP协议的包转发就能实现负载均衡。

优势

非常快,只需要最底层进行应用处理,不需要进行一些复杂的逻辑,值需要负责包的转发即可。

示意图

Nginx作为负载均衡服务

2、七层负载均衡

因为是在应用层,因此可以完成很多应用方面的协议请求,比如HTTP协议的负载均衡可以实现HTTP信息的改写,头信息的改写,安全应用规则的控制,转发,rewrite等等方面的规则控制。因此在七层负载均衡里面可以做的事情就更多一些,Nginx就是一个典型的七层负载均衡的SLB。

SLB(Server Load Balancing)服务器负载均衡。

示意图

Nginx作为负载均衡服务

Nginx负载均衡实现原理

通过 proxy_pass 转发到后端的服务器上,只是不是转发到一台,而是一组虚拟的服务池(即 upstream server)。在upstream 组里面实现了对于多台服务器请求的不断轮询。

当用户的请求过来后,就会通过 upstream_module 这个模块将用户的请求分发到不同的服务上,从而实现负载均衡。

故 proxy_pass 和 upstream 是两个核心的配置。

示意图

Nginx作为负载均衡服务

配置语法

ngx_http_upstream_module官方文档 :; http://nginx.org/en/docs/http/ngx_http_upstream_module.html

Syntax:    upstream name { ... }
Default:    —
Context:    http

示例:

a、用一台服务器来实现负载均衡,配置如下:

upstream chrdai {
    server 192.168.0.133:8001;
    server 192.168.0.133:8002;
    server 192.168.0.133:8003;
}

server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    access_log  /var/log/nginx/proxy_cache_access.log  main;

    location / {
        proxy_pass http://chrdai;

        include proxy_params;
    }
}

b、 另外三台真实服务器的配置如下:

我这里是通过同一台服务器的不同端口模拟的。

第一台(/etc/nginx/conf.d/realserver1.conf):

Nginx作为负载均衡服务

第二台(/etc/nginx/conf.d/realserver2.conf):

Nginx作为负载均衡服务

第三台(/etc/nginx/conf.d/realserver3.conf):

Nginx作为负载均衡服务

c、分别在三台真实服务器(当然我这里是在一台服务器中用三个端口模拟的)的项目目录下建立index.html文件。

第一台(/opt/app/code1):

upstream

    Test upstream1

第二台(/opt/app/code2):

upstream

    Test upstream2

第三台(/opt/app/code3):

upstream

    Test upstream3

c、刷新页面,发现页面可以在三个站点间轮询显示。’

Nginx作为负载均衡服务

Nginx作为负载均衡服务

Nginx作为负载均衡服务

说明我们的负载均衡配置成功。

注意:upstream只能配置在 http 这一层,即 server 层的外面。

下面我们来模拟其中一台服务器挂掉后,负载均衡是如何工作的。

如果是真实服务器,可以将nginx进程kill掉,但是由于我这里是在同一台服务器下面的三个端口来模拟的,所以不能直接kill掉Nginx进程。

我这里通过在 iptables 中添加一条规则来将所有来自 8002 端口的请求都 drop 掉,即不在对外提供 8002 端口的服务。

iptables -I INPUT -p tcp --dport 8002 -j DROP

此时我们在来访问页面,发现只会显示 upstream1 和 upstream3,upstream2已经被略过了。

Nginx作为负载均衡服务

Nginx作为负载均衡服务

说明当我们的负载均衡发现如果有一台服务器挂掉后,会自动略过这台服务器。打他提高了容灾性。

四、负载均衡调度中的状态

状态 说明

down 当前的server暂时不参与负载均衡 backup 预留的备份服务器 max_fails 允许请求失败的次数 fail_timeout 经过max_fails失败后,服务暂停的时间(默认是10秒) max_conns 限制最大的接收连接数

max_conns的应用场景是,当我们把两个不同配置的服务器加在了同一个upstream下时,比如一个是四核,一个是8核的服务器,总不能让两台服务器承受相同的请求连接数吧,默认的轮询策略会均匀分配,这时我们就可以通过这个参数来限制后端服务最大的请求数。

示例:

upstream chrdai {
    //8001不启用
    server 192.168.0.133:8001 down;
    //8002设为备份机
    server 192.168.0.133:8002 backup;
    server 192.168.0.133:8003 max_fails=1 fail_timeout=10s;
}

server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    access_log  /var/log/nginx/proxy_cache_access.log  main;

    location / {
        proxy_pass http://chrdai;

        include proxy_params;
    }
}

此时我们在访问,发现只有8003 在提供服务。

Nginx作为负载均衡服务

下面我们用iptables规则来限制来自8003的请求,看8002能否从备份状态恢复为提供服务状态。

iptables -I INPUT -p tcp --dport 8003 -j DROP

服务端经过一段时间的尝试,发现8003挂了,果然将8002转正了。

Nginx作为负载均衡服务

我们再次刷新页面,在8003没有恢复之前,都是访问的8002。

下面我们来将8003的服务恢复过来。

iptables -F

再次刷新页面,发现又是由8003来提供服务了,8002继续轮为备胎。

Nginx作为负载均衡服务

结论:

  • 当我们负载均衡中其中一台服务器挂掉后,会略过该服务器,剩下的服务器继续提供服务。
  • 当所有的主服务器都挂掉后,备用服务器会转正。
  • 当主服务器恢复后,继续由主服务器提供服务,备用服务器继续轮为备胎。

五、Nginx的调度算法

调度算法

调度算法名称 说明 轮询 按时间顺序逐一分配到不同的后端服务器 加权轮询 weight值越大,分配到的访问几率越高 ip_hash 每个请求按访问IP的的hash结果分配,这样来自同一个IP的固定访问一个后端服务器 url_hash 按照访问的url的hash结果来分配请求,使每个url定向到同一个后端服务器 least_conn 最少链接数,哪个机器连接数少,就分给哪个机器 hash关键数值 hash自定义的key

1、加权轮询示例:

upstream chrdai {
    server 192.168.0.133:8001;
    server 192.168.0.133:8002 weight=5;
    server 192.168.0.133:8003;
}
//理论上来讲,如果请求7次,应该有 5 次会请求 8002 所对应的这台服务器

2、ip_has策略示例:

upstream chrdai {
    ip_hash;
    server 192.168.0.133:8001;
    server 192.168.0.133:8002;
    server 192.168.0.133:8003;
}

服务器会根据 REMOTE_ADDR 做hash,同一个ip的请求,不管请求多少次,都会请求相同的一台服务器。

它的缺点是,如果中间有一层代理,那么取到的就不是客户端真实的ip,这样就无法基于用户真实的ip来做轮询了。而会跟代理服务器的ip来固定走一台服务器。

如果按照ip来分配,往往取不到用户端真实的ip。还有一个问题就是当服务端使用了缓存,假如一个用户先访问了服务器1,服务器1缓存了一部分资源,下一次访问的时候被轮询到了服务器2,那么上一次的缓存就无效了,Nginx又增加了更加友好的hash策略。

3、hash关键数值轮询策略

配置语法:

//version>1.7.2Syntax:hash key [consistent];
Default:-;
Context:upstream;

4、url_hash 示例:

upstream chrdai {
    hash $request_uri;
    server 192.168.0.133:8001;
    server 192.168.0.133:8002;
    server 192.168.0.133:8003;
}

在 /opt/app/cod1 目录下新建三个文件。

url1.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>upstreamtitle>
head>
<body>
    <p>server1 url1p>
body>
html>

url2.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>upstreamtitle>
head>
<body>
    <p>server1 url2p>
body>
html>

url3.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>upstreamtitle>
head>
<body>
    <p>server1 url3p>
body>
html>

/opt/app/code2 和 /opt/app/code3 目录下也创建三个 urlx.html,页面内容和上面同理,修改一下 server的值和url的值即可。

此时由于我们的hash策略是根据 reques_uri 来的,所以会有如下结果。

a、当我们访问 http://192.168.0.133/url1.html 时,由于一开始就进入了 server1 这台服务器,不管怎么刷新,以后也永远进入server1这台服务器,因为它是根据 request_uri来做的hash。

Nginx作为负载均衡服务

b、当我们访问 http://192.168.0.133/url2.html 时,由于一开始就进入了 server3 这台服务器,不管怎么刷新,以后也永远进入server3这台服务器。

Nginx作为负载均衡服务

c、当我们访问 http://192.168.0.133/url3.html 时,由于一开始就进入了 server2 这台服务器,不管怎么刷新,以后也永远进入server3这台服务器。

Nginx作为负载均衡服务

总结:

  • 加权轮询和轮询都是基于请求来进行分配的。
  • ip_hash策略,当中间有代理服务或者有设置缓存都有一定的局限性。
  • 通常使用自定义的 url_hash策略来控制轮询。
  • 当加权轮询策略和ip_hash 或者 url_hash 策略混用的时候,因为weight控制的是轮询策略下的权重,ip_hash是根据请求来源的ip加入轮询的算法。所以用了ip_hash或者url_hash的策略,就不需要添加weight的参数了。

本文为袋鼠学习中的总结,如有转载请注明出处:https://www.cnblogs.com/chrdai/protected/p/11397397.html ;

Original: https://www.cnblogs.com/chrdai/p/11397397.html
Author: Chrdai
Title: Nginx作为负载均衡服务

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/543829/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 使用 Certbot 申请 Let’s Encrypt SSL 证书,并定时续期

    网站有个 SSL 证书,可以提高安全性、及提高搜索引擎的排名。Let’s Encrypt SSL 证书是免费的,可以用命令行申请,也可以用命令行续期。 Let&#821…

    Java 2023年6月9日
    068
  • 【设计模式】三种工厂模式

    【设计模式】工厂模式 相对来说,写的比较乱,但是看一下实例,其实理解很快 抽象工厂模式(这里主要介绍抽象工厂模式) 核心的工厂类不再负责所有对象的创建,而是将具体的创建工作交给子类…

    Java 2023年6月13日
    072
  • 在 IconFont 上获取图标资源的操作方法与感悟

    如何在 IconFont 上获取图标资源 阿里巴巴矢量图标库网站(https://www.iconfont.cn/)上提供了非常丰富的图标资源,包括 SVG、AI、PNG、字体图标…

    Java 2023年6月16日
    0104
  • MySQL十二:索引分析

    转载~ 数据库优化是一个很常见的面试题,下面就针对这一问题详细聊聊如何进行索引与sql的分析与优化。 一、执行计划(EXPLAIN) MySQL 提供了一个 EXPLAIN 命令,…

    Java 2023年6月8日
    077
  • java中的集合

    数组的缺点引出集合的好处 数组有很多不足的地方 长度从一开始就必须指定的大小 元素的类型必须一致 使用数组的增删改查,代码比价多比较麻烦 集合的好处 可以动态的保存任意对象 提供了…

    Java 2023年6月6日
    076
  • Spring框架的XML扩展特性

    Spring框架从2.0版本开始,提供了基于Schema风格的XML扩展机制,允许开发者扩展spring配置文件。现在我们来看下怎么实现这个功能,可以参考spring帮助文档中的《…

    Java 2023年5月30日
    074
  • 线程池

    一.为什么使用线程池? 降低资源的消耗 线程的复用 控制最大的并发数 管理线程 二.执行流程 在创建了线程池后,开始等待请求 当调用execute()方法添加一个请求任务时,线程池…

    Java 2023年6月7日
    0108
  • 【转】消息中间件MQ的学习境界和路线

    原文:https://www.cnblogs.com/xiexj/p/16095395.html Original: https://www.cnblogs.com/tc310/p…

    Java 2023年5月29日
    095
  • knife4j的学习

    https://www.toutiao.com/a6789135368064074253/?tt_from=mobile_qq&utm_campaign=client_s…

    Java 2023年5月29日
    067
  • Python递归遍历目录并删除文件中的前N行

    1 import os 2 3 # 遍历目录下的所有文件 4 def check_file(file_path): 5 os.chdir(file_path) 6 print(os…

    Java 2023年6月7日
    075
  • Map 笔记记录

    Map 是一个存放二元 Key – Value 对的数据集合接口。在其中每个元素都对应于一个唯一的 key,使用 key 可以获得对应的 value。 其有如下两个常用…

    Java 2023年6月7日
    080
  • LeetCode.1137-第N个泰波那契数(N-th Tribonacci Number)

    这是小川的第 409次更新,第 441篇原创 看题和准备 今天介绍的是 LeetCode算法题中 Easy级别的第 260题(顺位题号是 1137)。Tribonacci(泰波那契…

    Java 2023年6月5日
    093
  • java动态代理实现与原理详细分析

    关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式–代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理。 一、代理模式 代理模式是…

    Java 2023年5月29日
    085
  • Eureka详解系列(二)–如何使用Eureka(原生API,无Spring)

    简介 通过上一篇博客 Eureka详解系列(一)–先谈谈负载均衡器 ,我们知道了 Eureka 是什么以及为什么要使用它,今天,我们开始研究如何使用 Eureka。 在…

    Java 2023年6月13日
    074
  • Springboot使用Maven Profile和Spring Profile进行多环境配置

    https://www.jianshu.com/p/b7c75b0c364c Original: https://www.cnblogs.com/tszr/p/16506781.h…

    Java 2023年5月30日
    070
  • JVM-垃圾回收机制

    引用计数法 可达性分析 Java 中常见的垃圾回收算法 标记-清除算法 复制算法 标记-整理算法 分代回收算法 内存分配机制 Minor GC 和 Full GC 垃圾收集器 在 …

    Java 2023年6月9日
    070
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球