关于云原生-cloud-native:工商银行基于-Dubbo-构建金融微服务架构的实践服务发现篇

33次阅读

共计 5021 个字符,预计需要花费 13 分钟才能阅读完成。

作者 | 张远征
起源 |阿里巴巴云原生公众号

导读:Dubbo 作为散布式微服务框架,泛滥公司在实践中基于 Dubbo 进行分布式系统架构。重启开源后,咱们不仅看到 Dubbo 3.0 最新的 Roadmap 公布,而且还看到阿里在本身电商开始推动 Dubbo 和外部 HSF 的交融,并在 双 11 上开始应用 Dubbo 3.0。本文是工商银行基于 Dubbo 构建金融微服务架构的分享,次要讲述了服务发现的应答策略和成绩,后续将公布工行大规模服务监控治理的实际,以及从企业角度怎么去对 Dubbo 二次开发等内容。欢送关注。

背景及概览

工行传统的业务零碎个别都是基于 JEE 的单体架构,面对金融业务线上化及多样化的发展趋势,传统架构曾经无奈满足业务的需要。因而从 2014 年开始,工行抉择了一个业务零碎做服务化的尝试,并验证、评估、比照了过后的几个分布式服务框架,最终抉择了绝对欠缺、并且国内曾经有较多公司落地应用的 Dubbo。与此同时,工行还对 Dubbo 做了企业定制,帮忙这个业务零碎实现了服务化的落地,上线之后也收到了十分好的成果。

2015 年,工行开始扩充服务架构的落地范畴,一方面帮忙传统业务零碎进行架构转型,另一方面也逐步积淀了相似中台的超大规模服务群组,撑持业务零碎疾速服务的组合和复用。随着教训积攒,工行也一直对 Dubbo 进行迭代优化和企业定制,同时围绕服务也逐渐打造了欠缺的服务生态体系。

2019 年,工行的微服务体系也正式降级为工行开放平台外围银行零碎的要害能力之一,助力工行 IT 架构实现真正的分布式转型。

工行的微服务体系组成如下图所示:

  • 基础设施方面,不论是业务零碎的服务节点,还是微服务平台本身的工作节点,都已部署在工行的云平台。
  • 服务注册发现方面,除了惯例的服务注册核心外,还配合部署了元数据中心,用于实现服务的按节点注册发现。
  • 服务配置方面,通过内部的分布式配置核心,以实现各类动静参数的对立治理和下发。
  • 服务监控方面,实现对服务各类运行指标的对立采集和存储,并与企业的监控平台对接。
  • 服务跟踪方面,次要是用于实时跟踪服务的整体链路,帮忙业务零碎疾速定位故障点,并精确评估故障的影响范畴。
  • 服务网关是为了满足传统业务零碎拜访服务需要,在 Dubbo 服务订阅及 RPC 能力之上,实现了新服务、新版本的主动发现、主动订阅和协定转换能力(HTTP 协定转 RPC 协定),实现 7×24 小时不间断运行。
  • 服务治理平台,提供给运维人员和开发测试人员一个一站式的治理、监控、查问的平台,晋升日常服务治理的效率。

最大的挑战

通过工行多年的落地实际,本文共总结了以下两方面的最大挑战:

  • 性能容量方面,目前线上服务数(即 Dubbo 概念中的服务接口数),已超 2 万,每个注册核心上的提供者条目数(即每个服务的所有提供者累计),已超 70 万。依据评估,将来须要能撑持 10 万级别的服务数,以及每个注册核心 500 万级的提供者条目数。
  • 高可用方面,工行的指标是:微服务平台任何节点故障都不能影响线上交易。银行的业务零碎 7×24 小时运行,即便在版本投产工夫窗内,各业务零碎的投产工夫也是互相错开的,平台本身节点要做降级,如何防止对线上交易带来影响,特地是注册核心的本身的版本更新。

本文将先从服务发现方面,来分享一下工行的应答策略及功效。

服务发现难点和优化

1. 入门

在 Dubbo 中,服务的注册订阅及调用是一个规范范式,服务的提供者初始化时注册服务,服务消费者初始化时订阅服务并获取全量提供者列表。而运行期间,服务提供者发生变化时,服务消费者可获取最新的提供者列表。消费者与提供者之间点对点 RPC 调用,调用过程不经注册核心。

在注册核心的抉择上,工行在 2014 年就抉择了 Zookeeper。Zookeeper 在业界的各类场景下有大规模的利用,并且反对集群化部署,节点间数据一致性通过 CP 模式保障。

在 Zookeeper 外部,Dubbo 会按服务建设不同的节点,每个服务节点下又有 providers、consumers、configurations 及 routers 四个字节点:

  • providers 长期节点:记录该服务提供者清单。提供方下线子节点就主动删除,通过 Zookeeper 的 watch 机制,消费者能够第一工夫晓得提供者清单产生了变动。
  • consumers 长期节点:记录消费者的清单,次要用于服务治理时查问消费者。
  • configurations 长久节点:次要保留服务治理时须要调整的服务参数。
  • routers:子节点为长久节点,次要用于配置服务的动静路由策略。

在线上生产环境,Zookeeper 分数据中心部署了多个集群,每个集群配置了 5 个选举节点,若干个 Observer 节点。Observer 节点是 Zookeeper3.3.3 版本引入的一个新的节点类型,它不参加选举,只听取表决后果,其余能力则和 Follower 节点雷同。Observer 节点有以下几方面的益处:

  • 分流网络压力:随着服务节点的增多,如果客户端都连贯选举节点,对选举节点来说须要耗费大量的 CPU 去解决网络连接和申请。然而选举节点又无奈任意程度扩容,选举节点越多,事务投票过程就越长,对高并发写性能是不利的。
  • 升高跨城跨 DC 的注册订阅流量:当有 100 个消费者须要跨城订阅同一个服务,Observer 能够对立解决这部分跨城网络流量,防止对城际间的网络带宽带来压力。
  • 客户端隔离:能够将几个 Observer 节点专门调配给某个重点利用应用,保障其网络流量隔离。

2. 问题剖析

工行依据这几年线上 Zookeeper 的应用心酸血泪史,总结了 Zookeeper 在作为服务注册核心时面临的问题:

  • 随着服务数量以及服务提供者节点的减少,服务推送的数据量会呈爆炸式增长。举个例子,一个服务有 100 个提供者,当提供者启动的时候,因为 Zookeeper 的 CP 个性,每上线一个提供者,消费者都会收到事件告诉,并从 Zookeeper 来读取这个服务的以后全副提供者的列表,而后刷新本地缓存。这个场景下,实践上每个消费者总共收到了 100 次事件告诉,并从 Zookeeper 读取了 100 次服务提供者列表,1+2+3+…+100,总计 5050 条提供者数据。这在业务零碎投产高峰期问题尤为突出,容易导致 Zookeeper 集群的网络被打满,造成服务订阅效率极其低下,并进一步影响了服务注册的性能。
  • 随着写在 Zookeeper 上节点数量的增多,Zookeeper 的 snapshot 文件也一直变大,每次 snapshot 写入磁盘,会呈现一次磁盘 IO 冲高。投产高峰期,因为事务量大,写 snapshot 文件的频率也十分高,这对基础设施带来了较大的危险。同时 snapshot 文件越大,也预示着 Zookeeper 节点故障后复原的工夫越长。
  • 当 Zookeeper 选举节点产生从新选举后,Observer 节点都要从新的 Leader 节点同步全量事务,这个阶段如果耗时过长,就很容易导致连贯在 Observer 节点上的客户端 session 超时,使对应 providers 节点下的长期节点全副被删除,即从注册核心角度看,这些服务都下线了,消费者端则呈现无提供方的异样报错。紧接着,这些提供者会从新连贯 Zookeeper 并从新注册服务,这种短时间内大批量服务的注册翻转景象,往往带来更为严重的服务注册推送的性能问题。

综上,能够得出的论断是:总体上 Zookeeper 作为注册核心还是比拟称职的,但在更大规模服务量场景下,须要进一步优化。

3. 优化计划

工行最次要的优化措施包含上面这几方面:订阅提早更新、注册核心采取 multiple 模式、降级到按节点注册等。

1)订阅提早更新

工行对 Zookeeper 客户端组件 zkclient 做了优化,把消费者收到事件告诉后获取提供者列表做了一个小的延时。

当 zkclient 收到 childchange 一次性的事件后,installWatch() 通过 EventThread 去复原对节点的监听,同时又应用 getChildren() 去读取节点下的全副子节点获取提供者列表,并刷新本地服务提供者缓存。这就是后面说的“5050 条数据”问题的本源。

工行在 zkclient 收到 childchange() 的事件后,做了个期待提早,再让 installWatch() 去做它原来该做的事件。这个期待过程中如果服务提供者发生变化,则不产生 childchange 事件。

有人会问,这是不是违反了 zookeeper 的 CP 模型呢,其实并不是,zookeeper 服务端的数据是强统一的,消费者也收到了事件告诉,只是延后去读取提供者清单,前面执行 getChildren() 时,读取到的曾经是 zookeeper 上的最新数据,所以是没有问题的。

外部压测结果显示,服务提供者大规模上线时,优化前,每个消费者收到了总计 422 万个提供者节点的数据量,而提早 1 秒解决后,这个数据量则变成了 26 万,childchange 事件次数和网络流量都变成了原来的 5% 左右,做完这个优化,就能从容应对投产高峰期大量服务的高低线。

2)Multiple 模式

工行驳回并优化革新了 Dubbo 新版本中 registry-multiple 的 SPI 实现,用于优化多注册核心场景下的服务订阅。

Dubbo 中服务消费者原有解决逻辑是这样:当存在多个注册核心的时候,消费者按注册核心对应的 invoker 缓存去筛选提供方,第一个注册核心对应的缓存中如果没找到,则去找第二个注册核心对应的缓存。如果此时第一个注册核心呈现可用性问题,推送给消费者的数据有缺失,甚至为空,就会影响消费者的这个筛选过程,如呈现无提供方的异样、调用负载不平衡等。

而 multiple 注册核心是把多个注册核心推送的数据合并后再更新缓存,所以即便单个注册核心故障,推送了数据不残缺或者为空,只有有其余任意一个注册核心的数据使残缺的,就不会影响最初合并的数据。

并且,multiple 注册核心机制也用于异构的注册核心场景,呈现问题能够随时把注册核心下线,这个过程对服务节点的服务调用则齐全通明,比拟适宜灰度试点或者应急切换。

更进一步,还有额定的收益,消费者端 Reference 对象是比拟占用 JVM 内存,通过 multiple 注册核心模式,能够帮消费者端节俭一半的 invoker 对象开销,因而,十分举荐多个注册核心场景采纳 multiple 模式。

3)按节点注册

工行反向移植 Dubbo2.7 及 Dubbo3.0 的服务发现逻辑,应用“按节点注册”的服务注册 - 发现模型。这里即配置核心、元数据中心、注册核心这个铁三角组合:

  • 配置核心:次要用来存储节点级别的动静参数,以及服务的原来写在 Zookeeper 上的 configurations 和 routers 这些长久节点的数据。
  • 元数据中心:存储节点元数据,也就是每个服务节点名称(也就是 applicaiton-name)和其提供的服务的映射关系,以及每个服务的类定义信息,比方每个办法的输入输出参数信息。
  • 注册核心:此时注册核心则只须要存储服务提供者节点名称和理论 ip 端口的关系。

这个模型的变动,对于消费者的服务调用则没有任何影响。消费者端依据元数据中心上“服务节点名称”与“服务”的关系,以及注册核心“服务节点名称”与理论 ip 端口的关系,生成兼容存量模式的服务提供方 invoker 缓存。

压测结果显示,按节点注册能够让注册核心上的数据量变成原来的 1.68%,这对量就对线上的 Zookeeper 来说毫无压力,10 万级别的服务量和 10 万级别的节点量都可能轻松撑持。

将来的布局

将来,工行也心愿能有机会走进来,深度参加到社区中,把本身在 Dubbo、Zookeeper 服务端、zkclient 上的好的 feature 奉献进去,比方除了下面的优化点外,工行还在 Dubbo 上做了 RPC 后果的精细化辨认,PAAS 的适配,同端口多协定、自隔离等能力,还在 Zookeeper 上减少了注册熔断机制,同时正在钻研 Observer 的同步机制防止数据全量同步带来的一系列问题。

另外,从微服务的倒退看,Mesh 曾经是目前的热点之一。工行的痛点次要在服务 SDK 版本升级上,Istio 不争气,MCP 生死未卜,如何能让存量 Dubbo 服务平滑过渡到 MESH 架构,目前曾经有初步的计划,但还有十分多的技术难关须要克服。

欢送 Dubbo 有实际的同学们一起来探讨大规模场景下的问题和心得,独特把 Dubbo 的企业落地做的更好!

更多企业落地实际内容,可下载云原生架构白皮书理解详情!

正文完
 0