Golang 语言微服务的服务发现组件 Consul 的系统架构介绍

Posted Golang语言开发栈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Golang 语言微服务的服务发现组件 Consul 的系统架构介绍相关的知识,希望对你有一定的参考价值。

大家好,我是 frank。
欢迎大家点击标题下方蓝色文字「Golang 语言开发栈」关注公众号。
设为星标,第一时间接收推送文章。
文末扫码,加群一起学 Golang 语言。

01 

介绍

在上篇文章「Golang 语言微服务的服务注册与发现组件 Consul」中,我们已经介绍服务注册与发现是什么,Golang 语言微服务架构为什么需要使用服务注册与发现组件,Golang 语言开发的服务注册与发现组件 Consul 的主要特性和基本介绍。

本文我们介绍 Consul 的系统架构,读者朋友们阅读完本文可以了解 Consul 的工作原理。

02 

Consul 术语

在介绍 Consul 系统架构之前,我准备先介绍几个 Consul 术语,目的是让读者朋友们更容易理解 Consul 系统架构的介绍内容。

  • Datacenter 数据中心
  • Cluster 集群
  • Server 服务器
  • Client 客户端
  • Agent 代理
  • Consul 原生支持多数据中心,数据中心中包含 Consul 集群,集群由客户端、服务器或客户端和服务器混合体的节点组成。

    多个部署和运行 Agent 的节点组成 Consul Cluster,集群中包含 Client、Server 或 Client 和 Server 的混合体。

    如果节点运行的 Agent 开启 Server 模式,那么该节点为 Server。

    如果节点运行的 Agent 未开启 Server 模式,那么该节点为 Client。

    Agent 是 Consul 集群中所有节点都运行的一个守护进程,负责维护成员身份信息、注册服务、运行健康检查、响应查询等。

    03 

    Consul 系统架构

    Consul 官方为我们提供了一张 Consul 系统架构图,在这张图中,我们可以看到包含两个数据中心,分别标记为 DATACENTER 1 和 DATACENTER 2。由此可见,Consul 原生支持多数据中心。

    在每个数据中心中都包含一个 Consul 集群,DATACENTER 1 中的集群由 6 个部署并运行 Agent 的节点组成,其中三个是以 Server 模式运行的,另外三个是以 Client 模式运行的。

    而 DATACENTER 2 中的集群由 3 个部署并运行 Agent 的节点组成,并且这三个节点都是以 Server 模式运行的。

    由此可以得出一个结论,DATACENTER 中的集群可以是包含 Client 和 Server 的混合体,也可以是仅包含 Server 节点。

    需要注意的是,每个 Consul 数据中心中的集群,官方建议 Server 模式运行的节点控制在 3 至 5 个,因为 3 至 5 个 Server 节点发生故障时,就可以提供一致性和可用性,并且 Server 节点是以 Raft 协议选举 Leader,Server 节点越多,Leader 选举越慢。而 Client 节点的数量没有限制,它是轻量级进程,我们甚至可以创建成千上万个 Client 节点。

    Server 负责基于 Raft 协议选举 Leader,维护集群状态,响应 RPC 查询,与其他 DATACENTER 交换 WAN Gossip,将查询请求转发给 Leader 或远程 DATACENTER。

    Client 是无状态的,负责将所有查询请求转发给 Server,而且 Client 不需要与其他 DATACENTER 交换 WAN Gossip,只需参与 LAN Gossip,资源开销很小,只消耗少量网络带宽。

    04 

    总结

    本文我们介绍 Consul 的系统架构,我们先从宏观上了解 Consul 的工作原理,也就是先抓住纲,然后再详细学习 Consul 的各个组件。

    推荐阅读:

    Golang 语言怎么打印结构体指针类型字段的值?

    Golang 语言怎么避免空指针引发的 panic

    Golang 语言 for 和 for-range 的区别

    Golang 语言怎么避免引发 panic?

    Golang 语言编写的消息队列 NSQ 官方客户端 go-nsq 怎么使用?

    参考资料:
    https://www.consul.io/docs/architecture 

    扫描二维码或回复「微信群」,加入微信群


    点「赞」和「在看」是最大的支持

    Eureka服务发现注册详解

    目录

    一、服务发现简介

    二、Eureka简介

    三、Eureka一些特性及配置过程时需要注意的问题

    四、EurekaServer和EurekaClient的作用分析 

    五、Eureka开发实战


    一、服务发现简介

            1.服务提供者、服务消费者、服务发现组件三者之间的关系大致如下:

    • 各个微服务在启动时时,将自己的网络地址等信息注册到服务发现组件上(eureka,zookeeper,Consul,spring cloud alibaba的nacos),服务发现组件会存储这些信息。
    • 服务消费者会从服务发现组件查询服务提供者的网络地址,然后将服务地址列表缓存到本地,然后根据服务名负载均衡调用服务提供者的接口。
    • 各个微服务与服务发现组件使用一定的机制来维持心跳,服务发现组件若发现有服务没有提供心跳,那么服务发现组件会将该服务剔除。
    • 微服务网络地址发生变更(例如实例增减或者IP端口发生变化等),会重新注册到服务发现组件上,使用这种方式,可以避免因网络变化导致服务之间的通讯停止,服务消费者也无须人工的修改网络地址。

    二、Eureka简介

            Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。

            1.Eureka包含两个组件:Eureka Server和Eureka Client。

    Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。

    Eureka Client是一个java客户端,用于简化与Eureka Server的交互,客户端同时也就是一个内置的、使用轮询负载算法的负载均衡器。

            2.在应用启动后,Eureka Client会向Eureka Server发送心跳,默认周期为30秒,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。

            3.Eureka Server之间通过复制的方式完成数据的同步,Eureka还提供了客户端缓存机制,即使所有的Eureka Server都挂掉,客户端依然可以利用缓存中的信息消费其他服务的API。综上,Eureka通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。

    三、Eureka一些特性及配置过程时需要注意的问题

            1.Eureka能够保证AP,即当Eureka中的某个节点挂掉后,剩余的节点继续仍然可以提供服务的发现与注册服务。而Eureka的客户端在向某个Eureka或者发现了当前的Eureka不可用时,会自动切换到其他的节点,也就是说Eureka的节点是平等的,只要有一台Eureka服务器在,就能保证服务的可以继续被使用。

            2.Eureka的自我保护机制,我们在注册服务时,如发生断网的情况,Eureka不能接收到当前服务的任何心跳请求,Eureka会在默认的90s后,将该服务进行强制剔除,这样就能保证到网络故障时,虽然失去了部分节点,但不会像zookeeper那样会使整个注册服务瘫痪。当网络稳定时,新的实例会同步到其他节点中。

            3.相关配置问题

    服务端的配置如下,不注册自身:

    security:
      basic:
        enabled: true
      user:
        name: user
        password: password123
    eureka:
      client:
        register-with-eureka: false
        fetch-registry: false
        service-url:
          defaultZone: http://user:password123@localhost:8761/eureka

    如果我们需要使用ip地址来配置的话,先添加一行:

       eureka.instance.prefer.IpAddress=true;

    如果我们想要关闭保护机制,则设置以下代码:
    eureka.server.enable-self-preservation=false
    设置eureka剔除服务的时间间隔:
    eureka.server.eviction-interval-timer-in-ms=3000

    需要注意的是要在应用类的头上添加@EnableEurekaServer来启用Eureka服务器。

    接下来:访问Eureka,Url为:http://localhost:8761/

    可以发现eureka注册中心就启动了!!!

    在这里解释一下register-with-eureka=fasle和fetch-registry的用法,如果不指定该属性,服务端会将自身作为一个服务注册到注册中心去,因此我们需要在服务端启动前,指定这两个属性值为false。

    假如我们把以下代码给注释掉,指定一个应用名,重新启动eureka-server端:

    security:
      basic:
        enabled: true
      user:
        name: user
        password: password123
    
    server:
      port: 8888
    
    eureka:
      instance:
        hostname: 192.168.43.246
        prefer-ip-address: true
        instance-id: $eureka.instance.hostname:$server.port
      client:
    #    register-with-eureka: false
    #    fetch-registry: false
        service-url:
          defaultZone: http://user:password123@$eureka.instance.hostname:$server.port/eureka
    spring:
      application:
        name: eureka-server
    

    发现eureka-server也注册到eureka上去了!

    注:

        如果使用ip地址来注册时,一定要添加以下两行代码:

        第一种方式: ,使用参数占位符来引用已经配置好的信息:

           eureka.instance.prefer-ip-adderss=true

            eureka.instance.instance-id=$eureka.instance.hostname:$server.port

         第二种方式: 使用springcloud来自动获取ip地址: 

         eureka.instance.hostname=$spring.cloud.client.ip-address
         eureka.instance.instance-id=$eureka.instance.hostname:$server.port

    eureka客户端的配置添加上这两行代码,可以发现,添加以上两行代码的服务是以ip地址形式来注册的,没有添加的则以默认的方式来进行注册,即使用的主机名的方式来注册:

    附上使用ip地址注册服务的完整配置:

    eureka服务端:

    security:
      basic:
        enabled: true
      user:
        name: user
        password: password123
    
    server:
      port: 8888
    eureka:
      instance:
        hostname: 192.168.43.246
    #    使用ip地址的方式进行注册
    #    prefer-ip-address: true
    #    instance-id: $eureka.instance.hostname:$server.port
      client:
    #    不注册自身
    #    register-with-eureka: false
    #    fetch-registry: false
        service-url:
          defaultZone: http://user:password123@$eureka.instance.hostname:$server.port/eureka
    spring:
      application:
        name: eureka-server
    

    eureka客户端:

    security:
      basic:
        enabled: true
      user:
        name: user
        password: password123
    
    server:
      port: 9999
    spring:
      application:
        name: eurekaClient
    eureka:
      instance:
        hostname: 192.168.43.246
        prefer-ip-address: true
        instance-id: $eureka.instance.hostname:$server.port
      client:
       service-url:
          defaultZone: http://user:password123@$eureka.instance.hostname:8888/eureka
    

    此处的server-url的端口号要为服务端的端口号。注: 是 deafaultZone, 不是default-zone

     附:使用指定的ip去注册

    客户端配置如下,如果你在pom文件中添加了如下依赖,客户端可以不用在启动类上面添加@EnableEurekaClient注解。只需要在applicantion.properties文件中添加配置即可:

     eureka客户端和eureka服务端:

     <!-- eureka-server-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka-server</artifactId>
                <version>1.2.3.RELEASE</version>
            </dependency>
    
            <!--eureka-client-->
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
                <version>1.2.3.RELEASE</version>
            </dependency>

    四、EurekaServer和EurekaClient的作用分析 

            1.  EurekaServer提供服务发现的能力,当有服务来注册时,EurekaServer会将这些服务的信息存储到起来。

            2.  EurekaClient是一个java客户端,可以与服务发现组件来交互。

            3.  续约。微服务启动后,会默认底向EurekaServer发送心跳,默认时间为30s,这样的作用就是续约自己的租约。

            4.  剔除。如果Eureka在一定时间内没有收到客户端的心跳,那么EurekaServer会剔除掉没有发生心跳客户端,默认时间为90s。  

            5. 缓存。EurekaClient会缓存服务器的信息,这种方式的好处是当EurekaServer宕机时,,服务消费者依然可以访问服务。

            6. eureka 服务器默认是将自身注册到服务器里。可以使用如下代码不讲自身注册进去:

    eureka:
      client:
    #    不注册自身
    #    register-with-eureka: false

            7. 如果设置多个eureka时,需要设置 eureka.client.fetchRegistry=true,表示多个服务器之间的数据同步。单个节点直接设置成false即可。

    五、Eureka开发实战

            1. 在Spring Cloud Edgware以及更高的版本中,只需要添加相关依赖,即可自动注册服务到EurekaServer中,在实际的项目中,我们可以直接实现服务消费者连接服务提供者,这样我们可以不用将服务注册到eureka上,以便于调试。

            2.  如果不想将服务注册到EurekaServer上,只需要设置spring.cloud.service-registry.auto-registration.enabled=false,或使用注解@EnableDiscoveryClient(auto-Registry=false)。

            微服务之间的调用采用feign来进行远程调用,我们可以不通过eureka直接调用服务提供方, 为了便于调试,可以这样做: 

    1)  在resources目录下新建application-local.yml文件中添加调用各服务的url, 该参数为Feign接口上配置的url。

    @FeignClient(
     
            name = "$hcf.application.accounting.name:fec-accounting",
     
            url = "$hcf.application.payment.url:",
     
            contextId = "AccountingClient"
     
    )

      如果是远程服务的提供者,那么配置网关+地址。

      如果是本地的服务提供者,就是本地的ip地址+端口号。

    2) 启动需要指定profiles文件为local

    以上是关于Golang 语言微服务的服务发现组件 Consul 的系统架构介绍的主要内容,如果未能解决你的问题,请参考以下文章

    一个故事,一段代码告诉你如何使用不同语言(Golang&C#)提供相同的能力基于Consul做服务注册与发现

    微服务注册中心分布式集群设计原理与 Golang 实现

    微服务框架 Go-Micro 集成 Nacos 实战之服务注册与发现

    springcloud-Consul服务注册与发现

    Golang之微服务为什么发现不了

    服务注册发现之服务注册中心设计原理与Golang实现