nginx 配置反向代理、负载均衡、动静分离、集群搭建

nginx 配置反向代理、负载均衡、动静分离、集群搭建

nginx 基础知识和原理

反向代理实例一

实现效果

打开浏览器,在浏览器地址栏输入地址www.123.com,跳转到 web 项目主页(kestrel/tomcat/apache)

步骤

  1. 在 Windows 系统的 hosts 文件进行域名和IP的对应关系配置C:\Windows\System32\drivers\etc\hosts
    添加这么一行,IP 域名,这样就可以通过域名访问 nginx,这个IP地址是nginx的IP
192.168.0.199 www.123.com
  1. 在 nginx 进行请求转发的配置(反向代理配置)
    ngnix/sites-enabled 目录新建一个 nginx 的配置文件,命名随意,没有后缀名
server{
    # nginx 监听 80 端口,记得关闭默认配置文件的端口设置
    listen 80;
    # 目标IP地址或域名,可以随意
    server_name demo;

    location / {
        root html;
        index index.html index.htm;

        # 注意IP地址,这是 Web 项目部署的IP地址
        proxy_pass http://192.168.0.200:5000;
    }
}
  1. 启动 Web 项目,我使用是 Web 项目是 Visual Studio 2019 默认创建的 Web API 项目
    测试结果,Web API 默认是没有主页的,所以就这样显示了

反向代理实例二

实现效果

使用 nginx 反向代理,根据访问的路径跳转到不同端口的服务中
nginx 监听端口为 9001
访问 http://192.168.0.199:9001/test1/ 直接跳转到 192.168.0.200:8081
访问 http://192.168.0.199:9001/test2/ 直接跳转到 192.168.0.200:8082

步骤

  1. 准备两个 web 项目,一个 8081 端口,一个 8082 端口,并启动
  2. 创建文件夹和测试页面,在 web 项目中随便新建一个 html 文件,我使用的是 RESTful 项目,所以就返回一个IP地址
  3. 具体配置
server{
    listen 9001;
    server_name test;

    location /test1/ {
        proxy_pass http://192.168.0.200:8081/;
    }

    location /test2/ {
        proxy_pass http://192.168.0.200:8082/;
    }
}

4.开放端口
5. 重新加载 nginx

测试,项目代码,只是返回 appsettings.json 中 Kestrel 的 Url

[ApiController]
[Route("[controller]")]
public class IndexController : ControllerBase
{
    private readonly IConfiguration _configuration;

    public IndexController(IConfiguration configuration)
    {
        this._configuration = configuration;
    }

    [HttpGet]
    public async Task<IActionResult> Test()
    {
        var result = this._configuration["Kestrel:Endpoints:Http:Url"];
        return Ok(result);
    }
}

先是 test1 项目

然后是 test2 项目

补充

location 这一块儿挺迷的,有一种写法是这样的

location ~ /test1/ {
    proxy_pass http://192.168.0.200:8081;
}

我用正则表达式的结果是 404 ,proxy_pass 最后有没有 / 也有些区别

正则表达式:

  • =:用于不含正则表达式的uri前,要求请求字符串与uri严格匹配,如果匹配成功,就停止继续向下搜索并立即处理该请求
  • ~:用于表示uri包含正则表达式,并且区分大小写
  • ~*:用于表示uri包含正则表达式,并且不区分大小写
  • ^~:用于不含正则表达式的uri前,要求nginx服务器找到标识uri和请求字符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再使用 location 块中的正则uri和请求字符串做匹配

注意:如果 uri 包含正则表达式,则必须要有~或者~*标识

负载均衡

实现效果

浏览器地址栏输入地址 http://192.168.0.199:9001/test1/index,负载均衡效果,平均到 8081 和 8082 端口中

步骤

  1. 准备两个Web项目服务器,一个 8081,一个 8081
  2. 为这两个项目随便写一个页面
  3. 配置代码,在 http 块中
# 需要负载均衡的服务器IP
upstream test{
    server 192.168.0.200:8081;
    server 192.168.0.200:8082;
}

server{
    listen 9002;
    server_name 192.168.0.200;

    location / {
        # 对应 upstream 的名称
        proxy_pass http://test;

    }
}

测试,不停刷新浏览器,会在两个端口之间切换

补充

nginx 提供了几种分配策略

轮询(默认)

每个请求按时间顺序逐一分配到不同的后端服务器。如果后端服务器宕机,能自动剔除

weight

权重,默认是 1 ,权重越高,被分配的客户端越多。用于后端服务器性能不均的情况

upstream server_pool{
    server 192.168.0.200:8081 weight=10;
    server 192.168.0.200:8082 weight=10;
}

ip_hash

每个请求按 ip 的 hash 结果分配,这样每个访客固定一个后端服务器,可以解决 session 的问题

upstream server_pool{
    ip_hash;
    server 192.168.0.200:8081;
    server 192.168.0.200:8082;
}

fair

这是第三方的模块
按后端服务器的响应时间来分配请求,响应时间短的优先分配

upstream server_pool{
    server 192.168.0.200:8081;
    server 192.168.0.200:8082;
    fair;
}

动静分离

什么是动静分离?

nginx 动静分离简单来说就是把动态跟静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分开。
严格意义上说应该是动态请求跟静态请求分开,可以理解成使用 nginx 处理静态页面,web项目处理动态页面

动静分离从目前实现角度来讲大致分为两种

  • 纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前的主流方案
  • 动态跟静态文件混合在一起发布,通过 nginx 来分开

通过 location 指定不同的后缀名实现不同的请求转发
通过 expires 参数设置,可以使浏览器缓存过期时间,减少与服务器之间的请求和流量。访问这个缓存的URL时,会发送一个请求,比较服务器中该文件最后更新时间有无变化。无变化则不会从服务器抓取,返回状态码 304 ;如果有变化,则直接从服务器重新下载,返回状态码 200。此方法适合不经常变动的资源,如果是经常更新的文件,则不建议使用 expires 来缓存

步骤

  1. 在 linux 系统中准备静态资源,用于进行访问
  2. 具体配置
server{
    listen 8000;
    # nginx 地址
    server_name 192.168.0.199;

    location /Htmls/ {
        root /wwwroot/;
    }

    location /Images/ {
        root /wwwroot/;
        autoindex on;
    }
}

测试

http://192.168.0.199:8000/Images/a.jpg
http://192.168.0.199:8000/Htmls/a.html

a.jpg 是我随手截的图

a.html 也是随手写的

补充

autoindex on在访问目录时可以列出文件夹中所有文件

http://192.168.199:8000/Images/

集群

问题:nginx 和 web项目都可能宕机,请求就无法实现效果

解决方案:两台 nginx 服务器

主服务器 192.168.0.199
从服务器 192.168.0.200
虚拟IP   192.168.0.201

主服务器宕机,就会转换到从服务器中,从服务器也可以访问web项目

Keepalived

Keepalived 是一个路由,它有一个脚本,会检测 nginx 服务器是否宕机。如果宕机则切换到从服务器

两个 nginx 服务器绑定一个虚拟IP,Keepalived 会将这个绑定到 nginx 服务器上,达到主从切换的效果

两个 nginx 服务器都需要安装 Keepalived

步骤

  1. 需要两台 nginx 服务器
  2. 在两台 nginx 都安装 Keepalived,主从的配置就在 Keepalived 的配置中,keepalived.conf
  3. 需要虚拟IP
  4. 主从配置
  5. 把两台服务器上的 nginx 和 keepalived 启动

Keepalived 配置

修改 /etc/keepalived/keepalived.conf

# 全局配置
global_defs {
   notification_email {         # 设置 keepalived 在发生事件(比如切换)的时候,需要发送到的email地址,可以设置多个,每行一个。
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc    # 设置通知邮件发送来自于哪里,如果本地开启了sendmail的话,可以使用上面的默认值。
   smtp_server 192.168.0.200    # 指定发送邮件的smtp服务器。
   smtp_connect_timeout 30      # 设置smtp连接超时时间,单位为秒。
   router_id localhost          # 用户标识本节点的名称,通常为 localhost,与 /etc/hosts 中 127.0.0.1 对应,多个集群设置不同。
}

# 脚本配置
vrrp_script nginx_check {
    # nginx 检测脚本路径
    script "/usr/local/src/nginx_check.sh"

    interval 2 # 检测脚本执行的间隔,单位是秒

    weight 2 # 权重
}

# 虚拟IP配置
vrrp_instance VI_1{
    state MASTER # 主服务器为 MASTER,从服务器为 BACKUP
    interface enp0s3 # 网卡,用 ifconfig  查看
    virtual_router_id 51 # 设置VRID标记,主从服务器的 virtual_router_id 必须相同,多个集群不能重复(0..255)
    priority 100 # 主从服务器取不同的优先级,主服务器的值较大,从服务器的值较小
    advert_int 1 # 检测主服务器是否正常运行,单位是秒
    authentication {
        auth_type PASS # 权限校验方式,PASS 表示密码
        auth_pass 123456 # 密码
    }
    virtual_ipaddress {
        192.168.0.201 # 虚拟IP地址
    }
    track_script {
        nginx_check # 脚本名称,与上面定义的相同
    }
}

在 /usr/local/src 添加检测脚本 nginx_check.sh

#!/bin/bash
counter=$(ps -C nginx |grep -v PID |wc -l)
if [ $counter -eq 0 ];
then
    /usr/sbin/nginx # nginx 启动脚本的路径
    sleep 2
    counter=$(ps -C nginx |grep -v PID |wc -l)
    if [ $counter -eq 0 ];
    then
        echo "管理员密码" | sudo -S killall keepalived # 关闭 keepalived 进程
    fi
fi

测试

上面的检测脚本会重启nginx,所以测试用的脚本改成直接退出 keepalived

#!/bin/bash
counter=$(ps -C nginx |grep -v PID |wc -l)
if [ $counter -eq 0 ];
then
    echo "123456" | sudo -S killall keepalived
fi

先把两个服务器的 nginx 和 keepalived 都启动
主服务器,有虚拟IP

从服务器,还没有虚拟IP

使用虚拟 ip 地址 http://192.168.0.201 访问 nginx

停止主服务器的 nginx,nginx_check.sh脚本会停止主服务器的 keepalived,虚拟IP也没了

从服务器获得了虚拟IP

nginx 仍然可以访问

补充

nginc_check.sh脚本文件可能无法执行,进入脚本目录,通过ll命令查看文件,如果不是绿色就不能执行

chmod 775 文件名
chmod +x 文件名

还有一个坑,报Syntax error: "fi" unexpected (expecting "then")错误
使用cat -v 文件名查看文件,fi变成了fi^M
用vim打开文件,使用命令set ff,如果结果是fileformat=dos则说明是dos文件

解决方法
使用set ff=unix命令改变代码模式,然后wq保存就可以了,再使用ll命令检查一下文件是否可执行

如果还有问题,就查看 keepalived 日志,命令tail -f /var/log/messages

如果没有日志文件,可以参考这个:https://blog.csdn.net/feinifi/article/details/107037892

使用源码安装 keepalived 参考:https://cloud.tencent.com/developer/article/1766804

nginx 配置反向代理、负载均衡、动静分离、集群搭建 结束

posted @ 2021-09-20 16:09  .NET好耶  阅读(401)  评论(0编辑  收藏  举报