前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >实现动态服务负载均衡(docker+consul+consul_template+nginx)

实现动态服务负载均衡(docker+consul+consul_template+nginx)

作者头像
友儿
发布2022-09-13 16:18:49
3070
发布2022-09-13 16:18:49
举报
文章被收录于专栏:友儿

环境说明

主要技术以及版本

  • vagrant
代码语言:txt
复制
- vagrant是一个对虚拟环境管理的工具。virtualbox
代码语言:txt
复制
- VirtualBox 是一款开源虚拟机软件。docker
代码语言:txt
复制
- version 20.10.7
- docker是一个开源的应用容器引擎。
- 安装[docker](https://www.runoob.com/docker/ubuntu-docker-install.html)
- 具体安装细节以及权限问题解决请参考[Ubuntu安装docker](https://niuzheng.net/archives/1146/)consul
代码语言:txt
复制
- version 1.11.3
- consul是一个用来实现分布式系统的服务发现与配置的开源工具。
- [官网下载地址](https://www.consul.io/downloads)consul-template
代码语言:txt
复制
- version 0.19.0
- consul-template基于consul的自动替换配置文件的应用。
- [consul-template 下载地址](https://releases.hashicorp.com/consul-template)nginx
代码语言:txt
复制
- version 1.21.6
- 地球人都知道的嘛!!!额外说明
代码语言:txt
复制
- `virtualbox`和`vagrant`版本不兼容会出现很多未知问题(坑),官方网站也没有介绍哪个版本对应兼容,我这里分享一个兼容性不错的版本下载连接放下面,供大家参考。
- [virtualbox5.2.8](https://www.virtualbox.org/wiki/Download_Old_Builds_5_2)
- [vagrant2.1.1](https://www.vagrantup.com/downloads)

简要说明

  • 传统负载均衡架构图
代码语言:txt
复制
- 假如目前服务需要扩容,增加了一台Web Server5,你需要手动修改Nginx配置并且重启Nginx。
- 假如目前Web Server1、Web Server4服务大半夜突然挂了,你岂不是需要爬起来修改Nginx配置,这种情况重复来几次,这可不是什么好的体验,会让人崩溃的呢!!!我们要实现什么呢?下面我们附上图来说明!!
代码语言:txt
复制
- 因需要或者意外情况而造成增加/减少机器及或者某个服务而动态实现nginx配置自动更新并实现更新重载。
- web server 通过 registrator 注册到consul服务里,然后consul-template订阅consul实现nginx配置更新重载,达到动态扩容(增加/减少),保证服务稳定可靠运行的目的。

实现

  • 假设你已经安装好虚拟机(以ubuntu为例)和docker应用容器引擎。
  • 这里可以先完整安装一台机器的软件和应用,然后使用vagrant打包剩下的两个机器。
机器说明
  • 服务器1: IP: 192.168.56.2
  • 服务器2: IP: 192.168.56.3
  • 服务器3: IP: 192.168.56.4
consul集群角色分配(我这里电脑配置有限,搞太多虚拟机测试主机windows机器容易卡死,所以我的consul集群和webserver以及nginx转发服务器都用这三个机器实现啦)
  • 服务器1: IP: 192.168.56.2 leader
  • 服务器2: IP: 192.168.56.3 service
  • 服务器3: IP: 192.168.56.4 client nginx转发服务器
应用程序角色分配
  • 服务器1: IP: 192.168.56.2 直播服务API1
  • 服务器2: IP: 192.168.56.3 直播服务API2
  • 服务器3: IP: 192.168.56.4 直播服务API3
部署consul集群

consul常用命令

  • server : 定义agent运行在server模式
  • bootstrap-expect :在一个datacenter中期望提供的server节点数目,当该值提供的时候,consul一直等到达到指定sever数目的时候才会引导整个集群,该标记不能和bootstrap共用
  • bind:该地址用来在集群内部的通讯,集群内的所有节点到地址都必须是可达的,默认是0.0.0.0
  • node:节点在集群中的名称,在一个集群中必须是唯一的,默认是该节点的主机名
  • ui-dir: 提供存放web ui资源的路径,该目录必须是可读的
  • rejoin:使consul忽略先前的离开,在再次启动后仍旧尝试加入集群中。
  • config-dir:配置文件目录,里面所有以.json结尾的文件都会被加载
  • client:consul服务侦听地址,这个地址提供HTTP、DNS、RPC等服务,默认是127.0.0.1所以不对外提供服务,如果你要对外提供服务改成0.0.0.0
代码语言:javascript
复制
# 拉取镜像
docker pull consul 
# 192.168.56.2 (leader server)
docker run --net=host --name consul1 -d  consul  agent -server -bootstrap-expect 1 -ui -node=s0 -bind=192.168.56.2 -client=0.0.0.0
# 192.168.56.3 (server)
docker run --net=host --name consul3 -d  consul  agent -server  -ui -node=s3 -bind=192.168.56.3 -client=0.0.0.0 -join=192.168.56.2
# 192.168.56.4 (client)
docker run --net=host --name consul4 -d  consul  agent  -ui -node=s4 -bind=192.168.56.4 -client=0.0.0.0 -join 192.168.56.2
# 查看consul cluster中consul节点的信息
docker exec -it consul1 consul members
#查看consul集群已经启动以及选举的leader
docker exec -it consul1 consul operator raft list-peers

浏览器访问UI界面 http://192.168.56.2:8500/

编写直播API服务

我这里直接使用swoole简单模拟搭建一个直播的HTTP服务,前提是你的php安装了swoole扩展(server.php)

代码语言:javascript
复制
<?php

#192.168.56.3
$http = new Swoole\Http\Server('0.0.0.0', 8080);

$http->on('Request', function ($request, $response) {
  $response->header('Content-Type', 'text/html; charset=utf-8');
  $response->end('<h1>直播服务API2 #IP:192.168.56.3</h1>');
});

$http->start();
代码语言:javascript
复制
<?php

#192.168.56.3
$http = new Swoole\Http\Server('0.0.0.0', 8080);

$http->on('Request', function ($request, $response) {
  $response->header('Content-Type', 'text/html; charset=utf-8');
  $response->end('<h1>直播服务API2 #IP:192.168.56.3</h1>');
});

$http->start();
代码语言:javascript
复制
<?php

#192.168.56.4
$http = new Swoole\Http\Server('0.0.0.0', 8080);

$http->on('Request', function ($request, $response) {
  $response->header('Content-Type', 'text/html; charset=utf-8');
  $response->end('<h1>直播服务API3 #IP:192.168.56.4</h1>');
});

$http->start();

注册直播服务API到consul集群

consul api 文档

代码语言:javascript
复制
//composer require php-curl-class/php-curl-class
require __DIR__ . '/vendor/autoload.php';
use Curl\Curl;

function _curl($u = '',$method = 'get', $data = null)
{
  $curl = new Curl();
  $baseUrl = 'http://192.168.56.4:8500/v1';
  $url = $baseUrl. $u;
  if (in_array(strtolower($method), ['put','post']) && !empty($data)) {
      return $curl->$method($url,$data);
  } else {
      return $curl->$method($url);
  }
}
$res = 'init';
//注册开始
$servers = [
 ['ip' => '192.168.56.2','port' => 8080,'id' => 'zhibo-1','Name' => 'zhibo_service'],
 ['ip' => '192.168.56.3','port' => 8080,'id' => 'zhibo-2','Name' => 'zhibo_service'],
 ['ip' => '192.168.56.4','port' => 8080,'id' => 'zhibo-3','Name' => 'zhibo_service']
];
foreach ($servers as $serve)
{
  //注意同一个服务Name必须一样ID可以不同
  $data = array(
      'ID' => $serve['id'],
      'Name' => $serve['Name'],
      'Tags' => ["primary", "v2"],
      'Address' => $serve['ip'],
      'Port' => $serve['port'],
      'EnableTagOverride' => false,
      'check' => array(
          'DeregisterCriticalServiceAfter' => '90m',
          'HTTP' => "http://{$serve['ip']}:{$serve['port']}",
          'Interval' => '10s',
          "Timeout" => "5s"
      )
  );
  
  $data = json_encode($data,JSON_UNESCAPED_SLASHES);
  $res = _curl('/agent/service/register','put',$data);
  //$res = _curl('/agent/service/register?replace-existing-checks=true','put',$data);
  echo "<pre>";
  print_r($res);
}
##其他API大概描述
//注销直播-3服务
//$res = _curl('/agent/service/deregister/zhibo-3','put');

//启用维护模式(enable=true/false)
//$res = _curl('/agent/service/maintenance/zhibo-3?enable=false&reason=维护原因','put');

//检查是否健康 status 为passing的为通过
//$res = _curl('/health/checks/zhibo_service');

//列出服务
//$res = _curl('/agent/services');

//获取服务配置
//$res = _curl('/agent/service/zhibo-3');

//获取本地服务运行状况
//json
//$res = _curl('/agent/health/service/name/zhibo_service');
//text
//$res = _curl('/agent/health/service/name/zhibo_service?format=text');

//通过 ID 获取本地服务运行状况
//$res = _curl('/agent/health/service/id/zhibo-3');
//$res = _curl('/agent/health/service/id/zhibo-3?format=text');
echo '<pre>';
print_r($res);
die;

搭建nginx转发服务,安装consul-template并关联订阅服务consul集群更新nginx转发配置,重启nginx。
  • 目录结构

consul-template文档地址

模板文件

代码语言:javascript
复制
{{range services}} {{$name := .Name}} {{$service := service .Name}}
  upstream {{$name}} {
    zone upstream-{{$name}} 64k;
    {{range $service}}
         server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;
    {{else}}
         server 127.0.0.1:65535; # force a 502
    {{end}}
  }
{{end}}

server {
  listen 80 zhibo_service.com;

  location / {
      root /usr/share/nginx/html/;
      index index.html;
  }

  location /stub_status {
      stub_status;
  }

 {{range services}} {{$name := .Name}}
     location /{{$name}} {
       proxy_pass http://{{$name}};
     }
 {{end}}
}

Dockerfile 文件

代码语言:javascript
复制
#指定基础镜像
FROM nginx:latest
#指定维护人
#MAINTAINER zhengniu
LABEL authors="zhengniu <771036148@qq.com>"
#https://releases.hashicorp.com/consul-template
ARG CONSUL_TMEPLATE_VERSION="0.19.0"
RUN rm -rf /etc/nginx/sites-available/
ENV CONSUL_URL 127.0.0.1:8500
#ADD https://releases.hashicorp.com/consul-template/${CONSUL_TMEPLATE_VERSION}/consul-template_${CONSUL_TMEPLATE_VERSION}_linux_amd64.zip /usr/local/bin/
ADD  consul-template_0.19.0_linux_amd64.tgz /usr/local/bin/
VOLUME /templates
ADD service.ctmpl /templates/
EXPOSE 80
RUN mkdir -p /etc/service/nginx && rm -rf /etc/service/nginx/*
ADD start.sh /etc/service/nginx/run
CMD ["/etc/service/nginx/run"]

start.sh

代码语言:javascript
复制
#!/bin/bash
service nginx start &
consul-template -consul-addr=$CONSUL_URL -template="/templates/service.ctmpl:/etc/nginx/conf.d/service.conf:service nginx reload"

构建镜像以及启动镜像
代码语言:javascript
复制
 docker build -t nginx:consuleTemplate .
 docker run --net=host -d --name nginx nginx:consuleTemplate

验证

查看是否生成配置文件

代码语言:javascript
复制
#查看
docker exec -it nginx sh  -c "cat /etc/nginx/conf.d/service.conf"

#结果
upstream consul {
zone upstream-consul 64k;
server 192.168.56.2:8300 max_fails=3 fail_timeout=60 weight=1;
server 192.168.56.3:8300 max_fails=3 fail_timeout=60 weight=1;

}
upstream zhibo_service {
zone upstream-zhibo_service 64k;
server 127.0.0.1:65535; # force a 502
}

server {
listen 80 zhibo_service.com;

location / {
  root /usr/share/nginx/html/;
  index index.html;
}

location /stub_status {
  stub_status;
}


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

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

}

分别启动直播-1、直播-2、直播-3服务

代码语言:javascript
复制
#192.168.56.2
php server.php

#192.168.56.3
php server.php

#192.168.56.4
php server.php
#查看
docker exec -it nginx sh  -c "cat /etc/nginx/conf.d/service.conf"


#查看结果动态增加了
upstream consul {
zone upstream-consul 64k;
server 192.168.56.2:8300 max_fails=3 fail_timeout=60 weight=1;
server 192.168.56.3:8300 max_fails=3 fail_timeout=60 weight=1;

}
upstream zhibo_service {
zone upstream-zhibo_service 64k;
server 192.168.56.2:8080 max_fails=3 fail_timeout=60 weight=1;
server 192.168.56.3:8080 max_fails=3 fail_timeout=60 weight=1;
server 192.168.56.4:8080 max_fails=3 fail_timeout=60 weight=1;

}

server {
listen 80 zhibo_service.com;

location / {
  root /usr/share/nginx/html/;
  index index.html;
}

location /stub_status {
  stub_status;
}


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

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

}
# 浏览器访问 http://zhibo.com/zhibo_service  
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 环境说明
  • 主要技术以及版本
  • 简要说明
  • 实现
    • 机器说明
      • consul集群角色分配(我这里电脑配置有限,搞太多虚拟机测试主机windows机器容易卡死,所以我的consul集群和webserver以及nginx转发服务器都用这三个机器实现啦)
        • 应用程序角色分配
          • 部署consul集群
            • 编写直播API服务
              • 注册直播服务API到consul集群
                • 搭建nginx转发服务,安装consul-template并关联订阅服务consul集群更新nginx转发配置,重启nginx。
                  • 构建镜像以及启动镜像
                    • 验证
                    相关产品与服务
                    云直播
                    云直播(Cloud Streaming Services,CSS)为您提供极速、稳定、专业的云端直播处理服务,根据业务的不同直播场景需求,云直播提供了标准直播、快直播、云导播台三种服务,分别针对大规模实时观看、超低延时直播、便捷云端导播的场景,配合腾讯云视立方·直播 SDK,为您提供一站式的音视频直播解决方案。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档