当前位置: 首页 > article >正文

Nginx 负载均衡和反向代理

Nginx 是一个高性能的 HTTP 服务器和反向代理服务器,广泛应用于负载均衡中。它的负载均衡功能支持多种策略,可以有效分配流量到后端服务器,提升系统的可靠性和可用性。

负载均衡

首先,Nginx 负载均衡配置是通过在 Nginx 配置文件中定义 upstream 块和对应的 server 块来实现的。Nginx 安装过程就不多说了,如果没有安装,可以参考安装链接:Nginx 安装和访问-CSDN博客

负载均衡配置

我这儿以我的示例进行的配置。先在 192.168.128.139 机器上修改 nginx.conf (记得先将原 nginx.conf 备份)。

events {
    worker_connections  1024;
}

http {
    upstream backend {
        server 192.168.128.139:5001 weight=1;
        server 192.168.128.138:5001 weight=2;
    }

    server {
        listen 5000;
        location / {
            proxy_pass http://backend;
        }
    }
}

在上面的例子中,upstream backend 定义了一个名为 backend 的服务器组,包含了两个后端服务器,并设置权重分别为 1 和 2。

server 监听指定端口 5000(监听并转发来自 5000 端口的请求), proxy_pass 指令则将请求代理到定义的服务器组 backend 中。

配置好以后,执行 sbin/nginx 启动服务(后续修改 nginx.conf 配置以后,可使用 sbin/nginx -s reload 命令重新加载配置即可)。

root@master /u/l/nginx# pwd
/usr/local/nginx
root@master /u/l/nginx# sbin/nginx

为了配合验证 nginx 的负载均衡,我分别在两个虚拟机 192.168.128.139 和 192.168.128.138 上分别搭建了一个 flask 服务。

服务示例

如果仅仅是测试,为了避免访问被挡住的问题,可以将测试虚拟机的防火墙关闭。

[root@master ~]# service iptables stop
Redirecting to /bin/systemctl stop iptables.service
root@slave ~# service firewalld stop
Redirecting to /bin/systemctl stop firewalld.service

192.168.128.139

from flask import Flask

app = Flask(__name__)


@app.route('/test', methods=['POST', 'GET'])
def test():
    result = {
        "result": "from 192.168.128.139: I am backend1"
    }
    return result


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5001)

192.168.128.138 

from flask import Flask

app = Flask(__name__)


@app.route('/test', methods=['POST', 'GET'])
def test():
    result = {
        "result": "from 192.168.128.138: I am backend2"
    }
    return result


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5001)

请求示例

可以看到,我模拟请求的是 192.168.128.139 的 5000 端口,但请求最后还是可以被转发到 flask 服务的  5001 端口。

模拟请求 10 次,可以看到 192.168.128.139 和 192.168.128.138 的请求比 是 3:7,和我们配置的权重  1: 2 很接近(多次请求基本上就和配置权重一致了)。

import requests


def test_request(url):
    res = requests.get(url)
    print(res.json())


if __name__ == '__main__':
    url = "http://192.168.128.139:5000/test"
    for i in range(10):
        test_request(url)
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}

指定路由转发

上面的示例是统一将 根路径 下的所有请求进行转发。虽然我的请求使用的 /test 路径,但也会命中基础匹配,因此也会被转发。

但是,有时候我可能希望特定路由的请求被转发到特定的服务器。

如果涉及到指定多个 URL 路径(如  根路径 / 和路径 /test),则可以配置多个 location 分配不同路径到不同的后端服务器组。

events {
    worker_connections  1024;
}

http {
    upstream backend {
        server 192.168.128.139:5001 weight=1;
        server 192.168.128.138:5001 weight=2;
    }

    upstream backend_test {
        server 192.168.128.138:5001;
    }

    server {
        listen 5000;
        location / {
            proxy_pass http://backend;
        }

        location /test {
            proxy_pass http://backend_test;
        }
    }
}

这样,满足 /test 前缀的会被转发到 backend_test 服务器组,其它不满足的则命中基础匹配被转发到 backend 服务器组。

匹配规则

基础匹配

location / { ... }:这是最基本的匹配,匹配所有请求。因为它没有指定具体的文件或目录,所以通常作为后备选项出现。

精确匹配

location = /exact/path { ... }:精确匹配这个路径。如果请求的 URI 完全等于 /exact/path,则使用这个 location 块的配置处理此请求。这具有最高的优先级。

前缀匹配

location /prefix/ { ... }:前缀匹配请求的 URI 的开始部分。如果请求的 URI 以 /prefix/ 开始,这个 location 块将被用来处理请求。

location ^~ /prefix/ { ... }:前缀匹配,但它会停止正则表达式匹配,即使正则表达式可能会更具体匹配。如果该 location 匹配,Nginx 不会考虑之后的正则 location 块。

正则表达式匹配

location ~ /regex/ { ... }:大小写敏感的正则匹配。
location ~* /regex/ { ... }:大小写不敏感的正则匹配。
location / { ... } 正则表达式匹配会在普通字符串前缀匹配后进行。如果有多个正则表达式 location 都匹配请求,则使用第一个匹配的 location 块。

匹配优先级

Nginx 处理请求时 location 匹配的优先级顺序如下:

  • 首先进行精确匹配 location =
  • 其次按文件中出现顺序匹配所有正则表达式 location ~ 和 location ~*
  • 然后进行最长的前缀匹配 location ^~
  • 最后是通常的前缀匹配 location /prefix/
  • 如果前面的匹配都没有找到,就使用默认的 location /

负载均衡算法

Nginx 支持多种负载均衡算法,常见的包括:

  • 轮询(Round Robin):默认算法,按照顺序将请求依次分发到后端服务器。
  • 权重(Weighted Round Robin):为每个后端服务器设置权重,权重高的服务器分配的请求会更多。
  • IP 哈希(IP Hash):根据客户端 IP 的哈希值决定分发到哪台后端服务器,适用于需要保持会话一致性的场景。
  • 最少连接(Least Connections):将请求分配给当前连接数最少的后端服务器。
  • Hash(指定字段哈希):基于指定的请求字段(如 URL、Cookie 等)来分配请求。

轮询配置

默认的配置,按顺序把请求依次发到列表的服务器。

events {
    worker_connections  1024;
}

http {
    upstream backend {
        server 192.168.128.139:5001;
        server 192.168.128.138:5001;
    }

    server {
        listen 5000;
        location / {
            proxy_pass http://backend;
        }
    }
}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}

权重配置

为每个后端服务器设置权重,会尽可能将请求按照设定的权重比例进行转发。

upstream backend {
    server 192.168.128.139:5001 weight=1;
    server 192.168.128.138:5001 weight=2;
}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}

IP哈希配置

根据客户端 IP 的哈希值决定分发到哪台后端服务器,适用于需要保持会话一致性的场景。

简单理解,也即客户端的请求第一次被转发到的那台服务器,那么后续这个客户端的请求,都会被转发到之前的同一台服务器。

events {
    worker_connections  1024;
}

http {
    upstream backend {
        ip_hash;
        server 192.168.128.139:5001;
        server 192.168.128.138:5001;
    }

    server {
        listen 5000;
        location / {
            proxy_pass http://backend;
        }
    }
}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}

最少连接配置

将请求分配给当前连接数最少的后端服务器,也即哪台请求服务器的压力比较小,就将请求转发到哪台服务器。

events {
    worker_connections  1024;
}

http {
    upstream backend {
        least_conn;
        server 192.168.128.139:5001;
        server 192.168.128.138:5001;
    }

    server {
        listen 5000;
        location / {
            proxy_pass http://backend;
        }
    }
}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.139: I am backend1'}
{'result': 'from 192.168.128.138: I am backend2'}

健康检查配置

手动将某个服务器标记为不可用,那么负载均衡进行请求转发的时候,就会忽略掉 "不可用" 的服务器,从而不会将请求转发到这个失效的服务器上。

events {
    worker_connections  1024;
}

http {
    upstream backend {
        server 192.168.128.139:5001 down;
        server 192.168.128.138:5001;
    }

    server {
        listen 5000;
        location / {
            proxy_pass http://backend;
        }
    }
}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}

反向代理

简单理解,反向代理就是服务端的代理,上面一节的 负载均衡 也用到了反向代理。

upstream

我们把 192.168.128.139 上的 nginx.conf 配置从负载均衡稍微改一下。

events {
    worker_connections  1024;
}

http {
    upstream backend {
        server 192.168.128.138:5001;
    }

    server {
        listen 5000;
        location / {
            proxy_pass http://backend;
        }
    }
}

这样的话,请求到 192.168.128.139:5000 的请求,都被转发到了 192.168.128.138:5001 上去了。

再次用相同的请求运行,可以看到,请求都被转发到另外一个机器的另外一个端口上去了。

import requests


def test_request(url):
    res = requests.get(url)
    print(res.json())


if __name__ == '__main__':
    url = "http://192.168.128.139:5000/test"
    for i in range(10):
        test_request(url)
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}
{'result': 'from 192.168.128.138: I am backend2'}

proxy_pass

当然,如果只是想做单一的反向代理,并不考虑负载均衡的话,我们也可以不用 upstream 模块。

events {
    worker_connections  1024;
}

http {
    server {
        listen 5000;
        location / {
            proxy_pass http://192.168.128.138:5001;
        }
    }
}

上面这种,也可以达到反向代理的作用。但这种情况具有局限性,并不能做到负载均衡,只限于一个被代理服务器的情况下。


http://www.kler.cn/a/418965.html

相关文章:

  • 如何从 Hugging Face 数据集中随机采样数据并保存为新的 Arrow 文件
  • 利用Matlab进行分布函数回归分析
  • 什么是人工智能大模型?
  • 【IMF靶场渗透】
  • C语言零基础——简单的排序算法(4种)
  • 基于Java Springboot在线点餐系统
  • 二:OpenStack环境准备-controller node
  • Qt 窗口操作函数(置顶、全屏,最大化最小化按钮设置等)
  • Ubuntu 服务器部署 Tomcat 并配置 SSL/TLS 证书
  • 斐波那契数
  • k8s 1.28 聚合层部署信息记录
  • 2024年华为OD机试真题-矩阵扩散-C++-OD统一考试(E卷)
  • win32com python 操作wps 解决修改 表格触发关闭 其他excel的功能
  • 如何高效地架构一个Java项目
  • 三:安装服务-controller node
  • Oracle 去除小数点后面的零
  • CMAKE常用命令详解
  • 《Vue 组件化开发:构建可复用的模块》
  • 【笔记】成为雍正
  • CPU性能优化--性能瓶颈
  • 如何在 Debian 8 上设置 Apache 虚拟主机
  • Flask项目入门—会话技术Cookie和Session
  • SpringBoot整合WebService
  • flink学习(9)——time+water mark
  • Linux服务器使用JupyterLab
  • shell编程基础笔记