一场事故告诉你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 共享锁 排他锁 防插入锁

试验1事务1&#xff1a;#!/usr/bin/pythonimport timeimport MySQLdb;conn MySQLdb.connect(host"localhost",port3306,user"root",passwd"asdf",db"test",unix_socket"/data/mysql_3306/mysql.sock")cursor conn.cursor(…

MySQL操作之JSON数据类型操作详解

MySQL操作之JSON数据类型操作详解 这篇文章主要介绍了MySQL操作之JSON数据类型操作详解&#xff0c;内容较为详细&#xff0c;具有收藏价值&#xff0c;需要的朋友可以参考。 概述 mysql自5.7.8版本开始&#xff0c;就支持了json结构的数据存储和查询&#xff0c;这表明了my…

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

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

Http GET 请求参数中文乱码

Http GET 请求参数中文乱码 两种解决方式 第1种&#xff1a;代码里转换 String name request.getParamter("name"); String nameUtf8 new String(name.getBytes("ISO8859-1"), "UTF-8");第2种&#xff1a;修改Tomcat配置 TOMCAT_HOME/conf…

matlab randomsample,randperm和randsample函数用法对比

构建替代数据的时候&#xff0c;一种常见的思路是打乱原数据的排列次序&#xff0c;通过随机置换原数据的排列次序从而产生和原数据系列统计特征(如均值、方差、分布)一致的随机数据。具体到Matlab中&#xff0c;此思路的实现会涉及到两个命令&#xff1a;randperm和randsample…

SpringBoot的编码问题

第一种方式&#xff1a;直接在配置文件中设置浏览器的解析编码的格式 #设置字符编码 #开启springboot的http字符编码的支持 spring.http.encoding.enabledtrue #强制使用指定字符编码 spring.http.encoding.forcetrue #指定使用的字符编码 spring.http.encoding.charsetUTF-8第…

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

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

SpringMVC请求参数乱码问题

post 请求方式&#xff1a; 在 web.xml 中配置一个过滤器 <!-- 配置 springMVC 编码过滤器 --><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter…

MySQL中 JSON 数据类型应用

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

如何修改matlab中的语句,求大神帮忙看一下这个语句怎么改!!!!!

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼clcclearWimread(e:\matlab\aaa\1.jpg);imshow (W);I rgb2gray(W); % 灰度处理imshow (I);title(灰度图像);Jimnoise(I,salt & pepper,0.2); %椒盐噪声figureimshow (J) ;title(椒盐噪声);Qimnoise(I,gaussian,0,0.01); %高斯…

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 七、总结 概述…

python新手输出错误,Python 新手常犯错误(第一部分)

用一个可变的值作为默认值这是一个绝对值得放在第一个来说的问题。不仅仅是因为产生这种BUG的原因很微妙&#xff0c;而且这种问题也很难检查出来。思考一下下面的代码片段&#xff1a;def foo(numbers[]):numbers.append(9)print numbers在这里&#xff0c;我们定义了一个 lis…

分布式和微服务的区别

分布式和微服务的区别 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…

oracle-04045,Oracle ORA-04045 errors during recompilation/revalidation

About UTLRP.SQL What is UTLRP.SQL?This script recompiles invalid PLSQL modules.NOTE: This script DOES NOT Invalidate any PLSQL modules like utlirp.sql and utlip.sql What this script does?This script recompiles all existing invalid PL/SQL modules in a dat…

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

一、分布式系统 在《分布式系统原理与范型》一书中有如下定义&#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、各微…