乐趣区

关于php:构建一套适合微服务的高可用架构

随着近几年微服务与云计算的飞速发展,机器由物理机逐渐变为了虚拟机,应用服务由宏大的单体利用逐步变为了若干个微服务联结组成的利用集群,更新迭代的速度成倍上涨,传统的部署模式已无奈满足开发日常更新需要,须要一套适宜微服务的治理架构。

技术栈及文档

资源调度框架 MESOS

利用编排平台 Marathon

nginx 动静批改 upstream dyups

nginx 动静批改 upstream upsync

应用 Mesos 进行机器资源管理

首先,是机器资源的治理。在微服务的架构中,原有的单体服务被拆分成了一个个独立单元的应用程序,这些服务体量较小,能够独立运行在配置较小的机器上。为了故障隔离,咱们会尽可能的把这些服务部署在不同的虚拟机上,这样机器的数量会成倍增加。对于运维来说,每个新服务部署时,须要先查看现有机器的残余资源是否满足新服务的需要,有时可能因为评估不精确造成来回扩容、迁徙,或者资源节约。

开始时,咱们的架构可能时这样的

为了解决下面的问题,能够应用 MESOS(布式资源管理框架),它能够 让咱们像用一台电脑(一个资源池)一样应用整个数据中心。
mesos 部署时分为 master 和 agent 两个角色,当然,你能够在同一台机器启动它们。

装置 Mesos 前须要装置 zookeeper,mesos 应用 zk 实现高可用和选举,包含一个 master leader 和 几个备份 master 防止宕机。

Mesos master  负责管理各个 Framework 和 Slave,并将 Slave 上的资源非配给各个 Framework。
Mesos agent   负责管理本节点上的各个 Mesos Task,为各个 Executor 分配资源 (低版本为 mesos-slave)。

$ cat > /tmp/bintray-mesos-el.repo <<EOF

bintray-mesos-el – packages by mesos from Bintray

[bintray-mesos-el]
name=bintray-mesos-el
baseurl=https://dl.bintray.com/apache…
gpgcheck=0
repo_gpgcheck=0
enabled=1
EOF
 
$ sudo mv /tmp/bintray-mesos-el.repo /etc/yum.repos.d/bintray-mesos-el.repo
 
$ sudo yum update
 
$ sudo yum install mesos
 
$ tree /etc/mesos-master
/etc/mesos-master/
|– hostname
|– ip
|– log_dir
|– quorum   # quorum > (number of masters)/2
`– work_dir
 
$ tree /etc/mesos-agent
/etc/mesos-agent/
|– containerizers  # 容器类型,默认 mesos,能够增加 docker,如: mesos,docker
|– hostname
|– ip
|– log_dir
|– master           # master 地址,格局为 host:port 或 
zk://host1:port1,host2:port2,…/path 或 file:///path/to/file
|– resources       # 设置总资源大小,能够设置小些来预留更多机器资源
`– work_dir
 
$ cat /etc/mesos/zk  # 设置 mesos 在 zk 中的存储目录
zk://192.168.100.9:2181,192.168.100.110:2181,192.168.100.234:2181/mesos
 
$ systemctl start mesos-master
$ systemctl start mesos-slave

当 mesos 服务启动后,agent 会向 master 节点汇报机器资源,包含 CPU、内存、磁盘等。当咱们要公布一个服务时,只须要设置这个服务的 CPU、内存、磁盘参数,mesos master 会主动帮咱们抉择有足够资源的机器去运行,如下图

咱们将微服务的启动都交给 Mesos 治理,这样咱们只须要关注整体资源即可。MESOS 提 供了 UI 界面,能够间接拜访 mesos master 的 5050 端口,查看集群资源应用状况。总体应用状况 及 Agent 节点应用状况

实现以上后,咱们的架构变成了这样

应用 Marathon 进行微服务治理

Marathon 是建设在 Mesos 上的公有 PaaS 平台。它能主动解决硬件或者软件故障,并确 保每个应用程序都 ” 永远在线 ”。咱们应用 Marathon 治理微服务有以下劣势 1. 反对容器和非容器,不受限于服务启动类型,操作系统版本等。2. 丑陋而弱小的用户界面,能够在 UI 上进行快捷不便的应用程序配置 3. 反对约束条件,例如容许一个 mesos agent 节点只运行一个应用程序。4. 反对健康检查。能够配置 http、https、tcp、command 类型的监控查看。5. 残缺的 REST API,易于集成和编写脚本。这个对于前期集成来说至关重要。

 Add the repository

$ sudo rpm -Uvh http://repos.mesosphere.com/e…
 

 Install packages

$ sudo yum -y install mesos marathon
 

 marathon  and mesos zk path

$ cat /etc/default/marathon 
MARATHON_MESOS_USER=”root”
MARATHON_MASTER=”zk://192.168.100.9:2181,192.168.100.110:2181,192.168.100.234:2181/mesos”
MARATHON_ZK=”zk://192.168.200.9:1181,192.168.100.110:2181,192.168.100.234:2181/marathon”
 
systemctl start marathon

启动后,间接拜访 marathon 的 8080 端口,就能看到一个丑陋弱小的 UI 界面。

咱们以 springboot 利用为例,在 marathon 上创立一个应用程序

当咱们更新应用程序时,marathon 会新建雷同实例数量的应用程序,待 health check 通过之后替换老节点,所以不须要放心新的服务没有启动期间老的服务停掉造成线上事 故。到这里为止,咱们曾经能够在 marathon 上方便快捷的进行日常利用的创立、降级、扩 容、缩容。当服务健康检查失败或者机器宕机后,marathon 会主动在其它节点上启动挂掉的应用程序,大大晋升了高可用性。

应用 nginx upsync/dyups 模块进行平滑变更

当咱们的微服务能够随机调配在不同机器上时,便产生了一个新的令人头疼的问题。nginx 并不知道后端节点的变更, 也不可能每次都去手动批改 upstream 节点,reload nginx,这样老本就太高了。咱们的解决思路是和微服务的注册核心买通,当服务注册、登记时,都会对注册核心进行 更新,利用 nginx upsync/dyups 模块 能够动静批改 upstream 节点的能力进行同步,做 到平滑变更。如果应用的注册核心为 consul,倡议应用 upsync 模块,这样无需开发,只须要简略的 nginx 配置,就能够实现咱们想要的成果, 反对 consul kv, consul_services, consul_health, 同时 upsync 也反对 etcd。倡议应用 consul_health 接口。upsync 模块不是 nginx 内置模块,应用时须要从新编译增加此模块。

wget ‘http://nginx.org/download/ngi…’
tar -xzvf nginx-1.8.0.tar.gz
cd nginx-1.8.0/
 
 
./configure –add-module=/path/to/nginx-upsync-module
make
make install

配置文件示例

http {
    upstream test {
        upsync 127.0.0.1:8500/v1/health/service/test upsync_timeout=6m upsync_interval=500ms upsync_type=consul_health strong_dependency=off;
        upsync_dump_path /usr/local/nginx/conf/servers/servers_test.conf;
 
        include /usr/local/nginx/conf/servers/servers_test.conf;
    }
 
    upstream bar {
        server 127.0.0.1:8090 weight=1 fail_timeout=10 max_fails=3;
    }
 
    server {
        listen 8080;
 
        location = /proxy_test {
            proxy_pass http://test;
        }
 
        location = /bar {
            proxy_pass http://bar;
        }
 
        location = /upstream_show {
            upstream_show;
        }
 
    }
}

当 upsync 无奈满足咱们的需要或者注册核心不是 consul、etcd 时,咱们能够思考应用 nginx dyups 模块。dyups 仅对外提供 upstream 的增删查改接口,和注册核心比照、修 改的工作须要咱们通过脚本的形式实现。尽管这种形式麻烦一些,然而可定制化水平高,反对 http,C,lua API,基本上能够满足大部分的场景需要。

dyups 模块也须要 nginx 编译时增加

$ git clone git://github.com/yzprofile/ngx_http_dyups_module.git
 

 to compile as a static module

$ ./configure –add-module=./ngx_http_dyups_module
 

 to compile as a dynamic module

$ ./configure –add-dynamic-module=./ngx_http_dyups_module

示例配置

http {
 
    include conf/upstream.conf;
 
    server {
        listen   8080;
 
        location / {
            # The upstream here must be a nginx variable
            proxy_pass http://$dyups_host;
        }
    }
 
    server {
        listen 8088;
        location / {
            return 200 “8088”;
        }
    }
 
    server {
        listen 8089;
        location / {
            return 200 “8089”;
        }
    }
 
    server {
        listen 8081;
        location / {
            dyups_interface;
        }
    }
}

特地留神,应用 dyups 时,proxy_pass 时的 upstream 必须是 nginx 变量,否则不生 效,切记。

整体回顾

通过以上调整,咱们失去了以下优化

  1. 服务器资源主动调配,正当利用
  2. 晋升微服务的高可用性
  3. 减低 OPS 人工成本,更加便于管理和保护
退出移动版