centos选择什么版本_有几千个 Dubbo 实例的瓜子二手车,为什么要选择2.7.3版本?...

a50650d0b26496eb136a65db89555b82.png

随着瓜子业务的不断发展,系统规模在逐渐扩大,目前在瓜子的私有云上已经运行着数百个 Apache Dubbo ( 下文简称 Dubbo )应用,上千个 Dubbo 实例。瓜子各部门业务迅速发展,版本没有来得及统一,各个部门都有自己的用法。随着第二机房的建设,Dubbo 版本统一的需求变得越发迫切。几个月前,公司发生了一次与 Dubbo 相关的生产事故,成为了公司基于社区 Dubbo 2.7.3 版本升级的诱因。接下来,我会从这次线上事故开始,讲讲我们这段时间所做的 Dubbo 版本升级的历程以及我们规划的 Dubbo 后续多机房的方案。Ephermal 节点未及时删除导致 provider 不能恢复注册的问题修复

da62756923b624fde296d64634cd8d13.png

事故背景在生产环境,瓜子内部各业务线共用一套 ZooKeeper 集群作为 Dubbo 的注册中心。2019 年 9 月份,机房的一台交换机发生故障,导致 ZooKeeper 集群出现了几分钟的网络波动。在 ZooKeeper 集群恢复后,正常情况下 Dubbo 的 provider 应该会很快重新注册到 ZooKeeper 上,但有一小部分的 provider 很长一段时间没有重新注册到 ZooKeeper 上,直到手动重启应用后才恢复注册。排查过程首先,我们统计了出现这种现象的 Dubbo 服务的版本分布情况,发现在大多数的Dubbo版本中都存在这种问题,且发生问题的服务比例相对较低,在 GitHub 中我们也未找到相关问题的 issues 。因此,推断这是一个尚未修复的且在网络波动情况的场景下偶现的问题。接着,我们便将出现问题的应用日志、ZooKeeper 日志与 Dubbo 代码逻辑进行相互印证。在应用日志中,应用重连 ZooKeeper 成功后 provider 立刻进行了重新注册,之后便没有任何日志打印。而在 ZooKeeper 日志中,注册节点被删除后,并没有重新创建注册节点。对应到Dubbo的代码中,只有在 FailbackRegistry.register(url) 的 doRegister(url) 执行成功或线程被挂起的情况下,才能与日志中的情况相吻合。

public void register(URL url) {

super.register(url);

failedRegistered.remove(url);

failedUnregistered.remove(url);

try {

// Sending a registration request to the server side

doRegister(url);

} catch (Exception e) {

Throwable t = e;

// If the startup detection is opened, the Exception is thrown directly.

boolean check = getUrl().getParameter(Constants.CHECK_KEY, true)

&& url.getParameter(Constants.CHECK_KEY, true)

&& !Constants.CONSUMER_PROTOCOL.equals(url.getProtocol());

boolean skipFailback = t instanceof SkipFailbackWrapperException;

if (check || skipFailback) {

if (skipFailback) {

t = t.getCause();

}

throw new IllegalStateException("Failed to register " + url + " to registry " + getUrl().getAddress() + ", cause: " + t.getMessage(), t);

} else {

logger.error("Failed to register " + url + ", waiting for retry, cause: " + t.getMessage(), t);

}

// Record a failed registration request to a failed list, retry regularly

failedRegistered.add(url);

}

}

在继续排查问题前,我们先普及下这些概念:Dubbo 默认使用 curator 作为ZooKeeper 的客户端, curator 与 ZooKeeper 是通过 session 维持连接的。当 curator 重连 ZooKeeper 时,若 session 未过期,则继续使用原 session 进行连接;若 session 已过期,则创建新 session 重新连接。而 Ephemeral 节点与 session 是绑定的关系,在 session 过期后,会删除此 session 下的 Ephemeral 节点。继续对 doRegister(url) 的代码进行进一步排查,我们发现在 CuratorZookeeperClient.createEphemeral(path) 方法中有这么一段逻辑:在createEphemeral(path) 捕获了 NodeExistsException ,创建 Ephemeral 节点时,若此节点已存在,则认为 Ephemeral 节点创建成功。这段逻辑初看起来并没有什么问题,且在以下两种常见的场景下表现正常:
  1. Session 未过期,创建 Ephemeral 节点时原节点仍存在,不需要重新创建。

  2. Session 已过期,创建 Ephemeral 节点时原节点已被 ZooKeeper 删除,创建成功。

public void createEphemeral(String path) {

try {

client.create().withMode(CreateMode.EPHEMERAL).forPath(path);

} catch (NodeExistsException e) {

} catch (Exception e) {

throw new IllegalStateException(e.getMessage(), e);

}

}

但是实际上还有一种极端场景,ZooKeeper 的 Session 过期与删除 Ephemeral 节点不是原子性的,也就是说客户端在得到 Session 过期的消息时, Session 对应的 Ephemeral 节点可能还未被 ZooKeeper删除。此时 Dubbo 去创建 Ephemeral 节点,发现原节点仍存在,故不重新创建。待 Ephemeral 节点被 ZooKeeper 删除后,便会出现 Dubbo 认为重新注册成功,但实际未成功的情况,也就是我们在生产环境遇到的问题。此时,问题的根源已被定位。定位问题之后,经我们与 Dubbo 社区交流,发现考拉的同学也遇到过同样的问题,更确定了这个原因。问题的复现与修复定位到问题之后,我们便开始尝试本地复现。由于 ZooKeeper 的 Session 过期但 Ephemeral 节点未被删除的场景直接模拟比较困难,我们通过修改 ZooKeeper 源码,在 Session 过期与删除 Ephemeral 节点的逻辑中增加了一段休眠时间,间接模拟出这种极端场景,并在本地复现了此问题。在排查问题的过程中,我们发现 Kafka 的旧版本在使用 ZooKeeper 时也遇到过类似的问题,并参考 Kafka 关于此问题的修复方案,确定了 Dubbo 的修复方案。在创建 Ephemeral 节点捕获到 NodeExistsException 时进行判断,若 Ephemeral 节点的 SessionId 与当前客户端的 SessionId 不同,则删除并重建 Ephemeral 节点。在内部修复并验证通过后,我们向社区提交了 issues 及 pr。Kafka 类似问题 issues:https://issues.apache.org/jira/browse/KAFKA-1387Dubbo 注册恢复问题 issues:https://github.com/apache/dubbo/issues/5125瓜子的 Dubbo 升级历程

da62756923b624fde296d64634cd8d13.png

上文中的问题修复方案已经确定,但我们显然不可能在每一个 Dubbo 版本上都进行修复。在咨询了社区 Dubbo 的推荐版本后,我们决定在 Dubbo2.7.3 版本的基础上,开发内部版本修复来这个问题。并借这个机会,开始推动公司 Dubbo 版本的统一升级工作。为什么要统一 Dubbo版本?
  1. 统一 Dubbo 版本后,我们可以在此版本上内部紧急修复一些 Dubbo 问题(如上文的 Dubbo 注册故障恢复失效问题)。

  2. 瓜子目前正在进行第二机房的建设,部分 Dubbo 服务也在逐渐往第二机房迁移。统一 Dubbo 版本,也是为 Dubbo 的多机房做铺垫。

  3. 有利于我们后续对 Dubbo 服务的统一管控。

  4. Dubbo 社区目前的发展方向与我们公司现阶段对 Dubbo 的一些诉求相吻合,如支持 gRPC、云原生等。

为什么选择 Dubbo 2.7.3?
  1. 我们了解到,在我们之前携程已经与 Dubbo 社区合作进行了深度合作,携程内部已全量升级为 2.7.3 的社区版本,并在协助社区修复了 2.7.3 版本的一些兼容性问题。感谢携程的同学帮我们踩坑~

  2. Dubbo2.7.3 版本在当时虽然是最新的版本,但已经发布了 2 个月的时间,从社区 issues 反馈来看,Dubbo 2.7.3 相对 Dubbo2.7 之前的几个版本,在兼容性方面要好很多。

  3. 我们也咨询了 Dubbo 社区的同学,推荐升级版本为 2.7.3。

内部版本定位基于社区 Dubbo 2.7.3 版本开发的 Dubbo 内部版本属于过渡性质的版本,目的是为了修复线上 provider 不能恢复注册的问题,以及一些社区 Dubbo 2.7.3 的兼容性问题。瓜子的 Dubbo 最终还是要跟随社区的版本,而不是开发自已的内部功能。因此我们在 Dubbo 内部版本中修复的所有问题均与社区保持了同步,以保证后续可以兼容升级到社区 Dubbo 的更高版本。兼容性验证与升级过程我们在向 Dubbo 社区的同学咨询了版本升级方面的相关经验后,于 9 月下旬开始了 Dubbo 版本的升级工作。
  1. 初步兼容性验证。首先,我们梳理了一些需要验证的兼容性 case ,针对公司内部使用较多的 Dubbo 版本,与 Dubbo 2.7.3 一一进行了兼容性验证。经验证,除 DubboX 外, Dubbo 2.7.3 与其他 Dubbo 版本均兼容。DubboX 由于对 Dubbo 协议进行了更改,与 Dubbo2.7.3 不兼容。

  2. 生产环境兼容性验证。在初步验证兼容性通过后,我们与业务线合作,挑选了一些重要程度较低的项目,在生产环境对 Dubbo 2.7.3 与其他版本的兼容性进行了进一步验证。并在内部版本修复了一些兼容性问题。

  3. 推动公司 Dubbo 版本升级。在 10 月初,完成了 Dubbo 兼容性验证后,我们开始在各个业务线推动 Dubbo 的升级工作。截止到 12 月初,已经有 30% 的 Dubbo 服务的完成了版本升级。按照排期,预计于 2020 年 3 月底前完成公司 Dubbo 版本的统一升级。

兼容性问题汇总在推动升级 Dubbo 2.7.3 版本的过程整体上比较顺利,当然也遇到了一些兼容性问题:1、创建 ZooKeeper 节点时提示没有权限Dubbo 配置文件中已经配置了 ZooKeeper 的用户名密码,但在创建 ZooKeeper 节点时却抛出 KeeperErrorCode = NoAuth 的异常,这种情况分别对应两个兼容性问题:a. issues:https://github.com/apache/dubbo/issues/5076Dubbo 在未配置配置中心时,默认使用注册中心作为配置中心。通过注册中心的配置信息初始化配置中心配置时,由于遗漏了用户名密码,导致此问题。b. issues:https://github.com/apache/dubbo/issues/4991Dubbo 在建立与 ZooKeeper 的连接时会根据 ZooKeeper 的 address 复用之前已建立的连接。当多个注册中心使用同一个 address,但权限不同时,就会出现 NoAuth 的问题。参考社区的 PR ,我们在内部版本进行了修复。2、curator 版本兼容性问题a. Dubbo 2.7.3 与低版本的 curator 不兼容,因此我们默认将 curator 版本升级至 4.2.0

org.apache.curator

curator-framework

4.2.0

org.apache.curator

curator-recipes

4.2.0

b. 分布式调度框架 elastic-job-lite 强依赖低版本的 curator,与 Dubbo 2.7.3 使用的 curator 版本不兼容,这给 Dubbo 版本升级工作带来了一定阻塞。考虑到 elastic-job-lite 已经很久没有人进行维护,目前一些业务线计划将 elastic-job-lite 替换为其他的调度框架。3、OpenFeign 与 Dubbo 兼容性问题issues:https://github.com/apache/dubbo/issues/3990Dubbo 的 ServiceBean 监听 Spring 的 ContextRefreshedEvent,进行服务暴露。OpenFeign 提前触发了 ContextRefreshedEvent,此时 ServiceBean 还未完成初始化,于是就导致了应用启动异常。参考社区的 pr,我们在内部版本修复了此问题。4、RpcException 兼容性问题Dubbo 低版本 consumer 不能识别 Dubbo 2.7 版本 provider 抛出的 org.apache.dubbo.rpc.RpcException。因此,在 consumer 全部升级到 2.7 之前,不建议将 provider 的 com.alibaba.dubbo.rpc.RpcException 改为 org.apache.dubbo.rpc.RpcException。5、QoS 端口占用Dubbo 2.7.3 默认开启 QoS 功能,导致一些混部在物理机的 Dubbo 服务升级时出现 QoS 端口占用问题。关闭 QoS 功能后恢复。6、自定义扩展兼容性问题业务线对于 Dubbo 的自定义扩展比较少,因此在自定义扩展的兼容性方面暂时还没有遇到比较难处理的问题,基本上都是变更 package 导致的问题,由业务线自行修复。7、Skywalking agent 兼容性问题我们项目中一般使 Skywalking 进行链路追踪,由于 Skywalking agent6.0 的 plugin 不支持 Dubbo 2.7,因此统一升级 Skywalking agent 到 6.1 。Dubbo 多机房方案

da62756923b624fde296d64634cd8d13.png

瓜子目前正在进行第二机房的建设工作,Dubbo 多机房是第二机房建设中比较重要的一个话题。在 Dubbo 版本统一的前提下,我们就能够更顺利的开展 Dubbo 多机房相关的调研与开发工作。初步方案我们咨询了 Dubbo 社区的建议,并结合瓜子云平台的现状,初步确定了 Dubbo 多机房的方案。
  1. 在每个机房内,部署一套独立的 ZooKeeper 集群。集群间信息不同步。这样就没有了 ZooKeeper 集群跨机房延迟与数据不同步的问题。

  2. Dubbo 服务注册时,仅注册到本机房的 ZooKeeper 集群;订阅时,同时订阅两个机房的 ZooKeeper 集群。

  3. 实现同机房优先调用的路由逻辑。以减少跨机房调用导致的不必要网络延迟。

同机房优先调用Dubbo 同机房优先调用的实现比较简单,相关逻辑如下:
  1. 瓜子云平台默认将机房的标志信息注入容器的环境变量中。

  2. provider 暴露服务时,读取环境变量中的机房标志信息,追加到待暴露服务的 url 中。

  3. consumer 调用 provider 时,读取环境变量中的机房标志信息,根据路由策略优先调用具有相同标志信息的 provider。

针对以上逻辑,我们简单实现了 Dubbo 通过环境变量进行路由的功能,并向社区提交了 PR。Dubbo 通过环境变量路由 PR:https://github.com/apache/dubbo/pull/5348文章来源:阿里巴巴中间件,点击查看原文。Kubernetes入门与实战培训

da62756923b624fde296d64634cd8d13.png

Kubernetes入门与实战培训将于2020年2月28日在北京开课,3天时间带你系统掌握Kubernetes,学习效果不好可以继续学习。本次培训包括:Docker基础、容器技术、Docker镜像、数据共享与持久化、Docker实践、Kubernetes基础、Pod基础与进阶、常用对象操作、服务发现、Helm、Kubernetes核心组件原理分析、Kubernetes服务质量保证、调度详解与应用场景、网络、基于Kubernetes的CI/CD、基于Kubernetes的配置管理等等,点击下方图片或者阅读原文链接查看详情。

11e4a8a7272e4936f229a9f98c042beb.png

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

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

相关文章

w7系统计算机里没有摄像头,win7系统没有摄像头不能视频的几种原因和解决方法...

电脑升级到win7旗舰版系统后,发现摄像头没有了,之前xp系统在硬盘符中就可以打开摄像头的,可是win7系统没有摄像头怎么办呢?这样就没办法视频了,针对此问题,小编研究出原来要从程序里面调出摄像头功能&#…

新计算机 安装win2000,图文教程!Windows 2000安装过程全接触

13、填写计算机名:安装程序提供了文字输入确定用户的计算机名和其它的设置。   在此,需要声明的是:安装程序会创建一个称为Administrator(系统管理员)的用户帐户,它拥有完全控制计算机的权限。确定这个帐户时,安装程序要求用户输入“系统管…

python创建多线程_初学者看过来:Python中多线程和多处理的指南

使用Python分析数据,如果使用了正确的数据结构和算法,有时可以大量提高程序的速度。实现此目的的一种方法是使用Muiltithreading(多线程)或Multiprocessing(多重处理)。 使用Python分析数据,如果使用了正确的数据结构和算法,有时可…

python求50的阶乘_python中求阶乘

广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 我如何去计算python中的一个整数的阶乘?...写一个猜数字的游戏,预先设定一个数字&am…

项目部署服务器 jstl,Springboot集成jsp及部署服务器实现原理

1.在application配置文件里面加入配置:spring:mvc:view:prefix: /jsp/suffix: .jsp2.手动在src->main->下面创建webapp文件夹3.在Springboot 启动类加入如下代码:Beanpublic InternalResourceViewResolver setupViewResolver() {InternalResourceV…

c primer英文版第5版_2019足坛10大巨星:梅西第2范戴克第3,C罗第5

点击“关注”获得更多更新更有趣的足坛资讯!2019年的足坛英雄辈出、岁月激荡。阿贾克斯的青年军两回合力克尤文闯进欧冠四强,梅西梅开二度难救主,巴萨遗憾止步欧冠半决赛,利物浦横扫欧陆,无奈联赛杯赛统统被国内曼城压…

python三维图能画地图_Python地图绘制实操详解

网上有很多地图绘制的教程,更多趋向于全国地图或者省级地图,但有时我们需要到县级。闲得慌,今天以贵州省毕节市为例,分享一篇Python县级地图的绘制(遥想当时差点把百度翻了个底朝天),希望对需要…

ajax juey,锋利的qjuey-ajax

jquery 中的ajaxload方法主要获取web服务器上静态数据1 load方法载入HTML文档load(url [,data] [,callback])$(function(){$("#send").click(function(){$("#resText").load("test.html")})})View Code2 筛选载入的HTML文档$("#resText&quo…

java读取pem格式私钥_openssl生成RSA格式及pkcs1与pkcs8格式互相转换

openssl简介OpenSSL 是一个开源项目,其组成主要包括以下三个组件:openssl:多用途的命令行工具libcrypto:加密算法库libssl:加密模块应用库,实现了ssl及tlsopenssl可以实现:密钥证书管理、对称加…

sql服务器文件夹共享,sqlserver2017共享功能目录路径不可改的解决方法

注意:什么路径不可改就搜索该路径进行删除注册表记录,然后重启电脑按 win键盘R输入 regedit 进去注册表,点击计算机按“编辑”--》查找下一个需要等一些时间结果出来后把搜到的结果的项删除删除之后 按F3继续查找下一个进行删除,…

tt协议号服务器,TTIot: TTIoT云端物联网Iot组件;面向JAVA;netty;mqtt;异步推送;以事件为驱动;为设备提供安全可靠的连接通信能力;...

TTIoT云端物联网组件;面向JAVA;以事件为驱动;为设备提供安全可靠的连接通信能力TTIoT简介TTIOT的Broker采用MQTT协议与设备进行交互,可以应用在数据采集、能源监控、智能生活、智能工业、农业水利等场景;向下提供连接海量设备服务,支撑设备数据采集上云,…

javamail发送html正文文件_Python实现-生成测试报告amp;自动邮件发送

之前单独介绍了生成测试报告和自动发送邮件,那么现在把两者整合到一起;生成测试报告后然后自动发送邮件,这里只是简单的整合实现功能,其实还可以优化的,先用吧,后面再慢慢优化先看下目录,其实目…

byte转换为string乱码_每日一课 | 如何将int转换为String

在Python中&#xff0c;我们可以使用str()将int转换为String。num1 100print(type(num1)) # int> num2 str(num1) print(type(num2)) # str>输出量<class int><class str>参考文献&#xff1a;Python文档– str()Python –如何将String转换为int翻译自: ht…

openssh升级后root_又一root神器停止营业!时至今日你还需要root吗

[PConline杂谈]最近&#xff0c;一条新闻引起了安卓玩家们的注意——360超级root宣布停止运营。在此前&#xff0c;也已经有其他知名root工具和玩家们渐行渐远&#xff0c;例如SuperSu开发者宣布停止开发所有root应用。除了root工具停止开发&#xff0c;root机在用户群中的热度…

dijkstra算法代码_深度好文:改变了我们生活方式最有影响力的5种图算法

作者&#xff1a;Rahul Agarwal编译&#xff1a;刘静图灵联邦编辑部出品本文作者Rahul Agarwal是一位数据科学家&#xff0c;近期&#xff0c;他在Medium上分享了常用的5种图算法的介绍和代码实现。以下是具体博文内容&#xff1a;作为数据科学家&#xff0c;我们已经对Pandas或…

laravel5.6 使用指定字段作为key_MyRocks TTL使用姿势及Bugfix

一些业务场景是经过一段时间后删除过期的数据&#xff0c;MyRocks提供了TTL可以满足该场景。MyRocks 通过Compaction回收过期的数据。本文介绍MyRocks TTL使用姿势以及Bugfix。TTL 通过 table comment 定义&#xff0c;有两种形式&#xff1a;CREATE TABLE t1 (a INT, b INT, c…

mybatis更新时间字段_你以为把Mybatis型处理器了解了,就不会“暴雷”了!

1. 明确需求在设计之初&#xff0c;sys_role表的enabled字段有2个可选值&#xff0c;其中0 代表禁用&#xff0c;1代表启用&#xff0c;而且实体类中我们使用的是Interger类型&#xff1a;/*** 有效标志*/ private Integer enabled;public Integer getEnabled() {return enable…

本地更新github项目_GitHub开源项目2019-03-29更新精选

1.etcd&#xff1a;一个高可用的分布式键值数据库&#xff0c;k8s 全家桶标配的注册与发现服务etcd&#xff1a;一个高可用的分布式键值数据库&#xff0c;k8s 全家桶标配的注册与发现服务。它采用 raft 一致性算法&#xff0c;基于 Go 语言实现。可以通过该项目了解、学习 raf…

maven default aliyun_大家看看大佬对Maven仓库的讲解,有何高明之处?

概念Maven在某个统一的位置存储所有项目的共享的构件&#xff0c;这个统一的位置&#xff0c;我们就称之为仓库。(仓库就是存放依赖和插件的地方)。分类maven的仓库只有两大类&#xff1a;1.本地仓库 2.远程仓库&#xff0c;在远程仓库中又分成了3种&#xff1a;中央仓库、 私服…