一场事故告诉你zookeeper和nacos谁更适合做注册中心

前言

​ 在分布式系统中,注册中心充当着重要角色,是服务发现、客户端负载均衡中不可缺少的一员。注册中心除了能够实现基本的功能外,他的稳定性、可用性和健壮性对整个分布式系统的流畅运行影响重大。dubbo作为国内一款主流的分布式系统,支持的注册中心有zookeeper、nacos和redis等第三方中间件,同时也支持Simple和Multicast的方式。zk和nacos可能是最常使用的方式,到底谁更胜一筹呢?以下的事故现场便有答案。

在分布式系统中,服务往往由提供方来定义,并给出服务定义的sdk包。消费方通过引入提供方的sdk包,进行服务的发现。但是当一个子系统需要依赖成千上百个子系统的服务,那么需要依赖成千上百个子系统的sdk包,显然有些不友好,那么有什么方式可以不引依赖呢,dubbo提供了泛化调用方式。泛化调用虽然解决了依赖引用的问题,但是也存在一些使用不当引发的致命问题,通过如下一个泛化服务定义未缓存的demo案例来揭穿。

案例复现

​ pom.xml文件中引入2.5.7版本的dubbo,0.11版本的zkClient依赖,采用zk作为注册中心。

		<dependency><groupId>com.alibaba</groupId><artifactId>dubbo</artifactId><version>2.5.7</version></dependency><dependency><groupId>com.101tec</groupId><artifactId>zkclient</artifactId><version>0.11</version></dependency>

​ 通过如下的代码来模拟泛化调用,helloService()方法中进行泛化服务的定义,并返回泛化服务。然后在sayHello()方法中进行服务泛化调用,sayHello方法总通过一个死循环一直进行服务获取,真到发生异常。

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.rpc.service.GenericService;
import org.springframework.stereotype.Service;@Service
public class HelloGenericService {private GenericService helloService() {ReferenceConfig<GenericService> config = new ReferenceConfig<>();config.setInterface("com.qiao.hao.ting.service.HelloService");config.setGeneric(true);config.setProtocol("dubbo");config.setCheck(false);//采用zk作为注册中心config.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));//config.setRegistry(new RegistryConfig("nacos://127.0.0.1:8848"));config.setTimeout(1000);config.setApplication(new ApplicationConfig("general"));GenericService service = config.get();return service;}public Object sayHello() {while (true) {try {GenericService genericService = helloService();//rpc调用//genericService.$invoke("syaHello", new String[]{}, new Object[]{});} catch (Exception e) {e.printStackTrace();break;}}return "success";}
}

​ 触发sayHello调用之后,来看zk节点的信息。通过zkCli客户端窗口查看dubbo注册节点信息,helloService每被调用一次,则会向zk的/dubbo/对应接口/consumers目录写入一个消费节点。

img

​ 程序一直运行下去,消费者节点个数会直接溢出ls命令能够接受的数组大小 。

img

​ 同时zk的data目录下的文件大小在不断地增加,那么一个最直观的问题就是磁盘随着时间推移一定会被打满。

img

​ 同时,通过dubbo-admin查看服务注册信息,可以看到com.qiao.hao.ting.service.HelloService服务节点个数不止一个,随着helloService的一直运行,那么节点个数就会一直增加。

img

​ 现在把注册中心改为nacos,注册客户端采用0.0.1版本的dubbo-registry-nacos。

		<dependency><groupId>com.alibaba</groupId><artifactId>dubbo</artifactId><version>2.5.7</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>dubbo-registry-nacos</artifactId><version>0.0.1</version></dependency>

​ 把泛化服务定义的registry设置为nacos。

   private GenericService helloService() {ReferenceConfig<GenericService> config = new ReferenceConfig<>();config.setInterface("com.qiao.hao.ting.service.HelloService");config.setGeneric(true);config.setProtocol("dubbo");config.setCheck(false);//config.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));//采用nacos作为注册中心config.setRegistry(new RegistryConfig("nacos://127.0.0.1:8848"));config.setTimeout(1000);config.setApplication(new ApplicationConfig("general"));GenericService service = config.get();return service;}

​ 触发sayHello方法,通过nacos的管理界面可知,无论程序怎么跑,com.qiao.hao.ting.service.HelloService消费者注册信息只有一条。

img

​ 为了对比的一致性,都通过dubbo-admin进行对比。dubbo-admin默认是通过zk进行注册的,这里需要对dubbo-admin进行小改造,通过以下两步把dubbo-admin切换到nacos。第一,下载对应dubbo-admin版本的源码(本案例是2.5.7版本),然后引入0.0.1版本的dubbo-registry-nacos的依赖。

img

​ 第二,把dubbo.registry.address的地址改为nacos://127.0.0.1:8848。

img

​ 然后重新构建dubbo-admin,运行。最后查看服务列表,可知,在nacos作为注册中心下,该com.qiao.hao.ting.service.HelloService服务也只会存在一条注册信息。

img

问题分析

​ 由于没有把泛化服务进行缓存,每次调用的时候都会进行一次服务注册,服务注册请求发送到zk,zk就会进行一个节点的写入;nacos中的一致性不是像zk通过节点数据进行维护,并不会出现服务无限重复注册的情况(两者具体的原理不在这里进行说明,敬请期待)。

GenericService service = config.get();

​ 当然实际代码中几乎不可能出现死循环调用注册的,但是在高并发,或者长时间维持一定量的请求,那么还是会导致zk的磁盘耗尽、io读写异常、导致zk不可用,从而导致整个集群的服务注册发型能力不可用。

​ 能不能在测试阶段发现这种问题。如果测试人员比较厉害的,还可能关注服务注册这块。但是一般不可能,服务注册一般不在测试范围,在功能测试,就算算上单元、冒烟、整体及回归测试,也不可能会出现zk的不可用。压力测试,一般比较短暂,短暂时间内的磁盘写入量,机器应该是能够抗住的,除非测试环境也做了监控,但一般也不可能。

解决方案

​ 如果使用zk作为注册中心了,那么如何预防和解决这样的问题呢。

1、对服务进行缓存,比如改为如下代码。

@Service
public class HelloGenericService {private GenericService genericService;private Object lockObject = new Object();private GenericService helloService() {if(genericService != null) {return genericService;}synchronized (lockObject) {if(genericService != null) {return genericService;}ReferenceConfig<GenericService> config = new ReferenceConfig<>();config.setInterface("com.qiao.hao.ting.service.HelloService");config.setGeneric(true);config.setProtocol("dubbo");config.setCheck(false);//config.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));config.setRegistry(new RegistryConfig("nacos://127.0.0.1:8848"));config.setTimeout(1000);config.setApplication(new ApplicationConfig("general"));genericService = config.get();}return genericService;}}

2、加强代码审核

3、对zk节点进行监控,比如磁盘、cpu、io等物理监控,注册服务请求的网络监控。

结论

​ 建议选择nacos作为注册中心。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mysql执行计划含义,mysql执行计划介绍

烂sql不仅直接影响sql的响应时间&#xff0c;更影响db的性能&#xff0c;导致其它正常的sql响应时间变长。如何写好sql&#xff0c;学会看执行计划至关重要。下面我简单讲讲mysql的执行计划&#xff0c;只列出了一些常见的情况&#xff0c;希望对大家有所帮助。测试表结构&…

寄生虫php版,-PHP版SEO最新教材版排名DeDeCms寄生虫V90繁殖

今天视频教程演示说明下PHP寄生虫服务端的使用。主要在很多搭建的过程中会出错&#xff0c;今天主要就讲解下寄生虫配置常见的问题。那么同样也可以看下我们之前的通用版寄生虫使用教程[通用版教程在文件夹中有]&#xff0c;本教程是针对PHP版本的寄生虫服务端进行配置演示。继…

MySQL中 JSON 数据类型应用

前言 今天接触到mysql中json数据类型&#xff0c;之前不知道有这个类型&#xff0c;今天学习一下。 JSON我相信大家都已经很熟悉了&#xff0c;但在 MySQL中&#xff0c;直至 5.7 版本中&#xff0c;才正式引入 JSON数据类型。在次之前&#xff0c;我们通常使varchar或text数…

MySql中json类型的使用___mybatis存取mysql中的json

MySql中json类型的使用 MySQL从5.7.8起开始支持JSON字段&#xff0c;这极大的丰富了MySQL的数据类型。也方便了广大开发人员。但MySQL并没有提供对JSON对象中的字段进行索引的功能&#xff0c;至少没有直接对其字段进行索引的方法。本文将介绍利用MySQL 5.7中的虚拟字段的功能…

百度下拉词+php,百度下拉词是如何生成的?

我们在百度搜索某一词汇的时候&#xff0c;都会在搜索框下面弹出一些相关性和搜索次数比较多的语句或词语&#xff0c;我们在百度上搜索一下&#xff0c;就可以看到用户平时搜索习惯&#xff0c;搜索爱好是什么。护发下拉很多小伙伴就又有疑问了&#xff1a;这些下拉词是根据什…

python元组赋值给变量,Python的赋值

一、序列解包多个赋值操作同时进行&#xff1a;赋值多个值后面再遇到对多个变量赋值时&#xff0c;就不需要对一个变量赋完值再对另一个变量赋值了&#xff0c;用一条语句就可以搞定&#xff0c;例如&#xff1a;再次赋值由输出结果看到&#xff0c;x和y的值交换了&#xff0c;…

微服务,你得知道这

目录 一、业务场景介绍 二、Spring Cloud核心组件&#xff1a;Eureka 三、Spring Cloud核心组件&#xff1a;Feign 四、Spring Cloud核心组件&#xff1a;Ribbon 五、Spring Cloud核心组件&#xff1a;Hystrix 六、Spring Cloud核心组件&#xff1a;Zuul 七、总结 概述…

分布式和微服务的区别

分布式和微服务的区别 1.颜老师&#xff0c;分布式和微服务有什么区别呢&#xff1f;网上说啥的都有&#xff0c;越看越晕了。 答&#xff1a;分布式的核心就一个字&#xff1a;拆。只要是将一个项目拆分成了多个模块&#xff0c;并将这些模块分开部署&#xff0c;那就算是分布…

Oracle数据库空间突然增大,Oracle 表空间异常增长过快解决方法

1. 首先用语句查询容量大于1G的数据段select segment_name,sum(bytes)/1024/1024 from dba_segments group by segment_name having sum(bytes)/1024/1024>1000;得到如下结果&#xff1a;SYS_LOB0000136091C00003$$ 255332MSYS_LOB0000136441C00004$$ 7170MSYS_C…

分布式和微服务是什么?二者的区别又是什么?

一、分布式系统 在《分布式系统原理与范型》一书中有如下定义&#xff1a; “分布式系统是若干独立计算机的集合&#xff0c;这些计算机对于用户来说就像单个相关系统”&#xff1b; 分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统…

SpringCloud 超详细个人笔记

文章目录SpringCloud1、常见面试题2、微服务概述2.1、什么是微服务2.2、微服务和微服务架构2.3、微服务优缺点2.4、微服务技术栈有哪些&#xff1f;2.5、为什么选择SpringCloud 作为微服务架构2.5.1、选型依据2.5.2、当前各大IT公司用的微服务架构有哪些&#xff1f;2.5.3、各微…

oracle server process,Oracle体系结构及备份(四)server-process

一 什么是服务器进程 除了 Oracle 的后台进程外&#xff0c;还有一些进程是代表用户的&#xff0c;称为服务器进程。这些服务器进程负责按照用户的要求检索数据&#xff0c;并将结果返回给用户。此外&#xff0c;还负责为用户修改缓冲区高数缓存中的数据。 当用户连接到 Oracle…

潘多拉路由器搭建php,MT7620A 无线路由 极路由 1S 定制版 OPERWRT 潘多拉 中继 营销...

定制版 机器 非原版极路由 1S原版极路由下面连接购买https://item.taobao.com/item.htm?id527531952640这个机器是大客户 定制版 营销路由 硬件和极路由 1S 完全相同&#xff0c;只简化了 SD卡座更换为塑胶外壳可以自己DIY 增加USB 接口和SD卡座电源接口为 MICRO USB接口&…

linux close 头文件,Linux open close read write lseek函数的使用

我们经常需要在Linux中进行文件操作&#xff0c;今天我就来分享下文件操作用到的一些函数1 open所需头文件&#xff1a;函数原型&#xff1a;int open(const char *pathname,flags,int perms)pathname&#xff1a;被打开的文件名&#xff0c;可包含路径flag &#xff1a;文件打…

顺序表的实现(头插、尾插、头删、尾删、查找、删除、插入)

目录 一. 数据结构相关概念​ 二、线性表 三、顺序表概念及结构 3.1顺序表一般可以分为&#xff1a; 3.2 接口实现&#xff1a; 四、基本操作实现 4.1顺序表初始化 4.2检查空间&#xff0c;如果满了&#xff0c;进行增容​编辑 4.3顺序表打印 4.4顺序表销毁 4.5顺…

为什么有了接口还要增加一层抽象类?

文章目录接口&#xff1a;抽象类&#xff1a;区别&#xff1a;表象&#xff1a;深层次理解&#xff1a;类图使用抽象类前使用抽象类后为什么有了接口还要增加一层抽象类&#xff1f;接口&#xff1a; 接口里的方法和抽象类中的方法一样&#xff0c;它的方法是抽象的&#xff0…

linux iptables 编译,Linux下编译安装iptables

Linux下如何编译安装iptables实例&#xff1a;先卸载系统已经安装的iptables&#xff0c;卸载前需备份三个文档&#xff1a;iptables启动脚本&#xff0c;iptables-config配置文档&#xff0c;以及已经建立好的iptables规则文档[rootlinuxidc ~]# cp /etc/init.d/iptables ~/ip…

linux密文解密工具,Linux之加密解密工具openssl的用法以及自建CA

在Linux下的安全工具openssl【安全特性】1、保密性&#xff1a;数据保密性、隐私性2、完整性&#xff1a;数据完整性、系统完整性3、可用性4、真实性&#xff1a;确保数据发送方不是被替换的5、可追溯性【安全***】被动***&#xff1a;窃听主动***&#xff1a;伪装、重播、消息…

Windows远程连接的用户名和密码怎么设置?

1、首先&#xff0c;打开A电脑的控制面板&#xff0c;点击系统和安全进入&#xff0c;设置电脑允许远程访问&#xff1b; ] 2、查看A电脑的ip地址&#xff0c;再次打开控制面板&#xff0c;在“网络和Internet”里面点击查看网络状态和任务。 ] 3、在访问类型连接网络里面点…

linux系统date s使用,简述Linux下date命令的使用方法与实例

在Linux环境中&#xff0c;不管是编程还是其他维护&#xff0c;时间是必不可少的&#xff0c;也经常会用到时间的运算&#xff0c;熟练运用date命令来表示自己想要表示的时间&#xff0c;肯定可以给自己的工作带来诸多方便。1.命令格式&#xff1a;date [参数]... [格式]2.命令…