IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Nginx + UpSync + Consul 实现 Dynamic Upstream -> 正文阅读

[系统运维]Nginx + UpSync + Consul 实现 Dynamic Upstream

Nginx 是一款开源、高性能、高可靠的 Web 和反向代理服务器,性能是 Nginx 最重要的考量,其占用内存少、并发能力强。
Nginx 最常见的使用场景就是反向代理,Nginx 接收客户端的请求并通过相应的负载均衡算法将流量转发给后端的多台应用服务器。

传统做法

通常我们先会配置一个 upstream 地址池,包含后端的多台应用服务器,然后通过 proxy_pass 将流量分发给 upstream 中的成员。

http {
    
    upstream upstream_server{
        server 192.168.1.134:81;
        server 192.168.1.134:82;
    }

    server {
        listen       80;
        server_name localhost;

        location / {
            proxy_pass http://upstream_server;
        }
    }
}

假如现在由于应用服务器压力比较大,要新增一台服务器,那么需要修改 upstream 为:

upstream upstream_server{
    server 192.168.1.134:81;
    server 192.168.1.134:82;
    #新增的服务器
    server 192.168.1.134:83;
}

修改完成之后,需要通过 nginx -s reload 命令重新加载配置,才能使配置生效。虽然 Nginx 可以做到平滑地重载配置,但是每次应用服务器增加或删除时都要改动 Nginx 显得并不是那么智能。如果有大量的 Nginx 需要管理,每次都需要手动操作将会极大地增加运维的负担。

Dynamic Upstream

基于传统做法的弊端,我们引入了注册中心保存应用服务信息,Nginx 通过动态获取注册中心中的服务信息,更新 upstream 配置,无需人为干预和重启。实际生产应用中我们可以将 CMDB 和 注册中心整合,管理人员只需要在 CMDB 上维护应用服务信息即可。

Nginx 第三方模块 nginx-upsync-module 支持通过注册中心动态发现 upstream 信息。目前 nginx-upsync-module 模块支持 Consul 和 Etcd 作为 注册中心。

另外开源版本的 Nginx 默认只支持被动的健康检查,只有当客户端访问时,才会发起对后端节点的探测。假设本次请求中, Nginx 转发的后端节点正好出现了异常,Nginx 会将请求再转交给另一个 upstream 中的节点处理,所以不会影响到这次请求的正常进行,但是会影响效率,因为多了一次转发。并且自带模块无法做到预警。因此我们还使用了第三方模块 nginx_upstream_check_module 用于健康检查,该模块不仅支持主动的健康检查还提供了 WebUI 用于查看健康检查状态。

本示例 github 地址:https://github.com/cr7258/nginx-lab/tree/master/dynamic-upstream

目前还有其他产品支持动态配置,不仅仅是 upstream,还包括了其他方面的配置。例如 Nginx 的商业版本 Nginx Plus,和云原生结合得比较好的 Envoy、Kong、Traefik 等等。大家有兴趣可以自行了解。

注册中心 Consul 搭建

我们在一台虚拟机上启动 3 个 Consul 服务,组成一个伪集群。

下载安装包。

wget https://releases.hashicorp.com/consul/1.9.3/consul_1.9.3_linux_amd64.zip
unzip consul_1.9.3_linux_amd64.zip
mv consul /usr/local/bin/

创建相关目录:

mkdir /data/consul && cd $_
mkdir -pv /data/consul/node{1..3}

创建 3 个 Consul 节点使用的配置文件:

node1

vim /data/consul/node1/consul_config1.json

{
  "datacenter": "dev",
  "data_dir": "/data/consul/node1",
  "log_file": "/data/consul/node1/consul.log",
  "log_level": "INFO",
  "server": true,
  "node_name": "node1",
  "ui": true,
  "bind_addr": "192.168.1.134",
  "client_addr": "192.168.1.134",
  "advertise_addr": "192.168.1.134",
  "bootstrap_expect": 3,
  "ports":{
    "http": 8510,
    "dns": 8610,
    "server": 8310,
    "serf_lan": 8311,
    "serf_wan": 8312
    }
}

node2

vim /data/consul/node2/consul_config2.json

{
  "datacenter": "dev",
  "data_dir": "/data/consul/node2",
  "log_file": "/data/consul/node2/consul.log",
  "log_level": "INFO",
  "server": true,
  "node_name": "node2",
  "ui": true,
  "bind_addr": "192.168.1.134",
  "client_addr": "192.168.1.134",
  "advertise_addr": "192.168.1.134",
  "bootstrap_expect": 3,
  "ports":{
    "http": 8520,
    "dns": 8620,
    "server": 8320,
    "serf_lan": 8321,
    "serf_wan": 8322
    }
}

node3

vim /data/consul/node3/consul_config3.json

{
  "datacenter": "dev",
  "data_dir": "/data/consul/node3",
  "log_file": "/data/consul/node3/consul.log",
  "log_level": "INFO",
  "server": true,
  "node_name": "node3",
  "ui": true,
  "bind_addr": "192.168.1.134",
  "client_addr": "192.168.1.134",
  "advertise_addr": "192.168.1.134",
  "bootstrap_expect": 3,
  "ports":{
    "http": 8530,
    "dns": 8630,
    "server": 8330,
    "serf_lan": 8331,
    "serf_wan": 8332
    }
}

启动 Consul 集群:

nohup consul agent -config-file=/data/consul/node1/consul_config1.json > /dev/null 2>&1 &
nohup consul agent -config-file=/data/consul/node2/consul_config2.json -retry-join=192.168.1.134:8311 > /dev/null 2>&1 &
nohup consul agent -config-file=/data/consul/node3/consul_config3.json -retry-join=192.168.1.134:8311 > /dev/null 2>&1 &

启动之后,便可以通过 http://192.168.1.134:8510 访问,此处 192.168.1.134:8510 是 Leader 角色。

启动后端应用服务

后端服务是用 Nginx 启动的 Web 服务。准备 3 个后端服务,IP 和 Port 分别是:

192.168.1.134:81
192.168.1.134:82
192.168.1.134:83

配置文件内容如下,3 个服务的配置基本一样,只是改了相关的端口和路径:

user root;
events{}
http{
server {
    listen       81 default_server;
    listen       [::]:81 default_server;
    server_name  127.0.0.1;
    root         /root/myapp/nginx/html/81;
    server_tokens off;

    gzip on;
    gzip_buffers 16 8k;
    gzip_comp_level 6;
    gzip_http_version 1.1;
    gzip_min_length 256;
    gzip_proxied any;
    gzip_vary on;
    gzip_types text/xml application/xml application/atom+xml application/rss+xml application/xhtml+xml image/svg+xml text/javascript application/javascript application/x-javascript text/x-json application/json application/x-web-app-manifest+json text/css text/plain text/x-component font/opentype application/x-font-ttf application/vnd.ms-fontobject image/x-icon;
    gzip_disable "msie6";


    location / {
        expires max;  
        open_file_cache max=1000 inactive=20s; 
        open_file_cache_valid 30s; 
        open_file_cache_min_uses 2; 
        open_file_cache_errors on;
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
  }
}

html 文件如下:

[root@nginx-plus1 nginx]# cat html/81/index.html 
<html>
<head>
    <meta charset="utf-8">
    <title>server1</title>
</head>
<body style="background-color:blue;">
    <h1>Server 1 url 1<h1>
</body>
</html>

启动 3 个后端服务,在启动 Nginx 的时候指定配置文件即可:

sbin/nginx -c /root/myapp/nginx/81.conf
sbin/nginx -c /root/myapp/nginx/82.conf
sbin/nginx -c /root/myapp/nginx/83.conf

访问 3 个应用服务:

编译 Nginx

实现 Dynamic Upstream 需要添加 nginx-upsync-modulenginx_upstream_check_module 两个第三方模块,在编译 Nginx 的时候要将这两个模块添加进去。这里准备了一个 Dockerfile,使用 docker build -t 镜像名:标签名 . 就可以构建出一个编译好的 Nginx Docker 镜像。

FROM debian:stretch-slim

RUN useradd  www && \
mkdir -p /logs/nginx/  /webserver/nginx /webserver/nginx/conf/upsync && \
chown -R www:www /logs/nginx/  /webserver/nginx && \
echo 'deb http://mirrors.163.com/debian/ stretch main non-free contrib' > /etc/apt/sources.list && \
echo 'deb http://mirrors.163.com/debian/ stretch-updates main non-free contrib' >> /etc/apt/sources.list && \
echo 'deb-src http://mirrors.163.com/debian/ stretch main non-free contrib' >> /etc/apt/sources.list && \
echo 'deb-src http://mirrors.163.com/debian/ stretch-updates main non-free contrib' >> /etc/apt/sources.list && \
echo 'deb-src http://mirrors.163.com/debian/ stretch-backports main non-free contrib' >> /etc/apt/sources.list && \
echo 'deb-src http://mirrors.163.com/debian-security/ stretch/updates main non-free contrib' >> /etc/apt/sources.list && \
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
apt-get update && \
apt-get install -y wget vim net-tools unzip libjemalloc-dev && \
apt-get build-dep -y nginx

RUN \
cd /usr/local/src/ && \
wget -c http://nginx.org/download/nginx-1.14.2.tar.gz && \
wget -c https://www.openssl.org/source/old/1.0.2/openssl-1.0.2m.tar.gz && \
wget -c https://github.com/simplresty/ngx_devel_kit/archive/v0.3.1rc1.tar.gz && \
wget -c https://github.com/openresty/lua-nginx-module/archive/v0.10.11.tar.gz && \
wget -c https://github.com/xiaokai-wang/nginx_upstream_check_module/archive/master.zip -O nginx_upstream_check_module.zip && \
wget -c https://github.com/weibocom/nginx-upsync-module/archive/master.zip -O nginx-upsync-module.zip && \
tar zxf ./nginx-1.14.2.tar.gz && rm nginx-1.14.2.tar.gz && \
tar zxf ./openssl-1.0.2m.tar.gz && rm openssl-1.0.2m.tar.gz && \
tar zxf ./v0.3.1rc1.tar.gz && rm v0.3.1rc1.tar.gz && \
tar zxf ./v0.10.11.tar.gz && rm v0.10.11.tar.gz &&  \
unzip ./nginx_upstream_check_module.zip && rm nginx_upstream_check_module.zip && \
unzip ./nginx-upsync-module.zip && rm nginx-upsync-module.zip

RUN \
cd /usr/local/src/nginx-1.14.2 &&\
patch -p1 < /usr/local/src/nginx_upstream_check_module-master/check_1.12.1+.patch &&\
./configure \
--prefix=/webserver/nginx \
--user=www --group=www --with-pcre \
--with-stream \
--with-http_v2_module \
--with-http_ssl_module \
--with-ld-opt=-ljemalloc \
--with-http_realip_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--http-log-path=/logs/nginx/access.log \
--error-log-path=/logs/nginx/error.log \
--with-openssl=/usr/local/src/openssl-1.0.2m \
--add-module=/usr/local/src/ngx_devel_kit-0.3.1rc1 \
--add-module=/usr/local/src/lua-nginx-module-0.10.11 \
--add-module=/usr/local/src/nginx_upstream_check_module-master \ 
--add-module=/usr/local/src/nginx-upsync-module-master && \
make && \
make install

另外我也准备了一个已经构建好的镜像:registry.cn-shanghai.aliyuncs.com/public-namespace/nginx-dynamic-upstream:v1.0.0 ,可以直接拿来使用。

准备 Nginx 动态更新的配置文件

配置 nginx.conf 文件:

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    upstream app {
        upsync 192.168.1.134:8510/v1/kv/upstreams/app/ upsync_timeout=6m upsync_interval=500ms upsync_type=consul strong_dependency=off;
        upsync_dump_path /webserver/nginx/conf/app.conf; # 当consul故障时候,就可以把此作为备份配置文件
        include /webserver/nginx/conf/app.conf; # 准备一个兼容的nginx测试文件,如果没有第一次启动会起不来
        check interval=1000 rise=2 fall=2 timeout=3000 type=http default_down=false;
        check_http_send "HEAD / HTTP/1.0\r\n\r\n";
        check_http_expect_alive http_2xx http_3xx;
        }
    server {
        listen       80;
        server_name  localhost;
        location / {
            proxy_pass http://app;
        }
        location /upstream_list {
            upstream_show;
        }
        location /upstream_status {
            check_status;
            access_log off;
        }
    }
}

app.conf 文件里随便写上一个 IP 和 Port 信息,可以是无法访问的服务,因为 Nginx 的 upstream 中必须要有地址才能启动 Nginx。我们后面会通过在 Consul 上注册服务让 Nginx 动态更新 Upstream。

server 0.0.0.0:12345 weight=1 max_fails=2 fail_timeout=10s;

在本地的 Mac 电脑上通过 Docker 启动 Nginx 容器:

docker run -d --name nginx-dynamic-upstream \
-v /Users/chengzhiwei/lab/docker-lab/nginx/dynamic-upstream/nginx.conf:/webserver/nginx/conf/nginx.conf \
-v /Users/chengzhiwei/lab/docker-lab/nginx/dynamic-upstream/app.conf:/webserver/nginx/conf/app.conf \
-p 80:80 -p 443:443 \
registry.cn-shanghai.aliyuncs.com/public-namespace/nginx-dynamic-upstream:v1.0.0 \
/webserver/nginx/sbin/nginx  -g "daemon off;"

通过 curl 命令发送 HTTP 请求往 Consul 中注册两个新的服务。

curl -X PUT -d '{"weight":1, "max_fails":2, "fail_timeout":10, "down":0}' http://192.168.1.134:8510/v1/kv/upstreams/app/192.168.1.134:81
curl -X PUT -d '{"weight":1, "max_fails":2, "fail_timeout":10, "down":0}' http://192.168.1.134:8510/v1/kv/upstreams/app/192.168.1.134:82

通过 http://localhost/upstream_list 查看 upstream 主机:

通过 http://localhost/upstream_status 可以看到应用服务的健康检查状态:

访问 http://localhost 可以代理到后端的应用服务:

此时我们停掉 192.168.1.134:81 的服务:

#查看监听 81 端口的进程号
[root@nginx-plus1 nginx]# lsof -i:81
COMMAND   PID USER   FD   TYPE    DEVICE SIZE/OFF NODE NAME
nginx   26047 root    6u  IPv4 202389912      0t0  TCP *:81 (LISTEN)
nginx   26047 root    7u  IPv6 202389913      0t0  TCP *:81 (LISTEN)
nginx   26048 root    6u  IPv4 202389912      0t0  TCP *:81 (LISTEN)
nginx   26048 root    7u  IPv6 202389913      0t0  TCP *:81 (LISTEN)
#停止服务
[root@nginx-plus1 nginx]# kill 26047

此时查看健康检查状态,发现 81 端口的服务已经被置为 down 了。

此时再访问 http://localhost 就只能访问到端口为 82 的服务了。

参考链接

  • https://cloud.tencent.com/developer/article/1802712?from=article.detail.1628590
  • https://github.com/weibocom/nginx-upsync-module
  • https://cloud.tencent.com/developer/article/1648733?from=article.detail.1802712

欢迎关注

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-07-11 16:57:23  更:2021-07-11 16:59:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 11:27:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计