⑴ consul 怎么移除失败的服务
Docker 1.9.0开始支持多主机网络(multi-host networking)。我们可以通过OVNOpen vSwitch virtual network)来将Docker的网络和Open vSwitch结合起来。
简介
对于OVN和Docker的多主机网络(multi-host networking),Docker需要分布式键值对存储的支持。假设我们这里采用consul来提供分布式键值对存储,并且你的主机IP地址为$HOST_IP。用户可以使用下面的命令来启动Docker进程:
docker daemon --cluster-store=consul://127.0.0.1:8500 /
--cluster-advertise=$HOST_IP:0
OVN为容器提供了网络虚拟化技术。OVN和Docker的结合使用存在两种模式—underlay模式和overlay模式。
在underlay模式下,OVN要求配置OpenStack来提供容器网络。在这个模式下,用户可以创建逻辑网络,并且让运行在虚拟机中的容器、独立的虚拟机(没有容器运行在其中)和物理机器连接到同一个逻辑网络上。这是一种多租户、多主机的解决办法。
在overlay模式下,OVN可以为运行跨主机的容器们提供一个逻辑网络。这是一种单租户(是否能扩展到多租户取决于安全特性)、多主机的解决办法。在这种模式下,你并不需要预创建好的OpenStack。
值得注意的是,用户必须在他想要运行容器的虚拟机或主机上安装并运行Open vSwitch。
Overlay 模式
Overlay模式下,需要Open vSwitch 2.5版本或后续版本的支持。
启动核心模块
OVN架构中会有一个核心的模块来存储网络信息。因此你需要在你其中一台主机(IP地址为$CENTRAL_IP,并且已经安装和启动了Open vSwitch)上启动相关的核心服务。
首先我们让ovsdb-server监听一个TCP端口:
ovs-appctl -t ovsdb-server ovsdb-server/add-remote ptcp:6640
接下来,启动ovn-northd后台进程。这个进程负责将来自Docker的网络信息(存储在OVN_Northbound 数据库中)转换成逻辑流存储于OVN_Southbound数据库。
/usr/share/openvswitch/scripts/ovn-ctl start_northd
一次性配置
在每一个你打算创建容器的主机上,你需要运行以下的命令(如果你的OVS数据库被清空,你需要再次运行这个命令。除此之外,重复运行这个命令都是没有任何影响的)。
其他的主机可以通过$LOCAL_IP地址来访问到这个主机,它就相当于本地通道的端点。
$ENCAP_TYPE是指用户想使用的通道的类型。它可以是地geneve逗或者地stt逗。(注意,你的内核需要支持以上两个类型,用户可以通过运行以下命令来检测内核是否支持以上类型:逗lsmod | grep $ENCAP_TYPE")
ovs-vsctl set Open_vSwitch . external_ids:ovn-remote="tcp:$CENTRAL_IP:6640"
external_ids:ovn-encap-ip=$LOCAL_IP external_ids:ovn-encap-type="$ENCAP_TYPE"
最后,启动ovn-controller(你需要在每一次启动时运行以下命令):
/usr/share/openvswitch/scripts/ovn-ctl start_controller
启动Open vSwitch网络驱动
在默认情况下,Docker使用Linux网桥,但它支持外扩展。为了替换Linux网桥,我们需要先启动Open vSwitch驱动。
Open vSwitch驱动使用了python Flask模块来监听Docker的网络API请求。因此,用户需要先安装Python 的Flask模块。
easy_install -U pip
pip install Flask
在每一个你想要创建容器的主机上启动Open vSwitch驱动:
ovn-docker-overlay-driver --detach
Docker内部包含了一些模块,这些模块拥有类似于OVN的逻辑交换机和逻辑端口的概念。请读者仔细阅读Docker的文档来查找相关的命令。这里我们给出了一些案例:
NID=`docker network create -d openvswitch --subnet=192.168.1.0/24 foo`
docker network ls
你也可以通过以下命令从OVN的northbound数据库中查找到这个逻辑交换机:
ovn-nbctl --db=tcp:$CENTRAL_IP:6640 lswitch-list
docker run -itd --net=foo --name=busybox busybox
ovn-nbctl --db=tcp:$CENTRAL_IP:6640 lport-list $NID
docker network create -d openvswitch --subnet=192.168.2.0/24 bar
docker network connect bar busybox
用户可以删除逻辑端口,或者将它们从运行容器上分离出来:
docker network disconnect bar busybox
docker network rm bar
Underlay模式
在这个模式下,OVN要求用户预安装好OpenStack。
用户也可以删除逻辑交换机:
用户也可以创建一个逻辑端口,并将它添加到一个运行中的容器上:
显示所有的逻辑端口
Docker现在并没有一个CLI命令来罗列所有的逻辑端口,但是你可以从OVN的数据库中找到它们:
Docker创建逻辑端口,并且将这个端口附加到逻辑网络上
比如说,将一个逻辑端口添加到容器busybox的逗foo地网络上:
显示已有逻辑交换机
创建用户自己的逻辑交换机
下面的命令创建了一个名为地foo逗的逻辑交换机,它的网段为地192.168.1.0/24地:
一次性配置
一个OpenStack的租户创建了一个虚拟机,这个虚拟机拥有单张或多张网卡。如果租户想要发送虚拟机中容器的网络包,他需要获取这些网卡的port-id。port-id可以通过以下命令获得:
nova list
然后运行:
neutron port-list --device_id=$id
在虚拟机中,下载OpenStack的RC文件,这些文件包含了租户的信息(我们用openrc.sh来指代它)。编辑这个文件,并且将之前获取到的port-id以 export OS_VIF_ID=$port-id的格式加入到文件中。文件的内容如下:
!/bin/bash
export OS_AUTH_URL=
export OS_TENANT_ID=
export OS_TENANT_NAME="demo"
export OS_USERNAME="demo"
export OS_VIF_ID=e798c371-85f4-4f2d-ad65-d09dd1d3c1c9
创建Open vSwitch网桥
如果用户的虚拟机只有一个以太网接口(比如说eth0),你需要将这个设备作为一个端口加入到Open vSwitch的地breth0地网桥上,并且移除它的IP地址,将其他相关的信息转移到这个网桥上。(如果有多个网路接口,用户自己创建Open vSwitch网桥,并且添加接口到网桥上)
如果你使用DHCP来获取IP地址,你需要关闭监听eth0的DHCP客户端,并且开启一个监听Open vSwitch breth0网桥的DHCP客户端。
你可以让以上的步骤持久化,比如说你的虚拟机是Debian/Ubuntu,你可以参考 openvswitch-switch.README.Debian,如果你的虚拟机基于RHEL,你可以阅读 README.RHEL完成持久化。
开启Open vSwitch网络驱动
Open vSwitch驱动使用了Python Flask模块来监听Docker的网络API调用。这个驱动还使用了OpenStack的python-neutronclient库。因此,如果你的主机还没有安装Python Flask或者python-neutronclient,你需要使用以下命令来安装:
easy_install -U pip
pip install python-neutronclient
pip install Flask
运行openrc文件:
../openrc.sh
开启网络驱动,并且提供OpenStack租户的密码:
ovn-docker-underlay-driver --bridge breth0 --detach
从现在开始,你可以使用和overlay模式类似的Docker命令了。请阅读逗man ovn-architecture地来理解OVN的技术细节。
⑵ 怎样使用Spring Cloud跨云管理
使用Spring Cloud构建实际的微服务架构。
基本概念:
使用Docker进行集成测试
混合持久化
微服务架构
服务发现
API网关
Docker
使用Docker对每一个服务进行构建和部署。使用Docker Compose在一个开发机上进行端到端的集成测试。
混合持久化
混合持久化其实就是说使用多种数据库来存储。不同的微服务实例都会使用它们自己的数据库,并通过REST服务或者消息总线来通信,举个例子,你可以使用基于以下数据库来构建微服务:
Neo4j(图形化)
MongoDB(文档化)
MySQL(关联)
微服务架构
这个例子演示了如何使用微服务创建一个新的应用。由于在项目中的每一个微服务只有一个单一的父项目。开发者为此得到的收益是可以在本机上运行和开发每一个微服务。添加一个新的微服务非常简单,当发现微服务时将会自动发现运行时的集群环境上。
Service Discovery
项目中包含两个发现服务,一个在Netflix Eureka,另一个使用了
Consul from Hashicorp。多种发现服务提供了多种选择,一个是使用(Consul)来做DNS服务集群,另一个是(Consul)基于代理的API 网关。
API 网关
每一个微服务都关联Eureka,在整个集群中检索API路由。使用这个策略,每一个在集群上运行的微服务只需要通过一个共同的API网关进行负载均衡和暴露接口,每一个服务也会自动发现并将路由请求转发到自己的路由服务中。这个代理技术有助于开发用户界面,作为平台完整的 API通过自己的主机映射为代理服务。
Docker 实例
下面的实例将会通过Maven来构建,使用Docker为每一个微服务构建容器镜像。我们可以很优雅的使用Docker Compose在我们自己的主机上搭建全部的微服务集群。
开始构建
在这之前,请先移步至项目的GitHub 仓库。
https://github.com/kbastani/spring-cloud-microservice-example
克隆或者fork这个项目并且把源码下载到自己的电脑上。下载完毕后,你需要使用Maven和Docker来编译和构建本地的容器镜像。
下载Docker
首先,如果你还没有Docker请先下载它。可以跟随这个指南来获取Docker:https://docs.docker.com/installation/,然后在开发机上安装并运行。
当然你也需要安装Docker Compose(https//docs.docker.com/compose/),这个指南将会帮到你:https://docs.docker.com/compose/install/。
环境要求
能够运行实例程序,需要在你的开发机上安装下面的软件:
Maven 3
java 8
Docker
Docker Compose
构建项目
通过命令行方式来构建当前项目,在项目的根目录中运行如下的命令:
$ mvn clean install
项目将会根据pom.xml中的每一个项目声明中下载相应的依赖jar包。每一个服务都将会被构建,同时Maven的Docker插件将会自动从本地Docker Registry中构建每一个容器镜像。Docker将会在构建成功后,根据命令行运行mvn clean install来清除相应的资源。
⑶ 【知识总结】6.服务注册发现框架比较(Consul/Zookeeper/etcd/Eureka)
服务发现就是服务提供者将自己提供的地址post或者update到服务中介,服务消费者从服务中介那里get自己想要的服务的地址。
但是有两个问题:
第一个问题:如果有一个服务提供者宕机,那么中介的key/value中会有一个不能访问的地址,该怎么办?
心跳机制: 服务提供者需要每隔5秒左右向服务中介汇报存活,服务中介将服务地址和汇报时间记录在zset数据结构的value和score中。服务中介需要每隔10秒左右检查zset数据结构,踢掉汇报时间严重落后的地址。这样就可以保证服务列表中地址的有效性。
第二个问题是服务地址变动时如何通知消费者。有两种解决方案。
第一种是轮询,消费者每隔几秒查询服务列表是否有改变。如果服务地址很多,查询会很慢。这时候可以引入服务版本号机制,给每个服务提供一个版本号,在服务变动时,递增这个版本号。消费者只需要轮询这个版本号的变动即可知道服务列表是否发生了变化。
第二种是采用pubsub。这种方式及时性要明显好于轮询。缺点是每个pubsub都会占用消费者一个线程和一个额外的连接。为了减少对线程和连接的浪费,我们使用单个pubsub广播全局版本号的变动。所谓全局版本号就是任意服务列表发生了变动,这个版本号都会递增。接收到版本变动的消费者再去检查各自的依赖服务列表的版本号是否发生了变动。这种全局版本号也可以用于第一种轮询方案。
CAP理论
CAP理论是分布式架构中重要理论
关于P的理解,我觉得是在整个系统中某个部分,挂掉了,或者宕机了,并不影响整个系统的运作或者说使用,而可用性是,某个系统的某个节点挂了,但是并不影响系统的接受或者发出请求,CAP 不可能都取,只能取其中2个。原因是
(1)如果C是第一需求的话,那么会影响A的性能,因为要数据同步,不然请求结果会有差异,但是数据同步会消耗时间,期间可用性就会降低。
(2)如果A是第一需求,那么只要有一个服务在,就能正常接受请求,但是对与返回结果变不能保证,原因是,在分布式部署的时候,数据一致的过程不可能想切线路那么快。
(3)再如果,同事满足一致性和可用性,那么分区容错就很难保证了,也就是单点,也是分布式的基本核心,好了,明白这些理论,就可以在相应的场景选取服务注册与发现了。
平时经常用到的服务发现的产品进行下特性的对比,首先看下结论:
补充:
(1)运维和开发如果是 Java 更熟,也更多 Java 的应用,那毫无疑问应该用 ZK;如果是搞 Go 的,那么还是 etcd 吧,毕竟有时候遇到问题还是要看源码的。
(2)在创建一百万个或更多键时,etcd可以比Zookeeper或Consul稳定地提供更好的吞吐量和延迟。此外,它实现了这一目标,只有一半的内存,显示出更高的效率。但是,还有一些改进的余地,Zookeeper设法通过etcd提供更好的最小延迟,代价是不可预测的平均延迟。
(3)
一致性协议: etcd 使用 Raft 协议,Zookeeper 使用 ZAB(类PAXOS协议),前者容易理解,方便工程实现;
运维方面:etcd 方便运维,Zookeeper 难以运维;
数据存储:etcd 多版本并发控制(MVCC)数据模型 , 支持查询先前版本的键值对
项目活跃度:etcd 社区与开发活跃,Zookeeper 感觉已经快死了;
API:etcd 提供 HTTP+JSON, gRPC 接口,跨平台跨语言,Zookeeper 需要使用其客户端;
访问安全方面:etcd 支持 HTTPS 访问,Zookeeper 在这方面缺失;
与 Eureka 有所不同,Apache Zookeeper 在设计时就紧遵CP原则,即任何时候对 Zookeeper 的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性,但是 Zookeeper 不能保证每次服务请求都是可达的。
从 Zookeeper 的实际应用情况来看,在使用 Zookeeper 获取服务列表时,如果此时的 Zookeeper 集群中的 Leader 宕机了,该集群就要进行 Leader 的选举,又或者 Zookeeper 集群中半数以上服务器节点不可用(例如有三个节点,如果节点一检测到节点三挂了 ,节点二也检测到节点三挂了,那这个节点才算是真的挂了),那么将无法处理该请求。所以说,Zookeeper 不能保证服务可用性。
当然,在大多数分布式环境中,尤其是涉及到数据存储的场景,数据一致性应该是首先被保证的,这也是 Zookeeper 设计紧遵CP原则的另一个原因。
但是对于服务发现来说,情况就不太一样了,针对同一个服务,即使注册中心的不同节点保存的服务提供者信息不尽相同,也并不会造成灾难性的后果。
因为对于服务消费者来说,能消费才是最重要的,消费者虽然拿到可能不正确的服务实例信息后尝试消费一下,也要胜过因为无法获取实例信息而不去消费,导致系统异常要好(淘宝的双十一,京东的618就是紧遵AP的最好参照)。
当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30~120s,而且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。
在云部署环境下, 因为网络问题使得zk集群失去master节点是大概率事件,虽然服务能最终恢复,但是漫长的选举事件导致注册长期不可用是不能容忍的。
Spring Cloud Netflix 在设计 Eureka 时就紧遵AP原则。Eureka是在Java语言上,基于Restful Api开发的服务注册与发现组件,由Netflix开源。遗憾的是,目前Eureka仅开源到1.X版本,2.X版本已经宣布闭源。
Eureka Server 也可以运行多个实例来构建集群,解决单点问题,但不同于 ZooKeeper 的选举 leader 的过程,Eureka Server 采用的是Peer to Peer 对等通信。这是一种去中心化的架构,无 master/slave 之分,每一个 Peer 都是对等的。在这种架构风格中,节点通过彼此互相注册来提高可用性,每个节点需要添加一个或多个有效的 serviceUrl 指向其他节点。每个节点都可被视为其他节点的副本。
在集群环境中如果某台 Eureka Server 宕机,Eureka Client 的请求会自动切换到新的 Eureka Server 节点上,当宕机的服务器重新恢复后,Eureka 会再次将其纳入到服务器集群管理之中。当节点开始接受客户端请求时,所有的操作都会在节点间进行复制(replicate To Peer)操作,将请求复制到该 Eureka Server 当前所知的其它所有节点中。
当一个新的 Eureka Server 节点启动后,会首先尝试从邻近节点获取所有注册列表信息,并完成初始化。Eureka Server 通过 getEurekaServiceUrls() 方法获取所有的节点,并且会通过心跳契约的方式定期更新。
默认情况下,如果 Eureka Server 在一定时间内没有接收到某个服务实例的心跳(默认周期为30秒),Eureka Server 将会注销该实例(默认为90秒, eureka.instance.lease-expiration-ration-in-seconds 进行自定义配置)。
当 Eureka Server 节点在短时间内丢失过多的心跳时,那么这个节点就会进入自我保护模式。
Eureka的集群中,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
Eureka不再从注册表中移除因为长时间没有收到心跳而过期的服务;
Eureka仍然能够接受新服务注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用);
当网络稳定时,当前实例新注册的信息会被同步到其它节点中;
因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使得整个注册服务瘫痪。
Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。Consul 使用 Go 语言编写,因此具有天然可移植性(支持Linux、windows和Mac OS X)。
Consul采用主从模式的设计,使得集群的数量可以大规模扩展,集群间通过RPC的方式调用(HTTP和DNS)。
Consul 内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value 存储、多数据中心方案,不再需要依赖其他工具(比如 ZooKeeper 等),使用起来也较为简单。
Consul 遵循CAP原理中的CP原则,保证了强一致性和分区容错性,且使用的是Raft算法,比zookeeper使用的Paxos算法更加简单。虽然保证了强一致性,但是可用性就相应下降了,例如服务注册的时间会稍长一些,因为 Consul 的 raft 协议要求必须过半数的节点都写入成功才认为注册成功 ;在leader挂掉了之后,重新选举出leader之前会导致Consul 服务不可用。
默认依赖于SDK
Consul本质上属于应用外的注册方式,但可以通过SDK简化注册流程。而服务发现恰好相反,默认依赖于SDK,但可以通过Consul Template(下文会提到)去除SDK依赖。
Consul Template
Consul,默认服务调用者需要依赖Consul SDK来发现服务,这就无法保证对应用的零侵入性。
所幸通过 Consul Template ,可以定时从Consul集群获取最新的服务提供者列表并刷新LB配置(比如nginx的upstream),这样对于服务调用者而言,只需要配置一个统一的服务调用地址即可。
Consul强一致性(C)带来的是:
Eureka保证高可用(A)和最终一致性:
其他方面,eureka就是个servlet程序,跑在servlet容器中; Consul则是go编写而成。
etcd是一个采用http协议的分布式键值对存储系统,因其易用,简单。很多系统都采用或支持etcd作为服务发现的一部分,比如kubernetes。但正事因为其只是一个存储系统,如果想要提供完整的服务发现功能,必须搭配一些第三方的工具。
比如配合etcd、Registrator、confd组合,就能搭建一个非常简单而强大的服务发现框架。但这种搭建操作就稍微麻烦了点,尤其是相对consul来说。所以etcd大部分场景都是被用来做kv存储,比如kubernetes。
etcd 比较多的应用场景是用于服务发现,服务发现 (Service Discovery) 要解决的是分布式系统中最常见的问题之一,即在同一个分布式集群中的进程或服务如何才能找到对方并建立连接。和 Zookeeper 类似,etcd 有很多使用场景,包括:
配置管理
服务注册发现
选主
应用调度
分布式队列
分布式锁
按照官网给出的数据, 在 2CPU,1.8G 内存,SSD 磁盘这样的配置下,单节点的写性能可以达到 16K QPS, 而先写后读也能达到12K QPS。这个性能还是相当可观。
etcd 提供了 etcdctl 命令行工具 和 HTTP API 两种交互方法。etcdctl命令行工具用 go 语言编写,也是对 HTTP API 的封装,日常使用起来也更容易。所以这里我们主要使用 etcdctl 命令行工具演示。
(1)注册中心ZooKeeper、Eureka、Consul 、Nacos对比
https://zhuanlan.hu.com/p/165217227?utm_source=wechat_session
(2)常用的服务发现对比(Consul、zookeeper、etcd、eureka)
https://blog.csdn.net/gaohe7091/article/details/101197107
⑷ OpenResty 动态负载均衡
在之前提到的OpenResty/Nginx的负载均衡当中,当服务器启动之后,upstream中的上游服务器就是固定死的了,做不到动态的变更。这里面说到的变更,其实更多指的是增加机器。因为当上游服务器不可用时,upstream会自动将服务器摘除,但是当新增服务器时,upstream就做不到了。传统的负载均衡办法,就是能是修改配置,然后重启服务。下面介绍一下动态负载均衡的方式,一种是通过动态重启服务;另外一种是通过代码的方式动态拉取服务器列表。
Consul是一个分布式服务注册与发现系统。这里面使用Consul来管理上游服务器,当服务器启动时将其注册到注册中心去,当服务关闭时从注册中心列表中剔除。这里面需要注意一点的是:当上游服务器关闭时,Consul本身不会自动从列表中剔除,而是需要在服务器关闭前主动向Consul发起删除服务。
Consul有以下特性:
通过Consul可以获取到upstream中的上游服务器列表,下面要做的事情就是生成upstream中的模板了。这里就需要用到Consul-templete,它可以使用HTTP长轮询实现变更触发和配置更改。从而可以根据Consul服务器列表动态生成配置文件,然后去重新启动OpenResty/Nginx即可。
Consul+Consul-templete 就如上面所说的,是一种监听服务器列表变更,然后动态生成upstream模板,重启服务器。
Consul-Server
笔者使用的是MAC,下面所进行的操作都是基于MAC系统的。首先需要安装Consul如下:
安装完成之后,可以通过如下命令启动Consul服务:
启动完成之后,可以通过如下地址:localhost:8500/ui。访问Consul的Web界面:
可以使用HTTP的方式向Consul注册一个服务:
Consul-template
Consul-template的作用是生成upstream配置模板,安装命令如下:
然后在nginx.conf同级目录下创建moguhu_server.ctmpl
重启OpenResty脚本如下:reboot.sh
然后nginx.conf配置如下:
上游服务器
上游服务器upstream中使用的是Spring Boot实现的,其核心代码如下所示:
笔者在实验时,Consul版本的问题,造成在JVM停止时,没有执行删除服务的操作。因此附上下面的pom依赖
测试验证
1、启动Consul
2、启动Consul-template
3、启动2台upstream服务器
然后你会发现在nginx.conf的同级目录下生成了moguhu_server.conf文件,内容如下:
当手动停掉一台服务器时,配置又会变更为如下:
此时reboot.sh脚本会自动触发执行,如下所示:
上面的方式实现动态负载均衡在配置较多的时候会有一些问题,比如配置较多时,OpenResty重启的速度就会变慢。所以通过Lua脚本的方式可以规避掉重启这一步骤。
使用Lua实现时,与上面的组件相比Consul-templete就不需要了。通过Consul的 http://127.0.0.1:8500/v1/catalog/service/moguhu_server 接口就可以获取到服务的列表,如下所示:
这一方式当中主要就是OpenResty里面的相关配置。
OpenResty 配置
upstreams.lua
nginx.conf
上面通过balancer_by_lua_block去动态的设置了,upstream的服务器列表。然后启动OpenResty就可以了。
参考:《亿级流量网站架构核心技术》
⑸ consul入门篇
consul是google开源的一个使用go语言开发的服务发现、配置管理中心服务。内置了服务注册与发现框架(类似zookeeper)、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案。服务部署简单,只有一个可运行的二进制的包。每个节点都需要运行agent,他有两种运行模式server和client。每个节点为以下三种状态的一种:
上图来源于 Consul 官网,很好的解释了 Consul 的工作原理。consul是一个服务管理软件,主要功能如下:
有些人可能对服务注册和发现还没有概念,有些人可能使用过其他服务发现的工具,比如 ZooKeeper,etcd,会有一些先入为主的经验。本文谈一下 Consul 做服务发现的实践和原理。
下面这张图描述了服务发现的完整流程,先大致看一下:
首先需要有一个正常的 Consul 集群,有 Server,有 Leader。这里在服务器 Server1、Server2、Server3 上分别部署了 Consul Server。
假设他们选举了 Server2 上的 Consul Server 节点为 Leader。这些服务器上最好只部署 Consul 程序,以尽量维护 Consul Server 的稳定。
然后在服务器 Server4 和 Server5 上通过 Consul Client 分别注册 Service A、B、C,这里每个 Service 分别部署在了两个服务器上,这样可以避免 Service 的单点问题。
服务注册到 Consul 可以通过 HTTP API(8500 端口)的方式,也可以通过 Consul 配置文件的方式。
Consul Client 可以认为是无状态的,它将注册信息通过 RPC 转发到 Consul Server,服务信息保存在 Server 的各个节点中,并且通过 Raft 实现了强一致性。
最后在服务器 Server6 中 Program D 需要访问 Service B,这时候 Program D 首先访问本机 Consul Client 提供的 HTTP API,本机 Client 会将请求转发到 Consul Server。
Consul Server 查询到 Service B 当前的信息返回,最终 Program D 拿到了 Service B 的所有部署的 IP 和端口,然后就可以选择 Service B 的其中一个部署并向其发起请求了。
如果服务发现采用的是 DNS 方式,则 Program D 中直接使用 Service B 的服务发现域名,域名解析请求首先到达本机 DNS 代理,然后转发到本机 Consul Client,本机 Client 会将请求转发到 Consul Server。
Consul Server 查询到 Service B 当前的信息返回,最终 Program D 拿到了 Service B 的某个部署的 IP 和端口。
图中描述的部署架构笔者认为是最普适最简单的方案,从某些默认配置或设计上看也是官方希望使用者采用的方案,比如 8500 端口默认监听 127.0.0.1,当然有些同学不赞同,后边会提到其他方案。
consul必须启动agent才能使用,有两种启动模式server和client,还有一个官方自带的web ui。server用与持久化服务信息,集群官方建议3或5个节点。client只用与于server交互。ui可以查看集群情况的。
server模式启动如下:
参数解释:
client启动如下:
client节点可以有多个,自己根据服务指定即可。
ui启动如下:
参数解释:
集群创建完成后:
使用一些常用的命令检查集群的状态:
可以在raft:stat看到此节点的状态是Fllower或者leader
新加入一个节点有几种方式;
访问ui:
http://192.168.1.198:8500/ui
端口:
8300:consul agent服务relplaction、rpc(client-server)
8301:lan gossip
8302:wan gossip
8500:http api端口
8600:DNS服务端口
输入 consul agent -dev
在浏览器中输入 www.localhost:8500 就可以启动web查看
consul注册服务,有三种方式,
方式一:通过配置文件的方式静态注册
创建文件夹/etc/consul.d
.d代表有许多配置文件在里面
vim /etc/consul.d/jetty.json 内容如下:
重启consul,并将配置文件的路径给consul(指定参数:-config-dir /etc/consul.d)
方式二:通过HTTP API接口来动态注册
直接调用/v1/agent/service/register接口注册即可,需要注意的是:http method为PUT提交方式。如:
注意,这种方式,和上面的注册方式有一点不一样,body的参数,是上面service的值,这点需要注意
方式三:使用程序实现服务的注册和发现(Java)
首先加入consul client的依赖
服务发现
consul支持两种方式实现服务发现,一种是通过http API来查询有哪些服务,另外一种是通过consul agent 自带的DNS(8600端口),域名是以NAME.service.consul的形式给出,NAME即在定义的服务配置文件中,服务的名称。DNS方式可以通过check的方式检查服务。
服务间的通信协议
Consul使用gossip协议管理成员关系、广播消息到整个集群,他有两个gossip pool(LAN pool和WAN pool),LAN pool是同一个数据中心内部通信的,WAN pool是多个数据中心通信的,LAN pool有多个,WAN pool只有一个。
https://www.toutiao.com/a6639493728086000142/?tt_from=weixin&utm_campaign=client_share&wxshare_count=1×tamp=1546144777&app=news_article&utm_source=weixin&iid=55667270026&utm_medium=toutiao_android&group_id=6639493728086000142
⑹ consul修改默认配置后执行命令失效
创建一个 bootstrap.properties 配置文件来配置consul的配置中心相关配置。
consul的配置中心功能可使用,在bootstrap.properties 配置文件中设置, spring.cloud.consul.config.enabled=false 。
仅使用consul的服务注册与发现功能,pom文件中删除spring-cloud-consul-config依赖。仅使用consul的服务注册与发现功能
⑺ 【实践】2.Prometheus命令和配置详解
Prometheus配置方式有两种:
(1)命令行,用来配置不可变命令参数,主要是Prometheus运行参数,比如数据存储位置
(2)配置文件,用来配置Prometheus应用参数,比如数据采集,报警对接
不重启进程配置生效方式也有两种:
(1)对进程发送信号SIGHUP
(2)HTTP POST请求,需要开启--web.enable-lifecycle选项curl -X POST http://192.168.66.112:9091/-/reload
配置文件格式是yaml格式,说明:
.yml或者.yaml 都是 yaml格式的文件,
yaml格式的好处: 和json交互比较容易
python/go/java/php 有yaml格式库,方便语言之间解析,并且这种格式存储的信息量很大。
命令行可用配置可通过prometheus -h来查看。
配置文件使用yml格式,配置文件中一级配置项如下,说明参考#备注内容。
配置文件中通用字段值格式
<boolean>: 布尔类型值为true和false
<scheme>: 协议方式包含http和https
原始配置文件内容:
全局默认的数据拉取间隔
全局默认的单次数据拉取超时,当报context deadline exceeded错误时需要在特定的job下配置该字段。
全局默认的规则(主要是报警规则)拉取间隔
该服务端在与其他系统对接所携带的标签
该字段配置与Alertmanager进行对接的配置
样例:
上面的配置中的 alert_relabel_configs 是指警报重新标记在发送到Alertmanager之前应用于警报。 它具有与目标重新标记相同的配置格式和操作,外部标签标记后应用警报重新标记,主要是针对集群配置。
这个设置的用途是确保具有不同外部label的HA对Prometheus服务端发送相同的警报信息。
Alertmanager 可以通过 static_configs 参数静态配置,也可以使用其中一种支持的服务发现机制动态发现,我们上面的配置是静态的单实例。
此外, relabel_configs 允许从发现的实体中选择 Alertmanager,并对使用的API路径提供高级修改,该路径通过 __alerts_path__ 标签公开。
完成以上配置后,重启Prometheus服务,用以加载生效,也可以使用热加载功能,使其配置生效。然后通过浏览器,访问 http://192.168.1.220:19090/alerts 就可以看 inactive pending firing 三个状态,没有警报信息是因为我们还没有配置警报规则 rules 。
这里定义和prometheus集成的alertmanager插件,用于监控报警。后续会单独进行alertmanger插件的配置、配置说明、报警媒介以及route路由规则记录。
此项配置和 scrape_configs 字段中 relabel_configs 配置一样,用于对需要报警的数据进行过滤后发向 Alertmanager
说明
relabel-configs的配置允许你选择你想抓取的目标和这些目标的标签是什么。所以说如果你想要抓取这种类型的服务器而不是那种,可以使用relabel_configs
相比之下,metric_relabel_configs是发生在抓取之后,但在数据被插入存储系统之前使用。因此如果有些你想过滤的指标,或者来自抓取本身的指标(比如来自/metrics页面)你就可以使用metric_relabel_configs来处理。
该项目主要用来配置不同的 alertmanagers 服务,以及Prometheus服务和他们的链接参数。 alertmanagers 服务可以静态配置也可以使用服务发现配置。Prometheus以pushing 的方式向alertmanager传递数据。
alertmanager 服务配置和target配置一样,可用字段如下
这个主要是用来设置告警规则,基于设定什么指标进行报警(类似触发器trigger)。这里设定好规则以后,prometheus会根据全局global设定的evaluation_interval参数进行扫描加载,规则改动后会自动加载。其报警媒介和route路由由alertmanager插件实现。
样例:
"first_rules.yml"样例:
Prometheus 支持两种类型的 Rules ,可以对其进行配置,然后定期进行运算:recording rules 记录规则 与 alerting rules 警报规则,规则文件的计算频率与警报规则计算频率一致,都是通过全局配置中的 evaluation_interval 定义。
不论是recording rules还是alerting rules都要在组里面。
要在Prometheus中使用Rules规则,就必须创建一个包含必要规则语句的文件,并让Prometheus通过Prometheus配置中的rule_files字段加载该文件,前面我们已经讲过了。 其实语法都一样,除了 recording rules 中的收集的指标名称 record: <string> 字段配置方式略有不同,其他都是一样的。
配置范例:
recording rules 是提前设置好一个比较花费大量时间运算或经常运算的表达式,其结果保存成一组新的时间序列数据。当需要查询的时候直接会返回已经计算好的结果,这样会比直接查询快,同时也减轻了PromQl的计算压力,同时对可视化查询的时候也很有用,可视化展示每次只需要刷新重复查询相同的表达式即可。
在配置的时候,除却 record: <string> 需要注意,其他的基本上是一样的,一个 groups 下可以包含多条规则 rules ,Recording 和 Rules 保存在 group 内,Group 中的规则以规则的配置时间间隔顺序运算,也就是全局中的 evaluation_interval 设置。
配置范例:
上面的规则其实就是根据 record 规则中的定义,Prometheus 会在后台完成 expr 中定义的 PromQL 表达式周期性运算,以 job 为维度使用 sum 聚合运算符 计算 函数rate 对http_requests_total 指标区间 10m 内的增长率,并且将计算结果保存到新的时间序列 job:http_requests_total:rate10m 中, 同时还可以通过 labels 为样本数据添加额外的自定义标签,但是要注意的是这个 lables 一定存在当前表达式 Metrics 中。
模板是在警报中使用时间序列标签和值展示的一种方法,可以用于警报规则中的注释(annotation)与标签(lable)。模板其实使用的go语言的标准模板语法,并公开一些包含时间序列标签和值的变量。这样查询的时候,更具有可读性,也可以执行其他PromQL查询 来向警报添加额外内容,ALertmanager Web UI中会根据标签值显示器警报信息。
{{ $lable.<lablename>}} 可以获取当前警报实例中的指定标签值
{{ $value }} 变量可以获取当前PromQL表达式的计算样本值。
调整好rules以后,我们可以使用 curl -XPOST http://localhost:9090/-/reload 或者 对Prometheus服务重启,让警报规则生效。
这个时候,我们可以把阈值调整为 50 来进行故障模拟操作,这时在去访问UI的时候,当持续1分钟满足警报条件,实际警报状态已转换为 Firing,可以在 Annotations中看到模板信息 summary 与 description 已经成功显示。
规则检查
拉取数据配置,在配置字段内可以配置拉取数据的对象(Targets),job以及实例
定义job名称,是一个拉取单元。每个job_name都会自动引入默认配置如
这些也可以在单独的job中自定义
服务端拉取过来的数据也会存在标签,配置文件中也会有标签,这样就可能发生冲突。
true就是以抓取数据中的标签为准
false就会重新命名抓取数据中的标签为“exported”形式,然后添加配置文件中的标签
切换抓取数据所用的协议
定义可选的url参数
每次抓取数据请求的认证信息
password和password_file互斥只可以选择其一
bearer_token和bearer_token_file互斥只可以选择其一
抓取ssl请求时证书配置
通过代理去主去数据
Prometheus支持多种服务现工具,详细配置这里不再展开
更多参考官网: https://prometheus.io/docs/prometheus/latest/configuratio n/configuration/
服务发现来获取抓取目标为动态配置,这个配置项目为静态配置,静态配置为典型的targets配置,在改配置字段可以直接添加标签
采集器所采集的数据都会带有label,当使用服务发现时,比如consul所携带的label如下:
这些lable是数据筛选与聚合计算的基础。
抓取数据很繁杂,尤其是通过服务发现添加的target。所以过滤就显得尤为重要,我们知道抓取数据就是抓取target的一些列metrics,Prometheus过滤是通过对标签操作操现的,在字段relabel_configs和metric_relabel_configs里面配置,两者的配置都需要relabel_config字段。该字段需要配置项如下
target配置示例
target中metric示例
target中metric示例
使用示例
由以上可知当使用服务发现consul会带入标签__meta_consul_dc,现在为了表示方便需要将该标签变为dc
需要做如下配置,这里面action使用的replacement
过滤采集target
为了防止Prometheus服务过载,使用该字段限制经过relabel之后的数据采集数量,超过该数字拉取的数据就会被忽略
Prometheus可以进行远程读/写数据。字段remote_read和remote_write
(1)Prometheus 配置详解
https://www.dazhuanlan.com/2019/12/12/5df11ada207ce/
(2)Prometheus配置文件prometheus.yml 四个模块详解
http://www.21yunwei.com/archives/7321
(3)官方文档说明
https://prometheus.io/docs/prometheus/latest/configuration/configuration/
(4)Prometheus监控神器-Rules篇
https://zhuanlan.hu.com/p/179295676
(5)Prometheus监控神器-Alertmanager篇(1)
https://zhuanlan.hu.com/p/179292686
(6)Prometheus监控神器-Alertmanager篇(2)
https://zhuanlan.hu.com/p/179294441
⑻ 电脑consul环境变量怎么设置和使用
环境变量也是我们系统属性中的一项重要的变量,接下来小编就教大家怎样进行环境变量的配置和使用。
具体如下:
1.首先打开电脑进入到桌面,然后找到我的电脑图标鼠标右击,在打开的菜单中选择属性选项。
然后我们会进入到系统界面我们在这个界面中点击左侧菜单中的高级系统设置选项。
接下来就会打开属性界面,我们点击系统属性窗口上方的高级设置选项,进入到高级设置选项界面之后,就可以点击界面下方的环境变量选项。
2.然后我们就会进入到环境变量窗口,我们在这个窗口下方系统变量中找到path的变量,然后我们鼠标点击选中之后,点击窗口下方的编辑按钮。
3. 接下来我们就会进入到编辑系统变量的窗口,我们在窗口下方便靓值的输入栏的分号后面进行编辑,输入D:\consul;。完成之后我们就可以点击窗口下方的确定按钮了。需要注意的是我们修改变量值的时候一定要在分号后面才可以进行修改,不然就会导致变量的损坏。
4.编辑完成之后我们就可以点击键盘上的WINDOWS图标键加上r键,打开运行窗口之后,在输入栏中输入cmd命令,然后敲击回车运行命令。如果我们在界面中出现了一连串的英文就说明我们已经成功修改了,如果失败了我们就需要重新进行设置。
5. 如果我们成功的进行配置之后我们就可以在最下方输入以下的命令:
consul.exe agent -dev ,consul.exe agent -dev -client 192.168.xx.xx。命令输入完成之后我们就已经可以成功使用了。
以上就是电脑consul环境变量的配置和使用方法。