K8S如何部署ZooKeeper以及如何进行ZooKeeper的平滑替换

2.png

前言

在之前的章节中,我们已经成功地将Dubbo项目迁移到了云环境。在这个过程中,我们选择了单机ZooKeeper作为注册中心。接下来,我们将探讨如何将单机ZooKeeper部署到云端,以及在上云过程中可能遇到的问题及解决方案。

ZooKeeper是一个开源的分布式协调服务,由Apache软件基金会开发。它主要用于实现分布式系统中的配置管理、命名服务、分布式同步和组服务等,是一个功能强大、高性能、高可用性和可扩展性的分布式协调服务,广泛应用于各种分布式系统和微服务架构中。ZooKeeper的主要特点如下:

  • 高可用性:ZooKeeper通过在集群中选举领导者来确保系统的可用性。当领导者不可用时,其他服务器可以自动选举出新的领导者,从而保证了系统的持续运行。

  • 数据一致性:ZooKeeper使用一种称为“原子广播”的数据同步机制,确保所有节点上的数据保持一致。这对于需要高度一致性的分布式应用(如金融交易系统)非常重要。

  • 高性能:ZooKeeper具有低延迟和高吞吐量的特点,适用于处理大量并发请求。它使用了多种优化技术,如内存管理和多线程,以提高性能。

  • 可扩展性:ZooKeeper支持水平扩展,可以通过增加服务器节点来提高系统的容量。此外,ZooKeeper还提供了负载均衡功能,可以根据服务器的负载情况自动分配客户端请求。

  • 灵活性:ZooKeeper提供了丰富的API和工具,方便开发者进行集成和定制。同时,它还支持多种编程语言,如Java、C++、Python等。

ZooKeeper的云端迁移

由于我们还有一些Dubbo服务并未部署在Kubernetes集群内,因此我们需要在Zookeeper中采用NodePort方式来暴露相关端口。这样一来,外部的Dubbo服务便可以通过访问Zookeeper节点的IP地址和NodePort号来建立连接,从而实现对其他Dubbo服务的访问。

在之前的文章中,我们提到了我们的Dubbo版本为2.7.22。因此,在查阅了Dubbo官方文档中关于Dubbo版本与ZooKeeper版本之间的依赖关系后,我们选择的ZooKeeper官方镜像为zookeeper:3.4.9

Dubbo版本与ZooKeeper版本关系

基于以上的历史原因,我们最终的部署文件如下所示:

apiVersion: v1
kind: Service
metadata:
  name: zookeeper
  namespace: your-namespace
spec:
  selector:
    app: zookeeper
  type: NodePort
  ports:
    - name: client
      port: 2181
      targetPort: 2181
      nodePort: 30000
    - name: follower
      port: 2888
      targetPort: 2888
      nodePort: 30001
    - name: leader
      port: 3888
      targetPort: 3888
      nodePort: 30002
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: zookeeper
  namespace: your-namespace
spec:
  replicas: 1
  selector:
    matchLabels:
      app: zookeeper
  template:
    metadata:
      labels:
        app: zookeeper
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: project.node
                    operator: In
                    values:
                      - your-namespace
      containers:
        - name: zookeeper
          image: zookeeper:3.4.9
          imagePullPolicy: IfNotPresent
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          ports:
            - containerPort: 2181
            - containerPort: 2888
            - containerPort: 3888
          volumeMounts:
            - name: data
              mountPath: /data
      volumes:
        - name: data
          hostPath:
            path: /var/lib/docker/zookeeper

在这个配置文件中,我们使用了一个名为zookeeper的Deployment来部署单机ZooKeeper,并使用了一个名为zookeeper的Service来暴露端口。Service的类型被设置为NodePort,这样可以在集群外部链接ZooKeeper。Service的选择器指定了要暴露的Pod,这里使用了一个名为zookeeper的标签。Service的端口被设置为2181、2888和3888,分别对应ZooKeeper的客户端端口、跟随者端口和领导者端口。targetPort字段指定了要转发到Pod的端口,这里使用了相同的端口号。nodePort字段指定了要暴露的端口号,这里分别使用了30000、30001和30002端口。我们将/data目录挂载到了宿主机的/var/lib/docker/zookeeper目录。这个目录用于存储ZooKeeper的数据和日志。

启动一个Dubbo服务,我们使用刚刚部署的Zookeeper作为注册中心。同时,我们也部署了一个Dubbo-Admin,它同样链接到刚刚部署的Zookeeper上。登录到Dubbo-Admin前端页面,我们发现服务已经成功注册。至此,Zookeeper已成功迁移到云端。

2.png

ZooKeeper的平滑迁移

根据上述步骤,我们已经成功部署了一个可用的单机ZooKeeper。那么,如何将线上存量服务在不停机的情况下优雅的平滑迁移过来呢?

其实,在Dubbo官方文档中,已经给了我们答案:多注册中心地址不聚合

Dubbo 注册中心和服务是独立配置的,通常开发者不用设置服务和注册中心组件之间的关联关系,Dubbo 框架会将自动执行以下动作:

  • 对于所有的 Service 服务,向所有全局默认注册中心注册服务地址。
  • 对于所有的 Reference 服务,从所有全局默认注册中心订阅服务地址。
<dubbo:registry id="one" address="zookeeper://127.0.0.1:9090" />
<dubbo:registry id="two" address="zookeeper://127.0.0.2:9010" />

因此,当我们配置如上所示独立配置的注册中心组件时,Dubbo会将所有的Service服务同时注册到这两个ZooKeeper上,并且所有的Reference服务也会同时订阅这两个ZooKeeper。地址列表在消费端默认是完全隔离的,负载均衡选址要经过两步:

  1. 注册中心集群间选址,选定一个集群
  2. 注册中心集群内选址,在集群内进行地址筛选

1.png

注册中心集群间选址策略有如下几种:

  • 随机默认策略,每次请求都随机的分配到一个注册中心集群。随机的过程中会有可用性检查,即每个集群要确保至少有一个地址可用才有可能被选到。

  • preferred 优先:如果有注册中心集群配置了 preferred="true",则所有流量都会被路由到这个集群。

    <dubbo:registry id="one" address="zookeeper://127.0.0.1:9090" preferred="true"/>
    <dubbo:registry id="two" address="zookeeper://127.0.0.2:9010" />
    
  • weighted:基于权重的随机负载均衡,以下集群间会有大概 10:1 的流量分布。

    <dubbo:registry id="one" address="zookeeper://127.0.0.1:9090" weight="100"/>
    <dubbo:registry id="two" address="zookeeper://127.0.0.2:9010" weight="10"/>
    
  • 同 zone 优先:根据 Invocation 中带的流量参数或者在当前节点通过 context 上下文设置的参数,流量会被精确的引导到对应的集群。

    <dubbo:registry id="one" address="zookeeper://127.0.0.1:9090" zone="one"/>
    <dubbo:registry id="two" address="zookeeper://127.0.0.2:9010" zone="two"/>
    
    RpcContext.getContext().setAttachment("registry_zone", "one");
    

在这里,我们采用默认的随机策略,因为在随机的过程中会有可用性检查,这确保了我们的消费者服务始终能够连接到可用的提供者服务,为我们不停机迁移提供了基础。

接下来,我们需要对代码进行修改,具体操作如下:

  • dubbo.xml:

    • 删除以下部分:

      <!-- zookeeper注册中心 -->
      <dubbo:registry address="${dubbox.registry.address}"/>
      
    • 新增以下部分:

      <!-- 老zookeeper注册中心 -->
      <dubbo:registry id="oldZkRegistry" address="${dubbox.registry.address}"/>
      <!-- 新k8s上zk注册中心 -->
      <dubbo:registry id="newZkRegistry" address="${dubbox.registry.address.new}"/>
      
  • 配置文件:在配置文件中,新增以下配置:

    # 新k8s上zk注册中心地址,ip为宿主机的ip,端口为nodeport暴露的client的端口
    dubbox.registry.address.new = zookeeper://xx.xx.xx.xx:30000
    
    

在经过改造后,我们的服务将同时注册到新的和旧的ZooKeeper上,这就相当于我们搭建了一个ZooKeeper集群。当所有的存量服务都完成改造并成功部署上线后,我们还需要对我们的代码进行进一步的改造。具体的步骤如下:

  • dubbo.xml:

    • 删除以下部分:

      <!-- 老zookeeper注册中心 -->
      <dubbo:registry id="oldZkRegistry" address="${dubbox.registry.address}"/>
      <!-- 新k8s上zk注册中心 -->
      <dubbo:registry id="newZkRegistry" address="${dubbox.registry.address.new}"/>
      
      
    • 新增以下部分:

      <!-- 新k8s上zk注册中心 -->
      <dubbo:registry address="${dubbox.registry.address.new}"/>
      
      
  • 配置文件:在配置文件中,删除以下配置:

    # 老zk注册中心地址
    dubbox.registry.address = zookeeper://xx.xx.xx.xx:2181
    
    

当我们的存量服务全部经过改造并成功部署上线后,我们的老ZooKeeper才能够进行停机下线。至此,ZooKeeper的平滑替换便顺利完成了。

小结

经过以上的阐述,我们可以明确地认识到,在决定ZooKeeper的部署版本时,我们需要进行深入细致的分析,充分考虑外部环境因素的影响,例如Duboo版本之间的兼容性问题。为了确保ZooKeeper的平稳迁移并维持服务的连续性,我们需要采取一系列策略,如逐步升级、严格的功能测试和版本兼容性检查等。要在生产环境中实现ZooKeeper的平滑迁移并保持服务不间断,这将需要投入大量的时间和精力。因此,在我们正式上线生产环境之前,必须进行详尽的规划,全面预见未来可能出现的情况,以最大程度地避免不必要的麻烦。只有这样,我们才能确保项目的长期稳定运行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/90828.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

免费开源使用的几款红黑网络流量工具,自动化的多功能网络侦查工具、超级关键词URL采集工具、Burpsuite被动扫描流量转发插件

免费开源使用的几款红黑网络流量工具&#xff0c;自动化的多功能网络侦查工具、超级关键词URL采集工具、Burpsuite被动扫描流量转发插件。 #################### 免责声明&#xff1a;工具本身并无好坏&#xff0c;希望大家以遵守《网络安全法》相关法律为前提来使用该工具&am…

【C++】初步认识模板

&#x1f3d6;️作者&#xff1a;malloc不出对象 ⛺专栏&#xff1a;C的学习之路 &#x1f466;个人简介&#xff1a;一名双非本科院校大二在读的科班编程菜鸟&#xff0c;努力编程只为赶上各位大佬的步伐&#x1f648;&#x1f648; 目录 前言一、泛型编程二、函数模板2.1 函…

【Java】基础练习(十)

1.判断邮箱 输入一个电子邮箱&#xff0c;判断是否是正确电子邮箱地址。 正确的邮箱地址&#xff1a; 必须包含 字符&#xff0c;不能是开头或结尾必须以 .com结尾和.com之间必须有其他字符 (1) Email类&#xff1a; package swp.kaifamiao.codes.Java.d0823; /** 输入一个…

4-4 Representing text Exercise

本文所用资料下载 一. Representing text Let’s load Jane Austen’s Pride and Prejudice. We first split our text into a list of lines and pick an arbitrary line to focus on: with open(D:jane-austen/1342-0.txt, encodingutf8) as f:text f.read() lines text.…

简单了解文件上传漏洞(md版)

简单了解文件上传漏洞 一、什么是文件上传漏洞二、常见功能点三、成功的前提四、文件上传的校验方式五、Pass-1六、Pass-2七、蚁剑结合msf获取目标权限 一、什么是文件上传漏洞 在文件上传的功能处&#xff0c;如果服务端未对上传的文件进行严格的验证和过滤&#xff0c;导致攻…

登录校验-Filter-详解

目录 执行流程 拦截路径 过滤器链 小结 执行流程 过滤器Filter拦截到请求之后&#xff0c;首先执行方放行之前的逻辑&#xff0c;然后执行放行操作&#xff08;doFilter&#xff09;&#xff0c;然后会访问对应的Web资源&#xff08;对应的Controller类&#xff09;&#…

【C++】C++ 引用详解 ⑤ ( 函数 “ 引用类型返回值 “ 当左值被赋值 )

文章目录 一、函数返回值不能是 " 局部变量 " 的引用或指针1、函数返回值常用用法2、分析函数 " 普通返回值 " 做左值的情况3、分析函数 " 引用返回值 " 做左值的情况 函数返回值 能作为 左值 , 是很重要的概念 , 这是实现 " 链式编程 &quo…

Acrobat Pro DC软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 Acrobat Pro DC是Adobe公司开发的一款PDF编辑软件&#xff0c;简称为DC&#xff0c;是Acrobat系列软件中的一款&#xff0c;是行业内的标准工具&#xff0c;被广泛应用于文档处理、电子合同、PDF表单等领域。 Acrobat Pro DC软…

【SpringBoot】第一篇:redis使用

背景&#xff1a; 本文是教初学者如何正确使用和接入redis。 一、引入依赖 <!--redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><depen…

适配器模式实现stack和queue

适配器模式实现stack和queue 什么是适配器模式&#xff1f;STL标准库中stack和queue的底层结构stack的模拟实现queue的模拟实现 什么是适配器模式&#xff1f; 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结)&#xff…

基于广义神经网络的网络入侵检测Matlab代码

1.案例背景 1.1 FCM 聚类算法 聚类方法是数据挖掘中经常使用的方法,它将物理的或抽象的对象分为几个种群,每个种群内部个体间具有较高的相似性,不同群体内部间个体相似性较低。模糊c均值聚类算法(Fuzzy C- Mean, FCM)是用隶属度确定每个元素属于某个类别程度的一种聚类算法&am…

Rspack 创建 vue2/3 项目接入 antdv(rspack.config.js 配置 less 主题)

一、简介 Rspack CLI 官方文档。 rspack.config.js 官方文档。 二、创建 vue 项目 创建项目&#xff08;文档中还提供了 Rspack 内置 monorepo 框架 Nx 的创建方式&#xff0c;根据需求进行选择&#xff09; # npm 方式 $ npm create rspacklatest# yarn 方式 $ yarn create…

AI 绘画Stable Diffusion 研究(十四)SD 图生图+剪映制作人物说话视频

大家好&#xff0c;我是风雨无阻。 前一篇&#xff0c;我们详细介绍了使用 SadTlaker制作数字人视频案例&#xff0c;感兴趣的朋友请前往查看:AI 绘画Stable Diffusion 研究&#xff08;十三&#xff09;SD数字人制作工具SadTlaker使用教程。 对于没有安装 SadTlaker 插件的朋友…

Java—实现多线程程序 | 入门

目录 一、前言 二、基本概念 进程 线程 三、Java多线程实现 java.lang.Thread类 获取线程名字及对象 获取main进程名 Thread currentThread() 四、线程优先级 设置优先级 一、前言 前期入门学习的代码中&#xff0c;全部都是单线的程序&#xff0c;也就是从头到尾…

leetcode 767. Reorganize String(重组字符串)

重新排列字符串s中的字母&#xff0c;使得任意两个相邻的字母都不相同。 思路&#xff1a; 让相邻字母不同&#xff0c;能想到的办法是先把相同的字母排列&#xff0c; 然后在相同字母的缝隙中插入另一种字母。 比如"aab", 先把"a a"排出来&#xff0c;再…

界面组件DevExpress Reporting——增强的SQL和实体框架数据源引入

DevExpress Reporting是.NET Framework下功能完善的报表平台&#xff0c;它附带了易于使用的Visual Studio报表设计器和丰富的报表控件集&#xff0c;包括数据透视表、图表&#xff0c;因此您可以构建无与伦比、信息清晰的报表。 本文总结了v23.1中针对DevExpress报表和BI Das…

UI位置与布局

UI位置与布局 引言 发现UGUI的RectTransform定位还是很复杂的&#xff0c;感觉有必要详细了解一下 RectTransform 继承自Transform。他的local position由其他几个变量控制。建议不要直接设置position 目的是为了实现UI自动布局。这套方法将绝对定位&#xff0c;相对定位&a…

vue和react学哪一个比较有助于以后发展?

前言 首先声明vue和react这两个框架都是很优秀的前端框架&#xff0c;使用的人群下载量上数量也是相当的庞大&#xff0c;这篇文章没有贬低或者攻击任何一个框架的意思&#xff0c;只在于根据答主的问题来对这两个框架做出对比&#xff0c;以方便大家更加清晰的了解到当下vue和…

设计模式--适配器模式(Adapter Pattern)

一、什么是适配器模式&#xff08;Adapter Pattern&#xff09; 适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许将一个类的接口转换成客户端所期望的另一个接口。适配器模式主要用于解决不兼容接口之间的问题&#xff0c;使得原本…

分析系统 - 使用Python爬虫

在竞争激烈的市场环境中&#xff0c;了解和分析竞争对手的销售策略和市场表现对于企业的成功至关重要。本文将介绍如何利用Python爬虫建立低成本的销售竞争对手分析系统&#xff0c;探索其方法、工具和好处&#xff0c;并同时解决可能出现的问题。 销售竞争对手分析的目标是获取…