`

基于Zookeeper的服务注册与发现

阅读更多

      

基于Zookeeper的服务注册与发现

背景

大多数系统都是从一个单一系统开始起步的,随着公司业务的快速发展,这个单一系统变得越来越庞大,带来几个问题:

  1. 随着访问量的不断攀升,纯粹通过提升机器的性能来已经不能解决问题,系统无法进行有效的水平扩展

  2. 维护这个单一系统,变得越来越复杂

  3. 同时,随着业务场景的不同以及大研发的招兵买马带来了不同技术背景的工程师,在原有达达Python技术栈的基础上,引入了Java技术栈。

如何来解决这些问题?业务服务化是个有效的手段来解决大规模系统的性能瓶颈和复杂性。通过系统拆分将原有的单一庞大系统拆分成小系统,它带来了如下好处:

  1. 原来系统的压力得到很好的分流,有效地解决了原先系统的瓶颈,同时带来了更好的扩展性

  2. 独立的代码库,更少的业务逻辑,系统的维护性得到极大的增强

同时,也带来了一系列问题:

▪ 随着系统服务的越来越多,如何来管理这些服务?

▪ 如何分发请求到提供同一服务的多台主机上(负载均衡如何来做)

▪ 如果提供服务的Endpoint发生变化,如何将这些信息通知服务的调用方?

最初的解决方案

Linkedin的创始人里德霍夫曼曾经说过:

成立一家初创公司就像把自己从悬崖上扔下来,在降落过程中去组装一架飞机。

这对于初创公司达达也是一样的,业务在以火箭般的速度发展着。技术在业务发展中作用就是保障业务的稳定运行,快速地“组装一架飞机”。所以,在业务服务化的早期,我们采用了Nginx+本地hosts文件的方式进行内部服务的注册与发现,架构图如下:

各系统组件角色如下:

  1. 服务消费者通过本地hosts中的服务提供者域名与Nginx的IP绑定信息来调用服务

  2. Nginx用来对服务提供者提供的服务进行存活检查和负载均衡

  3. 服务提供者提供服务给服务消费者访问,并通过Nginx来进行请求分发

这在内部系统比较少,访问量比较小的情况下,解决了服务的注册,发现与负载均衡等问题。但是,随着内部服务越来愈多,访问量越来越大的情况下,该架构的隐患逐渐暴露出来:

▪ 最明显的问题是Nginx存在单点故障(SPOF),同时随着访问量的提升,会成为一个性能瓶颈

▪ 随着内部服务的越来越多,不同的服务消费方需要配置不同的hosts,很容易在增加新的主机时忘记配置hosts导致服务不能调用问题,增加了运维负担

▪ 服务的配置信息分散在各个主机hosts中,难以保持一致性,不便于服务的管理

▪ 服务主机的发布和下线需要手工的修改Nginx upstream配置,修改的配置需要上线,不利于服务的快速部署

如何来解决

在谈如何来解决之前,现梳理一下服务注册与发现的目标:

▪ 服务的注册信息应该统一保存,方便于服务的管理

▪ 自动通过服务的名称去发现服务,而不必了解这个服务提供的end-point到底是哪台主机

▪ 支持服务的负载均衡及fail-over

▪ 增加或移除某个服务的end-point时,对于服务的消费者来说是透明的

▪ 支持Python和Java

备选方案一: DNS

DNS作为服务注册发现的一种方案,它比较简单。只要在DNS服务上,配置一个DNS名称与IP对应关系即可。定位一个服务只需要连接到DNS服务器上,随机返回一个IP地址即可。由于存在DNS缓存,所以DNS服务器本身不会成为一个瓶颈。

这种基于Pull的方式不能及时获取服务的状态的更新(例如:服务的IP更新等)。如果服务的提供者出现故障,由于DNS缓存的存在,服务的调用方会仍然将请求转发给出现故障的服务提供方;反之亦然。

备选方案二:Dubbo

Dubbo是阿里巴巴推出的分布式服务框架,致力于解决服务的注册与发现,编排,治理。它的优点如下:

  1. 功能全面,易于扩展

  2. 支持各种串行化协议(JSON,Hession,java串行化等)

  3. 支持各种RPC协议(HTTP,Java RMI,Dubbo自身的RPC协议等)

  4. 支持多种负载均衡算法

  5. 其他高级特性:服务编排,服务治理,服务监控等

缺点如下:

  1. 只支持Java,对于Python没有相应的支持

  2. 虽然已经开源,但是没有成熟的社区来运营和维护,未来升级可能是个麻烦

  3. 重量级的解决方案带来新的复杂性

备选方案三:Zookeeper

Zookeeper是什么?按照Apache官网的描述是:

ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services.

参照官网的定义,它能够做:

  1. 作为配置信息的存储的中心服务器

  2. 命名服务

  3. 分布式的协调

  4. Mater选举等

在定义中特别提到了命名服务。在调研之后,Zookeeper作为服务注册与发现的解决方案,它有如下优点:

  1. 它提供的简单API

  2. 已有互联网公司(例如:Pinterest,Airbnb)使用它来进行服务注册与发现

  3. 支持多语言的客户端

  4. 通过Watcher机制实现Push模型,服务注册信息的变更能够及时通知服务消费方

缺点是:

  1. 引入新的Zookeeper组件,带来新的复杂性和运维问题

  2. 需自己通过它提供的API来实现服务注册与发现逻辑(包含Python与Java版本)

我们对上述几个方案的优缺点权衡之后,决定采用了基于Zookeeper实现自己的服务注册与发现。

基于Zookeeper的服务注册与发现架构

在此架构中有三类角色:服务提供者,服务注册中心,服务消费者。

服务提供者

服务提供者作为服务的提供方将自身的服务信息注册到服务注册中心中。服务信息包含:

▪ 隶属于哪个系统

▪ 服务的IP,端口

▪ 服务的请求URL

▪ 服务的权重等等

服务注册中心

服务注册中心主要提供所有服务注册信息的中心存储,同时负责将服务注册信息的更新通知实时的Push给服务消费者(主要是通过Zookeeper的Watcher机制来实现的)。

服务消费者

服务消费者主要职责如下:

  1. 服务消费者在启动时从服务注册中心获取需要的服务注册信息

  2. 将服务注册信息缓存在本地

  3. 监听服务注册信息的变更,如接收到服务注册中心的服务变更通知,则在本地缓存中更新服务的注册信息

  4. 根据本地缓存中的服务注册信息构建服务调用请求,并根据负载均衡策略(随机负载均衡,Round-Robin负载均衡等)来转发请求

  5. 对服务提供方的存活进行检测,如果出现服务不可用的服务提供方,将从本地缓存中剔除

服务消费者只在自己初始化以及服务变更时会依赖服务注册中心,在此阶段的单点故障通过Zookeeper集群来进行保障。在整个服务调用过程中,服务消费者不依赖于任何第三方服务。

实现机制介绍

Zookeeper数据模型介绍

在整个服务注册与发现的设计中,最重要是如何来存储服务的注册信息。

在设计基于Zookeeper的服务注册结构之前,我们先来看一下Zookeeper的数据模型。Zookeeper的数据模型如下图所示:

Zookeeper数据模型结构与Unix文件系统很类似,是一个树状层次结构。每个节点叫做Znode,节点可以拥有子节点,同时允许将少量数据存储在该节点下。客户端可以通过监听节点的数据变更和子节点变更来实时获取Znode的变更(Wather机制)。

服务注册结构

服务注册结构如上图所示。

▪ /dada来标示公司名称dada,同时能方便与其它应用的目录区分开(例如:Kafka的brokers注册信息放置在/brokers下)

▪ /dada/services将所有服务提供者都放置该目录下

▪ /dada/services/category1目录定义具体的服务提供者的id:category1,同时该Znode节点中允许存放该服务提供者的一些元数据信息,例如:名称,服务提供者的Owner,上下文路径(Java Web项目),健康检查路径等。该信息可以根据实际需要进行自由扩展。

▪ /dada/services/category1/helloworld节点定义了服务提供者category1下的一个服务:helloworld。其中helloworld为该服务的ID,同时允许将该服务的元数据信息存储在该Znode下,例如图中标示的:服务名称,服务描述,服务路径,服务的调用的schema,服务的调用的HTTP METHOD等。该信息可以根据实际需要进行自由扩展。

▪ /dada/services/category1/helloworld/providers节点定义了服务提供者的父节点。在这里其实可以将服务提供者的IP和端口直接放置在helloworld节点下,在这里单独放一个节点,是为了将来可以将服务消费者的消息挂载在helloworld节点下,进行一些扩展,例如命名为:/dada/services/category1/helloworld/consumers。

▪ /dada/services/category__1/helloworld/providers/192.168.1.1:8080该节点定义了服务提供者的IP和端口,同时在节点中定义了该服务提供者的权重。

实现机制

由于目前服务注册通过我们的服务注册中心UI来进行注册,这部分逻辑比较简单,即通过UI界面来构造上述定义的服务注册结构。

下面着重介绍一下我们的服务发现是如何工作的:

在上述类图中,类ServiceDiscovery主要通过Zookeeper的API(Python/Java版本)来获取服务信息,同时对服务注册结构中的每个服务的providers节点增加Watcher,来监控节点变化。获取的服务注册信息保存在变量service_repos中。通过在初始化时设置LoadBalanceStrategy的实现(Round-Robin算法,Radmon算法)来实现服务提供者的负载均衡。主要方法:

  1. init获取Zookeeper的服务注册信息,并缓存在service_repos

  2. get_service_repos方法获取实例变量service_repos

  3. get_service_endpoint根据init构建好的service_repos,以及lb_strategy提供的负载均衡策略返回某个服务的URL地址

  4. update_service_repos通过Zookeeper的Watcher机制来实时更新本地缓存service_repos

  5. heartbeat_monitor是一个心跳检测线程,用来进行服务提供者的健康存活检测,如果出现问题,将该服务提供者从该服务的提供者列表中移除;反之,则加入到服务的提供者列表中

LoadBalanceStrategy定义了根据服务提供者的信息返回对应的服务Host和IP,即决定由那台主机+端口来提供服务。

RoundRobinStrategy和RandomStrategy分别实现了Round-Robin和随机的负载均衡算法

未来展望

目前达达基于Zookeeper的服务注册与发现的架构还处于初期,很多功能还未完善,例如:服务的路由功能,与部署平台的集成,服务的监控等等。

当然基于Zookeeper还能做其它许多事情,例如:实时动态配置系统。目前,我们已经基于Zookeeper实现了实时动态配置系统

分享到:
评论

相关推荐

    基于zookeeper注册发现服务的springbootDemo

    总的来说,这个"基于zookeeper注册发现服务的springbootDemo"是一个很好的学习资源,它涵盖了SpringBoot、Zookeeper、微服务、MyBatis和Durid等多个重要技术点,有助于理解并实践分布式系统中的服务治理。

    zookeeper在线注册服务查看工具

    1. **查看服务注册**:查看各个服务节点在Zookeeper中的位置,了解服务是否正确注册,节点数据是否与预期一致。 2. **查找服务故障**:当服务出现异常时,可以通过工具快速定位到可能存在问题的服务节点,检查其状态...

    基于ZooKeeper的一种分布式通信服务中间件的研究.pdf

    本研究基于ZooKeeper,设计并实现了一种分布式通信服务中间件。ZooKeeper是一个开源的分布式协调服务,它能够提供高性能、可扩展的服务协调功能,如分布式锁、配置管理、命名服务等。在本研究中,利用ZooKeeper提供...

    基于zookeeper集群监测服务器宕机情况,并发邮件通知

    由于项目需要,编写基于zookeeper集群监测服务器宕机情况,并发邮件通知代码;实现很简单,编写了客户端和服务端,基于maven实现,代码方面修改zookeeper ip地址,需要部署的服务器名和邮件信息即可实现。直接打包...

    基于ZooKeeper的分布式Session实现

    标题 "基于ZooKeeper的分布式Session实现" 涉及的是在分布式系统中如何利用Apache ZooKeeper来管理和共享Session信息。ZooKeeper是一款开源的分布式协调服务,它为分布式应用程序提供了一个简单一致的接口,用于处理...

    (源码)基于ZooKeeper的分布式服务管理系统.zip

    1. 服务注册与发现通过ZooKeeper实现服务的动态注册与发现,支持服务的动态上下线。 2. 分布式锁利用ZooKeeper的临时顺序节点特性,实现高效的分布式锁机制,避免传统锁机制中的“羊群效应”。 3. 统一配置管理通过...

    基于Zookeeper集群环境下的服务注册代码

    zookeeper作为如今分布式应用下常用的开发技术,已经广泛应用于各种...该项目介绍了zookeeper的服务注册功能,使用了zookeeper集群环境搭建,可参考博客:https://blog.csdn.net/LiaoHongHB/article/details/84950486

    基于ZooKeeper的一种分布式系统架构设计与实现.pdf

    本文介绍了一种基于ZooKeeper的分布式系统架构设计与实现,展示了如何通过分布式服务模型和异步通信来实现服务注册、服务监管、服务加载、通信服务等关键功能,并通过实际项目对所设计架构进行测试验证,证明了该...

    SpringCloud——Zookeeper(注册中心)

    在分布式系统中,服务注册与发现是至关重要的一个环节,SpringCloud通过集成不同的注册中心,如Eureka、Consul和Zookeeper,为微服务架构提供了强大的支持。本篇主要聚焦于SpringCloud与Zookeeper的结合,讲解如何...

    一款基于Netty+Zookeeper+Spring实现的轻量级Java RPC框架。提供服务注册,发现,负载均衡,.zip

    在RPC框架中,Zookeeper常被用作服务注册与发现的中心。服务提供者可以在Zookeeper上注册自己的服务,而服务消费者可以通过查询Zookeeper获取可用的服务实例,实现了服务的动态发现和负载均衡。 3. **Spring**: ...

    Netty + ZooKeeper 实现简单的服务注册与发现

    "Netty + ZooKeeper 实现简单的服务注册与发现" 在分布式系统中,服务注册和发现是核心组件之一。本文将介绍如何使用 Netty 和 ZooKeeper 实现简单的服务注册和发现。 服务注册和发现 服务注册和发现是分布式系统...

    基于Dubbo+Zookeeper实现webservice

    Dubbo服务注册与发现** Dubbo支持多种注册中心,其中Zookeeper是最常用的一种。Zookeeper作为一个分布式数据存储和命名服务,可以存储Dubbo服务提供者的元数据信息。当服务提供者启动时,会向Zookeeper注册自己的...

    springBoot+dubbo+zookeeper分布式微服务

    通过Zookeeper进行服务注册与发现,Dubbo能确保服务之间的通信稳定可靠。 **Zookeeper** Apache ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,它是集群的管理者,监视着集群中各个节点的状态根据...

    基于Zookeeper的分布式ICE中间件研究.pdf

    本文提出的基于Zookeeper的IceGrid服务高可用改进模型,目的是为了克服原有IceGrid服务在主节点不可用时需要手动切换的缺陷。通过Zookeeper的选举机制,当主节点不可访问时,可以在从节点中自动选举出一个新的主节点...

    使用node.js+zookeeper+springBoot实现服务注册与发现,请求代理转发

    在服务注册与发现场景中,Zookeeper作为一个中心化的注册表,允许服务提供者将自己的服务注册到Zookeeper中,并且服务消费者可以通过Zookeeper查找并连接到这些服务。每个服务都有一个唯一的ID(或叫服务名),...

    基于zookeeper动态扩展处理分类数据

    1. **服务注册与发现**:每个服务实例可以在ZooKeeper上注册一个节点,表示其存在和处理的分类数据类型。其他服务可以通过查询ZooKeeper找到负责特定分类数据的服务实例。 2. **负载均衡**:ZooKeeper可以协助实现...

    基于Java和Zookeeper的dubbo双端分布式服务设计源码

    该项目是一款基于Java和Zookeeper...该系统通过dubbo框架实现服务注册与发现,并利用Zookeeper进行服务协调,支持注解驱动的服务调用和查询所有操作。在Zookeeper注册服务后,系统显示的服务列表清晰有序,无无序符号。

    Dubbo+Zookeeper+Spring整合应用篇-Dubbo基于Zookeeper实现分布式服务(二)

    Dubbo提供了服务注册与发现、远程调用、负载均衡、容错和流量控制等关键功能。它支持多种协议,如HTTP、RMI、Hessian等,但最常使用的还是Dubbo自身的二进制协议,因为它提供了更高的性能和更低的网络开销。 ...

    基于DUBBO+ZOOKEEPER计量服务平台研究.pdf

    它还参与了服务的注册和发现,使得服务提供者与消费者的交互更加透明。 DUBBO与ZOOKEEPER的结合解决了以下问题: 1. 数据一致性:ZOOKEEPER的同步机制确保了跨系统间共享数据的事务一致性。 2. 数据共享:ZOOKEEPER...

Global site tag (gtag.js) - Google Analytics