架构师系列-Nginx、OpenResty(三)- 负载均衡配置

Nginx负载均衡

负载均衡用于从“upstream”模块定义的后端服务器列表中选取一台服务器接受用户的请求,一个最基本的upstream模块是这样的,模块内的server是服务器列表:

#动态服务器组
upstream dynamicserver {
  server 172.16.44.47:9001; #tomcat 1
  server 172.16.44.47:9002; #tomcat 2
  server 172.16.44.47:9003; #tomcat 3
  server 172.16.44.47:9004; #tomcat 4
}

在upstream模块配置完成后,要让指定的访问反向代理到服务器列表

#其他页面反向代理到tomcat容器
location ~.*$ {
  index index.jsp index.html;
  proxy_pass http://dynamicserver;
}

这就是最基本的负载均衡实例,但这不足以满足实际需求;目前Nginx服务器的upstream模块支持6种方式的分配。

完整配置文件如下

upstream dynamicserver {
  server 192.168.64.1:9001; #tomcat 1
  server 192.168.64.1:9002; #tomcat 2
  server 192.168.64.1:9003; #tomcat 3
  server 192.168.64.1:9004; #tomcat 4
}
server {
        server_name www.itcast.com;
        default_type text/html;
        charset   utf-8;

        location ~ .*$ {
            index index.jsp index.html;
            proxy_pass http://dynamicserver;
       }
}

常用参数

参数描述
server反向服务地址 加端口
weight权重
fail_timeout与max_fails结合使用。
max_fails设置在fail_timeout参数设置的时间内最大失败次数,如果在这个时间内,所有针对该服务器的请求都失败了,那么认为该服务器会被认为是停机了
max_conns允许最大连接数
fail_time服务器会被认为停机的时间长度,默认为10s
backup标记该服务器为备用服务器,当主服务器停止时,请求会被发送到它这里。
down标记服务器永久停机了
slow_start当节点恢复,不立即加入

负载均衡策略 

在这里,只详细说明Nginx自带的负载均衡策略。

负载策略描述
轮询默认方式
weight权重方式
ip_hash依据ip分配方式
least_conn最少连接方式
fair(第三方)响应时间方式
url_hash(第三方)依据URL分配方式

轮询 

最基本的配置方法,上面的例子就是轮询的方式,它是upstream模块默认的负载均衡默认策略,每个请求会按时间顺序逐一分配到不同的后端服务器。

#动态服务器组
upstream dynamicserver {
  server 192.168.64.1:9001; #tomcat 1
  server 192.168.64.1:9002; #tomcat 2
  server 192.168.64.1:9003; #tomcat 3
  server 192.168.64.1:9004; #tomcat 4
}

 注意

  • 在轮询中,如果服务器down掉了,会自动剔除该服务器。
  • 缺省配置就是轮询策略。
  • 此策略适合服务器配置相当,无状态且短平快的服务使用。

 配置示例

upstream dynamicserver {
  server 192.168.64.1:9001; #tomcat 1
  server 192.168.64.1:9002; #tomcat 2
  server 192.168.64.1:9003; #tomcat 3
  server 192.168.64.1:9004; #tomcat 4
}

server {
        server_name www.test.com;
        default_type text/html;
        charset   utf-8;

        location ~ .*$ {
            index index.jsp index.html;
            proxy_pass http://dynamicserver;
       }
}

 weight

权重方式,在轮询策略的基础上指定轮询的几率

#动态服务器组
upstream dynamicserver {
  server 192.168.64.1:9001  weight=2;                   #tomcat 1
  server 192.168.64.1:9002;                             #tomcat 2
  server 192.168.64.1:9003;                         #tomcat 3
  server 192.168.64.1:9004; #tomcat 4
}

weight参数用于指定轮询几率,weight的默认值为1,;weight的数值与访问比率成正比,比如Tomcat 7.0被访问的几率为其他服务器的两倍。

注意

  • 权重越高分配到需要处理的请求越多。
  • 此策略可以与least_conn和ip_hash结合使用。
  • 此策略比较适合服务器的硬件配置差别比较大的情况。

 ip_hash

指定负载均衡器按照基于客户端IP的分配方式,这个方法确保了相同的客户端的请求一直发送到相同的服务器,以保证session会话,这样每个访客都固定访问一个后端服务器,可以解决session不能跨服务器的问题

upstream dynamicserver {
  ip_hash;  #保证每个访客固定访问一个后端服务器
  server 192.168.64.1:9001  weight=2;                   #tomcat 1
  server 192.168.64.1:9002;                             #tomcat 2
  server 192.168.64.1:9003;                         #tomcat 3
  server 192.168.64.1:9004; #tomcat 4
}

注意

  • 在nginx版本1.3.1之前,不能在ip_hash中使用权重(weight)。
  • ip_hash不能与backup同时使用
  • 此策略适合有状态服务,比如session。
  • 当有服务器需要剔除,必须手动down掉。

least_conn 

把请求转发给连接数较少的后端服务器,轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高,这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。

upstream dynamicserver {
  least_conn;  #把请求转发给连接数较少的后端服务器
  server 192.168.64.1:9001  weight=2;                   #tomcat 1
  server 192.168.64.1:9002;                             #tomcat 2
  server 192.168.64.1:9003;                         #tomcat 3
  server 192.168.64.1:9004; #tomcat 4
}
  • 此负载均衡策略适合请求处理时间长短不一造成服务器过载的情况。

 重试策略

现在对外服务的网站,很少只使用一个服务节点,而是部署多台服务器,上层通过一定机制保证容错和负载均衡。

基础失败重试 

为了方便理解,使用了以下配置进行分析(proxy_next_upstream 没有特殊配置)

upstream dynamicserver {
      server 192.168.64.1:9001 fail_timeout=60s max_fails=3; #Server A
      server 192.168.64.1:9002 fail_timeout=60s max_fails=3; #Server B
}

配置说明

max_fails=3 fail_timeout=60s代表在60秒内请求某一应用失败3次,认为该应用宕机,后等待60秒,这期间内不会再把新请求发送到宕机应用,而是直接发到正常的那一台,时间到后再有请求进来继续尝试连接宕机应用且仅尝试1次,如果还是失败,则继续等待60秒...以此循环,直到恢复

模拟异常

模拟后端异常的方式是直接将对应服务关闭,造成 connect refused 的情况,对应 error 错误。

在最初始阶段,所有服务器都正常,请求会按照轮询方式依次转发给 AB 两个 Server 处理。假设这时 A 节点服务崩溃,端口不通,则会出现这种情况:

  1. 请求 1 转到 A 异常,再重试到 B 正常处理,A fails +1
  2. 请求 2 转到 B 正常处理
  3. 请求 3 转到 A 异常,再重试到 B 正常处理,A fails +1 达到 max_fails 将被屏蔽 60s
  4. 屏蔽 A 的期间请求都只转给 B 处理,直到屏蔽到期后将 A 恢复重新加入存活列表,再按照这个逻辑执行

如果在 A 的屏蔽期还没结束时,B 节点的服务也崩溃,端口不通,则会出现:

  1. 请求 1 转到 B 异常,此时所有线上节点异常,会出现:

    • AB 节点一次性恢复,都重新加入存活列表
    • 请求转到 A 处理异常,再转到 B 处理异常
    • 触发 no live upstreams 报错,返回 502 错误
    • 所有节点再次一次性恢复,加入存活列表
  2. 请求 2 依次经过 AB 均无法正常处理, 触发 no live upstreams 报错,返回 502 错误

 错误重试

有时候我们系统出现500等异常的情况下,希望nginx能够到其他的服务器进行重试,我们可以配置那些错误码才进行重试。在nginx的配置文件中,proxy_next_upstream项定义了什么情况下进行重试,官网文档中给出的说明如下

Syntax: proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ...;
Default:    proxy_next_upstream error timeout;
Context:    http, server, location

默认情况下,当请求服务器发生错误或超时时,会尝试到下一台服务器,还有一些其他的配置项如下:

错误状态描述
error与服务器建立连接,向其传递请求或读取响应头时发生错误;
timeout在与服务器建立连接,向其传递请求或读取响应头时发生超时;
invalid_header服务器返回空的或无效的响应;
http_500服务器返回代码为500的响应;
http_502服务器返回代码为502的响应;
http_503服务器返回代码为503的响应;
http_504服务器返回代码504的响应;
http_403服务器返回代码为403的响应;
http_404服务器返回代码为404的响应;
http_429服务器返回代码为429的响应(1.11.13);
non_idempotent通常,请求与 非幂等 方法(POST,LOCK,PATCH)不传递到请求是否已被发送到上游服务器(1.9.13)的下一个服务器; 启用此选项显式允许重试此类请求;
off禁用将请求传递给下一个服务器。

配置说明 

这里面我们配置了500等错误的时候会进行重试

upstream dynamicserver {
  server 192.168.64.1:9001 fail_timeout=60s max_fails=3; #tomcat 1
  server 192.168.64.1:9002 fail_timeout=60s max_fails=3; #tomcat 2
}

server {
        server_name www.itcast.com;
        default_type text/html;
        charset   utf-8;

        location ~ .*$ {
            index index.jsp index.html;
            proxy_pass http://dynamicserver;
            #下一节点重试的错误状态
            proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
       }
}

模拟异常

在正常的情况下如果500错误会直接出现异常页面,现在我们加入了以上500重试策略,重试错误的流程和上面流程是一样的

 backup 服务器

Nginx 支持设置备用节点,当所有线上节点都异常时启用备用节点,同时备用节点也会影响到失败重试的逻辑,因此单独列出来介绍。

backup 处理逻辑

upstream 的配置中,可以通过 backup 指令来定义备用服务器,其含义如下

  1. 正常情况下,请求不会转到到 backup 服务器,包括失败重试的场景
  2. 当所有正常节点全部不可用时,backup 服务器生效,开始处理请求
  3. 一旦有正常节点恢复,就使用已经恢复的正常节点
  4. backup 服务器生效期间,不会存在所有正常节点一次性恢复的逻辑
  5. 如果全部 backup 服务器也异常,则会将所有节点一次性恢复,加入存活列表
  6. 如果全部节点(包括 backup)都异常了,则 Nginx 返回 502 错误

配置说明 

upstream dynamicserver {
  server 192.168.64.1:9001 fail_timeout=60s max_fails=3; #Service A
  server 192.168.64.1:9002 fail_timeout=60s max_fails=3; #Server B
  server 192.168.64.1:9003 backup; #backup
}

server {
        server_name www.itcast.com;
        default_type text/html;
        charset   utf-8;

        location ~ .*$ {
            index index.jsp index.html;
            proxy_pass http://dynamicserver;
            #下一节点重试的错误状态
            proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
       }
}

在最初始阶段,所有服务器都正常,请求会按照轮询方式依次转发给 AB 两个节点处理。当只有 A 异常的情况下,与上文没有 backup 服务器场景处理方式一致,这里就不重复介绍了。

假设在 A 的屏蔽期还没结束时,B 节点的服务也崩溃,端口不通,则会出现:

  1. 请求 1 转到 B 处理,异常,此时所有线上节点异常,会出现:

    • AB 节点一次性恢复,都重新加入存活列表
    • 请求转到 A 处理异常,再重试到 B 处理异常,两者 fails 都 +1
    • 因 AB 都异常,启用 backup 节点正常处理,并且 AB 节点一次性恢复,加入存活列表
  2. 请求 2 再依次经过 A、B 节点异常,转到 backup 处理,两者 fails 都达到 max_fails:

    • AB 节点都将会被屏蔽 60s,并且不会一次性恢复
    • backup 节点正式生效,接下来所有请求直接转到 backup 处理
    • 直到 AB 节点的屏蔽到期后,重新加入存活列表

假设 AB 的屏蔽期都还没结束时,C 节点的服务也崩溃,端口不通,则会出现

  1. 请求 1 转到 C 异常,此时所有节点(包括 backup)都异常,会出现:

    • ABC 三个节点一次性恢复,加入存活列表
    • 请求转到 A 处理异常,重试到 B 处理异常,最后重试到 C 处理异常
    • 触发 no live upstreams 报错,返回 502 错误
    • 所有节点再次一次性恢复,加入存活列表
  2. 请求 2 依次经过 AB 节点异常,重试到 C 异常,最终结果如上个步骤,返回 502 错误

 限制重试方式

默认配置是没有做重试机制进行限制的,也就是会尽可能去重试直至失败,Nginx 提供了以下两个参数来控制重试次数以及重试超时时间

  • proxy_next_upstream_tries:设置重试次数,默认 0 表示无限制,该参数包含所有请求 upstream server 的次数,包括第一次后之后所有重试之和;
  • proxy_next_upstream_timeout:设置重试最大超时时间,默认 0 表示不限制,该参数指的是第一次连接时间加上后续重试连接时间,不包含连接上节点之后的处理时间
upstream dynamicserver {
      server 192.168.64.1:9001 fail_timeout=60s max_fails=3; #Server A
      server 192.168.64.1:9002 fail_timeout=60s max_fails=3; #Server B
}

server {
        server_name www.itcast.com;
        default_type text/html;
        charset   utf-8;

        location ~ .*$ {
            index index.jsp index.html;
            proxy_pass http://dynamicserver;
            # 表示重试超时时间是3s
            proxy_connect_timeout 3s;
            #表示在 6 秒内允许重试 3 次,只要超过其中任意一个设置,Nginx 会结束重试并返回客户端响应
            proxy_next_upstream_timeout 6s;
            proxy_next_upstream_tries 3;
       }
}

常用案例

代理静态文件

server {
        listen       10086;
        server_name  www.test.com;
    
        location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_redirect off;
        }
        
        location /data/ {
            alias '/usr/local/data/'; 
            #这里是重点,就是代理这个文件夹 
            expires    7d;
        }
}

访问 http://localhost:10086/data/下面的资源就是访问/usr/local/data文件夹的资源

反向代理 

server {
    listen       80;
    server_name  www.itcast.com;;

    location / {
        proxy_pass http://127.0.0.1:8080;
        index  index.html index.htm .jsp;
    }
}

跨域配置

server {
        listen       80;
        server_name  www.itcast.com;

    if ( $host ~ (.*).itcast.com){
        set $domain $1;##记录二级域名值
    }
    #是否允许请求带有验证信息
    add_header Access-Control-Allow-Credentials true;
    #允许跨域访问的域名,可以是一个域的列表,也可以是通配符*
    add_header Access-Control-Allow-Origin  *;
    #允许脚本访问的返回头
    add_header Access-Control-Allow-Headers 'x-requested-with,content-type,Cache-Control,Pragma,Date,x-timestamp';
    #允许使用的请求方法,以逗号隔开
    add_header Access-Control-Allow-Methods 'POST,GET,OPTIONS,PUT,DELETE';
    #允许自定义的头部,以逗号隔开,大小写不敏感
    add_header Access-Control-Expose-Headers 'WWW-Authenticate,Server-Authorization';
    #P3P支持跨域cookie操作
    add_header P3P 'policyref="/w3c/p3p.xml", CP="NOI DSP PSAa OUR BUS IND ONL UNI COM NAV INT LOC"';
    if ($request_method = 'OPTIONS') {##OPTIONS类的请求,是跨域先验请求
            return 204;##204代表ok
     }
}

防盗链

通过Referer实现防盗链比较基础,仅可以简单实现方式资源被盗用,构造Referer的请求很容易实现

场景:由于图片链接可以跨域访问,所以图片链接往往被其他网站盗用,从而增加服务器负担;

解决方案:nginx可以通过valid_referers配置进行防盗链配置

valid_referers 指令

指定合法的来源'referer', 他决定了内置变量$invalid_referer的值,如果referer头部包含在这个合法网址里面,这个变量被设置为0,否则设置为1. 需要注意的是:这里并不区分大小写的.

  • 语法: valid_referers none | blocked | server_names | string …;
  • 配置段: server, location

配置说明

  • none : 允许没有http_refer的请求访问资源;
  • blocked : 允许不是http://开头的,不带协议的请求访问资源;
  • 192.168.0.1 : 只允许指定ip来的请求访问资源;
  • *.google.com:允许*.google.com的域名请求访问资源

 配置代码

# 需要防盗的后缀
location ~* \.(jpg|jpeg|png|gif|bmp|swf|rar|zip|doc|xls|pdf|gz|bz2|mp3|mp4|flv)$
    #设置过期时间
    expires     30d;
    # valid_referers 就是白名单的意思
    # 支持域名或ip
    # 允许ip 192.168.0.1 的请求
    # 允许域名 *.google.com 所有子域名
    valid_referers none blocked 192.168.0.1 *.google.com;
    if ($invalid_referer) {
        # return 403;
        # 盗链返回的图片,替换盗链网站所有盗链的图片
        rewrite ^/ https://site.com/403.jpg;
    }
    root  /usr/share/nginx/img;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/571675.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DevOps(八)Jenkins的Maven和Git插件

一、Maven简介 Maven是一个构建生命周期管理和理解工具,用于Java项目。它提供了标准化的构建流程,并简化了从项目编译到文档生成等各种构建方面的管理。 Maven是由Apache软件基金会开发和维护的一个流行的项目管理工具。它的设计目的是简化Java项目的构…

PE结构(二)PE头字段说明

PE头字段 DOS头 PE标记 标准PE头 可选PE头 我们今天分析一下PE头字段中所有重要成员的含义 DOS头 DOS头中我们需要去分析的是如下两个成员: 1.WORD e_magic:MZ标记,用于判断是否为可执行文件,即如果显示4D 5A,…

[2021年最新]国产时序性数据TDenige入门

一、TDenige简介 TDengine:是涛思数据面对高速增长的物联网大数据市场和技术挑战推出的创新性的大数据处理产品,它不依赖任何第三方软件,也不是优化或包装了一个开源的数据库或流式计算产品,而是在吸取众多传统关系型数据库、NoS…

图搜索的经典启发式算法A星(A*、A Star)算法详解

文章目录 1. 引言2. 广度优先搜索3. Dijkstra 算法4. 启发式优先搜索(Heuristic)4.1 贪心最佳优先搜索4.2 A*搜索 1. 引言 在许多场景中,我们常会遇到一类问题,即“找到一个位置到另一个位置的距离最短(用时最少&…

ELK 日志分析系统(二)

一、ELK Kibana 部署 1.1 安装Kibana软件包 #上传软件包 kibana-5.5.1-x86_64.rpm 到/opt目录 cd /opt rpm -ivh kibana-5.5.1-x86_64.rpm 1.2 设置 Kibana 的主配置文件 vim /etc/kibana/kibana.yml --2--取消注释,Kiabana 服务的默认监听端口为5601 server.po…

ubuntu 24.04 beta server NAT模式上网设置

在Ubuntu 24.04 Beta上设置网络通常涉及使用命令行工具。以下是设置静态IP地址和动态IP地址的步骤: 动态IP设置: 查找你的网络接口名称: ip a ens37是我NAT模型的一张网卡,此时是没有ip的。 下面介绍如何NAT模式下添加DHCP动态…

Maven多模块快速升级超好用Idea插件-MPVP

功能:多模块maven项目快速升级指定版本插件,并提供预览和相关升级模块日志能力。 可快速进行版本升级,进行部署到Maven仓库。 安装: 可在idea插件中心进行安装 / 下载资源拖动安装 MPVP(Maven) - IntelliJ IDEs Plugin | Marke…

node.js 解析post请求 方法一

前提:依旧以前面发的node.js服务器动态资源处理代码 具体见 http://t.csdnimg.cn/TSNW9为模板,在这基础上进行修改。与动态资源处理代码不同的是,这次的用户信息我们借用表单来实现。post请求解析来获取和展示用户表单填写信息 1》代码难点&…

快速新建springboot项目

一、初始化 1.打开IDEA,在Spring initializer这里按照下图项目进行配置。注意:如果jdk是1.8建议将Server URL这里替换为图中的阿里云服务器,否则容易找不到对应的java8,然后点击next 2.在这里提前配置一些需要使用的依赖&#xf…

Linux上部署Jupyter notebook

安装jupyter notebook pip install notebook #或者 conda install notebook配置 jupyter notebook --generate-config## The IP address the notebook server will listen on. # Default: localhost # 设置可以访问的ip, 默认是localhost, 将其改为 * c.NotebookApp.ip *#…

CMakeLists.txt中如何添加编译选项?

1. 引子 编译器有多种可供选择,如g、c、clang等,如下以c作为示例。 2. 使用CMAKE_CXX_FLAGS添加编译选项 在Makefile中可能用类似如下的指令来添加编译选项: /usr/bin/c -Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unuse…

LLM大语言模型(十三):ChatGLM3-6B兼容Langchain的Function Call的一步一步的详细转换过程记录

# LangChain:原始prompt System: Respond to the human as helpfully and accurately as possible. You have access to the following tools: Calculator: Useful for when you need to calculate math problems, args: {\calculation\: {\description\: \calcul…

云安全防御篇:如何识别并做好服务器DDoS防护?

伴随着全球互联网业务和云计算的快速发展,作为一种破坏力巨大的攻击方式,DDoS攻击正以超出服务器承受能力的流量淹没网站,导致服务器宕机、企业营业额下跌,甚至企业品牌形象受损。越是面对复杂的攻击,就需要性能更强的…

linux安装nacos(单机简易版本)

1. 查看Java版本,必须有jdk支持 2. 下载安装包,解压 下载地址: https://github.com/alibaba/Nacos/releases 2.1 上传到 /opt文件夹 2.2使用解压命令 tar -zxvf nacos-server-2.2.1.tar.gz 2.3 解压后产生文件夹 3. 配置 3.1 修改配置&…

牛客NC98 判断t1树中是否有与t2树完全相同的子树【simple 深度优先dfs C++/Java/Go/PHP】

题目 题目链接: https://www.nowcoder.com/practice/4eaccec5ee8f4fe8a4309463b807a542 思路 深度优先搜索暴力匹配 思路和算法这是一种最朴素的方法——深度优先搜索枚举 s 中的每一个节点,判断这个点的子树是否和 t 相等。如何判断一个节点的子树是否…

zabbix6.4告警配置(短信告警和邮件告警),脚本触发

目录 一、前提二、告警配置1.邮件告警脚本配置2.短信告警脚本配置3.zabbix添加报警媒介4.zabbix创建动作4.给用户添加报警媒介 一、前提 已经搭建好zabbix-server 在需要监控的mysql服务器上安装zabbix-agent2 上述安装步骤参考我的上篇文章:通过docker容器安装za…

WEP、WPA、WPA2 和 WPA3:区别和说明

无线网络安全是保持在线安全的一个重要因素。通过不安全的链路或网络连接到互联网是一种安全风险,可能会导致数据丢失、帐户凭据泄露,以及他人在您的网络上安装恶意软件。必须使用适当的 Wi-Fi 安全措施 - 但在这样做时,也必须了解不同的无线…

[Linux初阶]常见的指令

我们学Linux指令,其实就是和学windows一样,学习Linux的操作 一、Linux下基本指令 ls 指令 语法 : ls [ 选项 ] [ 目录或文件 ] 功能 :对于目录,该命令列出该目录下的所有子目录与文件。对于文件,将列出…

就业班 第三阶段(负载均衡) 2401--4.19 day3

二、企业 keepalived 高可用项目实战 1、Keepalived VRRP 介绍 keepalived是什么keepalived是集群管理中保证集群高可用的一个服务软件,用来防止单点故障。 ​ keepalived工作原理keepalived是以VRRP协议为实现基础的,VRRP全称Virtual Router Redundan…

装饰模式【结构型模式C++】

1.概述 装饰模式是一种结构型设计模式, 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。 2.结构 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。具体构件(Concrete…
最新文章