1.常用服务注册与发现框架

常见服务发现框架 Consul、Eureka、 ZooKeeper以及Etcd ZooKeeper是这种类型的项目中历史最悠久的之一,它起源于Hadoop。它非常成熟、可靠,被许多大公司(YouTube、eBay、雅虎等)使用。其中consul并不需要专门的sdk集成到服务中,因此它不限制任何语言的使用

2.为什么要使用consul服务发现

因为一套微服务架构中有很多个服务需要管理,也就是说会有很多对grpc。如果一一对应的进行管理会很繁琐所以我们需要有一个管理发现的机制。

服务1~4把当前自己的网络位置注册到服务发现模块,服务发现就以K-V的方式记录下,K一般是服务名,V就是IP:PORT。服务发现模块定时的轮询查看这些服务能不能访问的了(这就是健康检查)。客户端在调用服务1~4的时候,就跑去服务发现模块问下它们的网络位置,然后再调用它们的服务。客户端完全不需要记录这些服务网络位置,客户端和服务端完全解耦! 

3.服务发现的妙用

  • (1)服务器热插拔

如果新增了一个APP服务器,在“注册中心”完成注册(注册中心和服务器之间长连接,以便可以随时感知服务器的状态),注册中心就可以告知客户端有新的服务器加入,之后客户端再进发送服务请求时,就会把新加入的服务器也包含进去(但是如果要告知客户端就需要注册中心也和客户端长连接),类似,一个服务器如果宕机了,注册中心就将信息告知给客户端,之后不再给宕机的服务器发送请求。

但是,要仔细思考一个问题?客户端的数量本来就是大量存在的,随时都有可能上线和下线,让注册中心和客户端之间保持长连接是否合理?我觉得是不合理的,也是没有这个必要。

综上考虑,注册中心可以和客户端之间进行“逻辑”上的长连接,也就是当客户端在注册中心获取服务器时,把客户端的ip地址以及需要的服务器类型存放到一个表格中。而当选择一个合适的服务器分配给客户端的时候,再将该服务器工作的客户端加到一个对应的列表中。当某个服务器宕机了,就给噶服务器工作过的客户端列表中的所有客户端告知该服务器已经不工作了,下次再有请求就找别的服务器服务。

两种情况:第一、客户端每隔一段时间,向注册中心请求一次服务器(刷新);第二、客户端直接向上一次发送过请求的服务器继续发送请求,发送失败的话,就像注册中心重新申请新的服务器。

  • (2)服务器在线升级

举个例子,在打王者或吃鸡的时候,会出现服务器升级成功的提示,但是我们的游戏界面好像并没有受到什么影响,这就是典型的服务发现的一个应用——服务器在线升级,内部原理也涉及到了上面第一点说过的“服务器热插拔”。

  • (3)容错机制

“容错机制”的意思是在客户端向服务器发送请求的过程中,该服务器突然宕机,就立刻切换到另一个服务器继续请求,不会影响请求的正常发送,是所谓的“容错”。

  • (4)负载均衡

1、注册中心还起到统计的作用,记录所有服务器的状态(服务器收到的请求次数,做出的响应次数,以及响应速度等等),以便给客户端推荐最合适的服务器。

2、服务器每隔一段时间给注册中心报告自身的状况,注册中心面对得到的数据和当前所有情况甚至之前的得到情况进行比较,还是推荐给客户端最合适的服务器。

3、软负载均衡:注册中心不统计服务器的状况,不参与客户端对服务器的选择,真正的负载均衡由客户端实现,设定每一次可供选择的服务器,或者直接用随机选择的方法匹配到服务器。但是存在的问题是,多个客户端有可能同时随机到相同的服务器(也可以通过函数随机来设置它的随机优先级)。(当然这并不是绝对均衡),还可以另外开辟一个线程,每隔一段时间客户端向服务器随便发送一条消息,计算出该服务器的响应效率,这样客户端可以实时的掌握服务器的效率高低,在发送真正的请求时就向那个效率高的服务器发送。

4.Consul快速入门

consul是google开源的一个使用go语言开发的服务发现、配置管理中心服务。Consul 简化了分布式环境中的服务的注册和发现流程,通过 HTTP 或者 DNS 接口发现。支持外部 SaaS 提供者等,它支持如下特性。

  • 服务注册:服务实现者可以通过HTTP API或DNS方式,将服务注册到Consul。
  • 服务发现:服务消费者可以通过HTTP API或DNS方式,从Consul获取服务的IP和PORT。
  • 故障检测:支持如TCP、HTTP等方式的健康检查机制,从而当服务有故障时自动摘除。
  • K/V存储:使用K/V存储实现动态配置中心,其使用HTTP长轮询实现变更触发和配置更改。
  • 多数据中心:支持多数据中心,可以按照数据中心注册和发现服务,即支持只消费本地机房服务,使用多数据中心集群还可以避免单数据中心的单点故障。
  • Raft算法:Consul使用Raft算法实现集群数据一致性。

通过Consul可以管理服务注册与发现,接下来需要有一个与Nginx部署在同一台机器的Agent来实现Nginx配置更改和Nginx重启功能。我们有Confd或者Consul-template两个选择,而Consul-template是Consul官方提供的,我们就选择它了。其使用HTTP长轮询实现变更触发和配置更改(使用Consul的watch命令实现)。也就是说,我们使用Consul-template实现配置模板,然后拉取Consul配置渲染模板来生成Nginx实际配置。

5.安装并运行consul

1、下载consul服务

## 从官网下载最新版本的Consul服务
wget https://releases.hashicorp.com/consul/1.10.3/consul_1.10.3_linux_amd64.zip 
##使用unzip命令解压
unzip consul_1.10.3_linux_amd64.zip 
##将解压好的consul可执行命令移动到/usr/local/bin目录下
mv consul /usr/local/bin
##测试一下
consul --version

2、启动consul服务

consul必须启动agent才能使用,有两种启动模式server和client,还有一个官方自带的ui。server用与持久化服务信息,集群官方建议3或5个节点。client只用与于server交互。ui可以查看集群情况的。终于来到这一步了,目前我手上有 3 台嗷嗷待哺的 Centos-7.0 服务器,他们的IP地址分别是:

  • 172.16.1.218
  • 172.16.1.219
  • 172.16.1.220

分别在三台服务器输入以下对应的命令

// 172.16.1.218
consul agent -server -ui -bootstrap-expect=3 -data-dir=/data/consul -node=agent-1 -client=0.0.0.0 -bind=172.16.1.218 -datacenter=dc1

// 172.16.1.219
consul agent -server -ui -bootstrap-expect=3 -data-dir=/data/consul -node=agent-2 -client=0.0.0.0 -bind=172.16.1.219 -datacenter=dc1 -join 172.16.1.218

// 172.16.1.220
consul agent -server -ui -bootstrap-expect=3 -data-dir=/data/consul -node=agent-3 -client=0.0.0.0 -bind=172.16.1.220 -datacenter=dc1 -join 172.16.1.218

上面的命令几乎无法再精简,简单来说,就是指定了 consul(-server) 集群有3台(-bootstrap-expect=3 )服务器(-node),指定当前主机客户端侦听地址为( -client=0.0.0.0 ),因为我有多块网卡,如果不指定,无法运行127.0.0.1。绑定了当前主机的IP地址(-bind),指定了一个数据中心的名称(-datacenter=dc1),后两台服务器在启动的时候加入第一台代理服务器(-join 172.16.1.218),同时指定了启用每台服务器的内置 WebUI 服务器组件(-ui),当三台服务器都正确运行起来以后,Consul 集群将自动选举 leader,自动进行集群事务,无需干预。

 其他命令

# 查看集群成员
consul members

# 查看集群状态
consul info

# 重新加载配置文件
consul reload

# 帮助
consul agent -h

参数解释:

  • -bootstrap-expect:集群期望的节点数,只有节点数量达到这个值才会选举leader。
  • -server: 运行在server模式
  • -client:consul服务侦听地址,这个地址提供HTTP、DNS、RPC等服务,默认是127.0.0.1所以不对外提供服务,如果你要对外提供服务改成0.0.0.0
  • -data-dir:指定数据目录,其他的节点对于这个目录必须有读的权限
  • -node:指定节点的名称
  • -bind:为该节点绑定一个地址
  • -config-dir:指定配置文件,定义服务的,默认所有一.json结尾的文件都会读
  • -enable-script-checks=true:设置检查服务为可用
  • -datacenter: 数据中心名称
  • -join:加入到已有的集群中

正常启动的服务器应该输出下面的信息

3.Consul 的 WebUI 控制台

现在,我尝试通过某台服务器访问 Consul 的 WebUI 控制台,web 控制台默认端口为:8500,查看集群状态,输入地址:

http://172.16.1.218:8500

上面的IP地址可以是 3 台 Consul 服务器中的任意一台,打开网页后,转向 Nodes 菜单,可以看到,由 3 台代理服务器组成的集群已成功启动和运行,健康检查都是草原的颜色,非常的健康。

6.服务注册

Consul支持两种服务注册的方式,一种是通过Consul的服务注册HTTP API,由服务自身在启动后调用API注册自己,另外一种则是通过在配置文件中定义服务的方式进行注册。Consul文档中建议使用后面一种方式来做服务。这里写了一个hello服务,通过配置文件的方式注册到Consul,服务的相关信息:

  • name:hello,服务名称,需要能够区分不同的业务服务,可以部署多份并使用相同的name注册。
  • id:hello1,服务id,在每个节点上需要唯一,如果有重复会被覆盖。
  • address:172.16.1.218,服务所在机器的地址。
  • port:5000,服务的端口。
  • 健康检查地址:http://localhost:5000/,如果返回HTTP状态码为200就代表服务健康,每10秒Consul请求一次,请求超时时间为1秒。

请将下面的内容保存成文件services.json,并上传到容器的/etc/consul.d目录中。

{
    "service": {
        "id": "hello1",
        "name": "hello",
        "tags": ["dev"],
        "address": "172.16.1.218",
        "port": 5000,
        "checks": [
            {
                "http": "http://localhost:5000/",
                "tls_skip_verify": false,
                "method": "Get",
                "interval": "10s",
                "timeout": "1s"
            }
        ]
    }
}

启动服务

consul agent -server -ui -bootstrap-expect=3 -data-dir=/data/consul -node=agent-1 -client=0.0.0.0 -bind=172.16.1.218 -datacenter=dc1 -config-dir=/etc/consul.d/ &

7.服务发现

服务注册成功以后,调用方获取相应服务地址的过程就是服务发现。Consul提供了多种方式。

  • HTTP API方式:

curl http://172.16.1.218:8500/v1/health/service/hello?passing=false

返回的信息包括注册的Consul节点信息、服务信息及服务的健康检查信息。这里用了一个参数passing=false,会自动过滤掉不健康的服务,包括本身不健康的服务和不健康的Consul节点上的服务,从这个设计上可以看出Consul将服务的状态绑定到了节点的状态。

如果服务有多个部署,会返回服务的多条信息,调用方需要决定使用哪个部署,常见的可以随机或者轮询。为了提高服务吞吐量,以及减轻Consul的压力,还可以缓存获取到的服务节点信息,不过要做好容错的方案,因为缓存服务部署可能会变得不可用。具体是否缓存需要结合自己的访问量及容错规则来确定。

上边的参数passing默认为false,也就是说不健康的节点也会返回,结合获取节点全部服务的方法,这里可以做到获取全部服务的实时健康状态,并对不健康的服务进行报警处理。

  • DNS方式:

hello服务的域名是:hello.service.dc1.consul,后边的service代表服务,固定;dc1是数据中心的名字,可以配置;最后的consul也可以配置。

官方在介绍DNS方式时经常使用dig命令进行测试,但是alpine系统中没有dig命令,也没有相关的包可以安装,但是有人实现了,下载下来解压到bin目录就可以了

curl -L https://github.com/sequenceiq/docker-alpine-dig/releases/download/v9.10.2/dig.tgz|tar -xzv -C /usr/local/bin

然后执行dig命令:

dig @127.0.0.1 -p 8600 hello.service.dc1.consul. ANY

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐