欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于Docker的微服务架构的企业级服务集群实践(一)——服务发现

程序员文章站 2022-06-03 11:33:26
...

前言

基于Docker的容器技术是在15年的时候开始接触的。两年多的时间,作为一名Docker的DevOps,也见证了Docker的技术体系的快速发展。本文主要是结合在公司搭建的微服务架构的实践过程,做一个简单的总结。希望给在创业初期探索如何布局服务架构体系的DevOps,或者想初步了解企业级架构的同学们一些参考。(PS:本来想一口气写完,但发现一个模块就写了太久,后续会持续更新。

Microservice和Docker

对于创业公司的技术布局,很多声音基本上是,创业公司就是要快速上线快速试错。用单应用或者前后台应用分离的方式快速集成,快速开发,快速发布。但其实这种结果造成的隐性成本会更高。当业务发展起来,开发人员多了之后,就会面临庞大系统的部署效率,开发协同效率问题。然后通过服务的拆分,数据的读写分离、分库分表等方式重新架构,而且这种方式如果要做的彻底,需要花费大量人力物力。
个人建议,DevOps结合自己对于业务目前以及长期的发展判断,能够在项目初期使用微服务架构,多为后人谋福。
随着Docker周围开源社区的发展,让微服务架构的概念能有更好的一个落地实施的方案。并且在每一个微服务应用内部,都可以使用DDD(Domain-Drive Design)的六边形架构来进行服务内的设计。关于DDD的一些概念也可以参考po主之前的几篇文章:领域驱动设计整理——概念&架构, 领域驱动设计整理——实体和值对象设计, 领域服务、领域事件
清晰的微服务的领域划分,服务内部有架构层次的优雅的实现,服务间通过RPC或者事件驱动完成必要的IPC,使用API gateway进行所有微服务的请求转发,非阻塞的请求结果合并。本文下面会具体介绍,如何在分布式环境下,也可以快速搭建起来具有以上几点特征的,微服务架构with Docker。

服务发现模式

如果使用Docker技术来架构微服务体系。那么区别于单系统的架构,服务发现就是一个必然的课题。目前主流的服务发现模式有两种: 客户端发现模式,以及服务端发现模式。

客户端发现模式

客户端发现模式的架构图如下:
基于Docker的微服务架构的企业级服务集群实践(一)——服务发现
客户端发现模式的典型实现是Netflix体系技术。客户端从一个服务注册服务中查询所有可用服务实例的库。客户端使用负载均衡算法从多个可用的服务实例中选择出一个,然后发出请求。比较典型的一个开源实现就是Netflix的Eureka。

Netflix-Eureka

Eureka的客户端是采用自注册的模式,客户端需要负责处理服务实例的注册和注销,发送心跳。
在SpringBoot项目作为一个微服务时,结合SpringCloud项目可以很方便得实现自动注册。在服务启动类上添加@EnableEurekaClient即可在启动时实现向配置好的Eureka服务端注册服务,并且定时发送心跳。客户端的负载均衡由Netflix Ribbon实现。服务网关使用Netflix Zuul,熔断器使用Netflix Hystrix
除了服务发现的配套框架,SpringCloud的Netflix-Feign,提供了声明式的接口来处理服务的Rest请求。当然,除了使用FeignClinet,也可以使用Spring RestTemplate。项目中如果使用@FeignClinet可以使代码的可阅读性更好,Rest Api也一目了然。
Eureka是为服务实例注册管理和查询可用实例提供了REST API接口。因为服务注册、注销是通过客户端自身发出请求的。所以这种模式的一个主要问题是对于不同的编程语言会注册不同服务,需要为每种开发语言单独开发服务发现逻辑。另外,使用Eureka时需要显式配置健康检查支持。

服务端发现模式

服务端发现模式的架构图如下:
基于Docker的微服务架构的企业级服务集群实践(一)——服务发现

客户端向负载均衡器发出请求,负载均衡器向服务注册表发出请求,将请求转发到注册表中可用的服务实例。服务实例也是在注册表中注册,注销的。负载均衡可以使用可以使用Haproxy或者Nginx。服务端发现模式目前基于Docker的主流方案主要是Consul、Etcd,zk。

Consul

Consul提供了一个API允许客户端注册和发现服务。其一致性上基于RAFT算法。通过WAN的Gossip协议,管理成员和广播消息,以完成跨数据中心的同步,且支持ACL访问控制。Consul还提供了健康检查机制,支持kv存储服务(Eureka不支持)。Consul的的一些更详细的介绍可以参考po主之前写的一篇:Docker 容器部署 Consul 集群

Etcd

Etcd都是强一致的(满足CAP的CP),高可用的。Etcd基于RAFT算法实现强一致性的KV数据同步。Kubernetes使用Etcd的KV结构存储所有对象的生命周期。
最近看了一篇文章,可以帮助理解Etcd的一些内部原理:etcd v3原理分析

Zookeeper

ZK最早应用于Hadoop,其体系已经非常成熟,常被用于大公司。如果已经有自己的zk集群,那么可以考虑用zk来做自己的服务注册中心。
Zookeeper同Etcd一样,强一致性,高可用性。一致性算法是基于Paxos的。对于微服务架构的初始阶段,没有必要用比较繁重的zk来做服务发现。

服务注册

服务注册表是服务发现中的一个重要组件。除了Kubernetes、Marathon其服务发现是内置的模块之外。服务都是需要注册到注册表上。上文介绍的Eureka,consul,etcd以及zk都是服务注册表的例子。
微服务如何注册到注册表也是有两种比较典型的注册方式:自注册模式,第三方注册模式。

自注册模式 Self-registration pattern

上文中的Netflix-Eureka客户端就是一个典型的自注册模式的例子。也即每个微服务的实例本身,需要负责注册以及注销服务。Eureka还提供了心跳机制,来保证注册信息的准确,具体的心跳的发送间隔时间可以在微服务中配置。
如下,就是使用Eureka做注册表时,在微服务(Springboot应用)启动时会有一条服务注册的信息:

com.netflix.discovery.DiscoveryClient    : DiscoveryClient_SERVICE-USER/{your_ip}:service-user:{port}:cc9f93c54a0820c7a845422f9ecc73fb: registering service...

一样的,在应用停用时,服务实例需要主动注销本实例信息:

2018-01-04 20:41:37.290  INFO 49244 --- [       Thread-8] c.n.e.EurekaDiscoveryClientConfiguration : Unregistering application service-user with eureka with status DOWN
2018-01-04 20:41:37.340  INFO 49244 --- [       Thread-8] com.netflix.discovery.DiscoveryClient    : Shutting down DiscoveryClient ...
2018-01-04 20:41:37.381  INFO 49244 --- [       Thread-8] com.netflix.discovery.DiscoveryClient    : Unregistering ...
2018-01-04 20:41:37.559  INFO 49244 --- [       Thread-8] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_SERVICE-USER/{your_ip}:service-user:{port}:cc9f93c54a0820c7a845422f9ecc73fb - deregister  status: 200

自注册方式是比较简单的服务注册方式,不需要额外的设施或代理,由微服务实例本身来管理服务注册。但是缺点也很明显,比如Eureka目前只提供了Java客户端,所以不方便多语言的微服务扩展。因为需要微服务自己去管理服务注册逻辑,所以也耦合了服务注册和心跳机制。跨语言性比较差。

第三方注册模式 Third party registration pattern

第三方注册,也即服务注册的管理(注册、注销服务)通过一个专门的服务管理器(Registar)来负责。 Registrator就是一个开源的服务管理器的实现。Registrator提供了对于Etcd一级Consul的注册表服务支持。Registrator需要部署运行在微服务所在的服务器或者虚拟机中。比较简单的安装方式就是通过Docker,以容器的方式来运行。如下图所示:

基于Docker的微服务架构的企业级服务集群实践(一)——服务发现

通过添加一个服务管理器,微服务实例不再直接向注册中心注册,注销。由服务管理器通过订阅服务,跟踪心跳,来发现可用的服务实例,并向注册中心(consul,etcd等)注册,注销实例,以及发送心跳。这样就可以达到服务发现组件和微服务架构的解耦。
Registrator配合Consul,以及Consul Template搭建服务发现中心,可以参考: Scalable Architecture DR CoN: Docker, Registrator, Consul, Consul Template and Nginx 。此文示例了Nginx来做负载均衡,在具体的实施过程中也可以用Haproxy或其他方案进行替代。

小结

除了以上几种做服务发现的技术,Kubernetes自带了服务发现模块,负责处理服务实例的注册和注销。Kubernetes也在每个集群节点上运行代理,来实现服务端发现路由器的功能。如果编排技术使用的k8n,可以用k8n的一整套Docker微服务方案,对k8n感兴趣的可以阅读下Kubernetes架构设计与核心原理
在实际的技术选型中,最主要还是要结合业务、系统的未来发展的特征进行合理判断。

  • 在CAP理论中。Eureka满足了AP,Consul是CA,ZK和Etcd是CP。 在分布式场景下Eureka和Consul都能保证可用性,搭建Eureka服务会相对更快速,不需要搭建额外的服务注册中心,在小规模时可以节省一定成本Consul则提供了KV存储,支持支持http和dns接口。
  • Eureka,Consul都提供了可以查看服务注册数据的WebUI组件。对于创业公司最开始搭建微服务,比较推荐这两者。
  • 如果考虑多数据中心,Consul自带数据中心的WAN方案,ZK和Etcd均不提供多数据中心功能的支持,需要额外的开发。
  • 跨语言性上,Zookeeper需要使用客户端api,跨语言支持较弱。Etcd,Eureka都支持http,Etcd还支持grpc。Consul 除了http之外还提供了DNS的支持。
  • 安全方面,Consul,Zookeeper支持ACL,另外 Consul,Etcd 支持安全通道https。
  • SpringCloud目前对于Eureka,Consul,Etcd,ZK都有相应的支持。
  • Consul 和Docker一样,都是用Go语言实现,基于Go语言的微服务应用可以优先考虑用Consul。

服务发现解决了之后,微服务间可以怎样进行进程间通信,以及各个通信协议、技术的选型,可以继续读下一篇:微服务间的IPC机制