dubbo k8s 服务发现_工商银行基于 Dubbo 构建金融微服务架构的实践-服务发现篇

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

352de293125e47ce574c16621aba0e75.png

背景及概览

工行传统的业务系统一般都是基于 JEE 的单体架构,面对金融业务线上化及多样化的发展趋势,传统架构已经无法满足业务的需求。因此从 2014 年开始,工行选择了一个业务系统做服务化的尝试,并验证、评估、对比了当时的几个分布式服务框架,最终选择了相对完善、并且国内已经有较多公司落地使用的 Dubbo。与此同时,工行还对 Dubbo 做了企业定制,帮助这个业务系统完成了服务化的落地,上线之后也收到了非常好的效果。

2015 年,工行开始扩大服务架构的落地范围,一方面帮助传统业务系统进行架构转型,另一方面也逐渐沉淀了类似中台的超大规模服务群组,支撑业务系统快速服务的组合和复用。随着经验积累,工行也不断对 Dubbo 进行迭代优化和企业定制,同时围绕服务也逐步打造了完善的服务生态体系。

2019 年,工行的微服务体系也正式升级为工行开放平台核心银行系统的关键能力之一,助力工行 IT 架构实现真正的分布式转型。

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

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

最大的挑战

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

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

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

服务发现难点和优化

1. 入门

37398e2965503bc72e89e5dd1940f48d.png

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

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

de6af5e4588ee9193b5f0234178780ec.png

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

  • providers 临时节点:记录该服务提供者清单。提供方下线子节点就自动删除,通过 Zookeeper 的 watch 机制,消费者可以第一时间知道提供者清单发生了变化。
  • consumers 临时节点:记录消费者的清单,主要用于服务治理时查询消费者。
  • configurations 持久节点:主要保存服务治理时需要调整的服务参数。
  • routers:子节点为持久节点,主要用于配置服务的动态路由策略。

15569cbdcd62c42ddda57dfe64c7a490.png

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

  • 分流网络压力:随着服务节点的增多,如果客户端都连接选举节点,对选举节点来说需要消耗大量的 CPU 去处理网络连接和请求。但是选举节点又无法任意水平扩容,选举节点越多,事务投票过程就越长,对高并发写性能是不利的。
  • 降低跨城跨 DC 的注册订阅流量:当有 100 个消费者需要跨城订阅同一个服务,Observer 可以统一处理这部分跨城网络流量,避免对城际间的网络带宽带来压力。
  • 客户端隔离:可以将几个 Observer 节点专门分配给某个重点应用使用,保障其网络流量隔离。

2. 问题分析

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

5dc06515ee1ce3bc4be973d1da101f59.png
  • 随着服务数量以及服务提供者节点的增加,服务推送的数据量会呈爆炸式增长。举个例子,一个服务有 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)订阅延迟更新

24736691f145f85e636f955ed1e60f48.png

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

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

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

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

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

2)Multiple 模式

5e62f03fe367540ea40ef121af3aa653.png

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

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

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

并且,multiple 注册中心机制也用于异构的注册中心场景,出现问题可以随时把注册中心下线,这个过程对服务节点的服务调用则完全透明,比较适合灰度试点或者应急切换。

更进一步,还有额外的收益,消费者端 Reference 对象是比较占用 JVM 内存,通过 multiple 注册中心模式,可以帮消费者端节省一半的 invoker 对象开销,因此,非常推荐多个注册中心场景采用 multiple 模式。

3)按节点注册

d121d3cda0385a7e0185a95eaf6704b9.png

工行反向移植 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 架构,目前已经有初步的方案,但还有非常多的技术难关需要克服。

作者:张远征
原文链接

本文为阿里云原创内容,未经允许不得转载

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

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

相关文章

初识ABP vNext(12):模块的独立运行与托管

点击上方蓝字"小黑在哪里"关注我吧模块运行动态 C# API 客户端前言很久没更新这个系列。。。之前的章节中讲到ABP的模块是可以独立运行的,但是没有介绍具体怎么操作,本篇就来讨论一下模块如何独立运行,以及一些托管方式。本人也是处…

后端学习 - Spring5

文章目录一 简介二 IOC1 底层原理2 实现过程3 Spring 实现 IOC 的两个接口二 Bean1 普通 Bean 与 FactoryBean2 Bean 单例与否的设置3 Bean 的生命周期三 IOC 的 Bean 管理(XML)1 创建对象2 属性注入 - 使用 set 方法3 属性注入 - 通过有参构造器实现3 注…

吐槽一下Abp的用户和租户管理模块

1. 背景ASP.NET Core 基于声明的访问控制到底是什么鬼?聊到基于声明的身份认证将 身份和签发机构分离,应用程序信任签发机构,故认可签发的身份信息。-----------ClaimB站:438962688 Name:饭思思_weibo:538210234 Name:饭思思van姓名:不详 籍贯…

后端学习 - JDBC

文章目录一 JDBC概述1 Java中的数据存储技术2 什么是JDBC3 JDBC程序的编写步骤二 Java连接数据库的方式三 使用 PreparedStatement 实现 CRUD 操作1 数据库的调用的三个接口2 增Create/删Delete/改Update 操作3 查Retrieval操作4 批量插入操作四 数据库事务1 事务2 事务的 ACID…

后端学习 - JavaWeb

技术体系 文章目录一 HTML1 网页的组成部分2 HTML 概述3 HTML 标签4 常用标签5 表单与表单的提交二 CSS1 语法格式2 使用方法三 JavaScript1 概述2 与 HTML 结合的两种方式3 变量类型及特殊值4 关系、逻辑运算5 数组6 函数7 事件8 DOM (Document Object Model&#…

心想技术驱动业务,却在背道而驰

这里是Z哥的个人公众号每周五11:45 按时送达当然了,也会时不时加个餐~我的第「165」篇原创敬上大家好,我是Z哥。相信每一位真正的程序员心里都有这样一个念想:只要我的技术够牛,就能驱动业务的发展。但是往…

后端学习 - SpringMVC

文章目录一 SpringMVC 简介1 MVC2 SpringMVC3 创建第一个 SpringMVC 项目二 RequestMapping1 注解类与方法的区别2 value 属性3 method 属性4 params 属性5 headers 属性6 SpringMVC 支持路径中的占位符三 获取 Request 的一系列参数1 通过控制器方法的形参2 控制器方法形参 映…

hbase shell远程连接_hbase与phoenix集成

Phoenix是构建在HBase之上的关系型数据库层,作为内嵌的客户端JDBC驱动用以对HBase中的数据进行低延迟访问Phoenix会将用户编写的sql查询编译为一系列的scan操作,最终产生通用的JDBC结果集返回给客户端Phoenix可以看成是mysql准备安装包apache-phoenix-4.…

对精致码农大佬的 [理解 volatile 关键字] 文章结论的思考和寻找真相

一:背景1. 讲故事昨天在园里的编辑头条看到 精致码农大佬 写的一篇题为:[C#.NET 拾遗补漏]10:理解 volatile 关键字 (https://www.cnblogs.com/willick/p/13889006.html) 的文章,大概就是说在 多线程环境下,一个在debu…

后端学习 - SpringBoot

SpringBoot 是整合 Spring 技术栈的一站式框架,是简化 Spring 技术栈的快速开发脚手架约定大于配置 文章目录一 概述1 第一个 SpringBoot 项目2 SpringBoot 特性:依赖管理3 SpringBoot 特性:自动配置二 SpringBoot 的 IOC容器1 组件添加&…

centos rpm 安装 perl_Linux【常用软件安装篇】

摘要:本文介绍Linux常用的软件安装方式以及jdk、vim、mysql、tomcat、redis的安装过程。1 Linux常用软件安装方式常用方式有:rmp包安装、yum指令安装、源码包安装、解压免安装。1.1 rpm包安装rpm是Red-Hat Package Manager(RPM软件包管理器&a…

日计不足涓滴成河-自定义响应结果格式化器

什么是响应结果响应结果就是,在客户端向服务器发出请求后,服务器根据客户端的请求参数,给出的结果,这就是一个完整的响应结果过程。响应的结果包含的内容非常多,主要的有 HTTP Status Code,Content-Type,Co…

docker 容器启动顺序_Docker容器启动时初始化Mysql数据库

1. 前言 Docker在开发中使用的越来越多了,最近搞了一个Spring Boot应用,为了方便部署将Mysql也放在Docker中运行。那么怎么初始化 SQL脚本以及数据呢? 我这里有两个传统方案。 第一种方案是在容器启动后手动导入,太low了不行。第二…

后端学习 - JVM(上)内存与垃圾回收

JVM 架构图 文章目录一 JVM 简介二 类加载子系统:1 作用2 类的三个加载过程3 类加载器的分类4 双亲委派机制 & Tomcat为何不遵循5 两个 class 对象为同一个类的必要条件三 运行时数据区:PC寄存器(Program Counter Register)四…

SM2 国密算法被 Linux 内核社区接受

喜欢就关注我们吧!10 月 25 日,有开发者发文称,SM2 国密算法终于被 Linux 内核社区接受了。该作者表示,SM2 的补丁已经更新到了 v7 版本,这个版本的补丁最终被社区接受,目前已经合并到了 Linux 主线的 5.10…

后端学习 - MyBatis

MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的 持久层框架 文章目录一 基于配置文件的 MyBatis 搭建1 搭建过程(增删改)2 查询操作3 特殊操作二 MyBatis 获取参数值的方式1 单个字面量类型的参数2 多个字面量类型的参数3 Map 类型的参数4 实体…

国产操作系统发展离不开人才和市场

日前,中国 1024 程序员节盛大举行,一大批开源大咖齐聚千年岳麓,围绕开源标准、生态、人才发展等主题分享,共议开源软件与操作系统未来。其中,统信软件总经理刘闻欢表示,“有了市场才会被真正的用起来”&…

后端学习 - Redis

文章目录一 Redis 概述Redis 为什么是单线程,单线程为什么这么快?数据存储结构二 常用数据类型1 String2 HashHash 的扩容机制:渐进式 rehash*3 List4 Set5 Zset三 Redis 事务1 乐观锁与 watch 命令2 事务的三个特性四 Redis 持久化1 RDB(Red…

再被补刀!Flash又遭抛弃,你会怀念它吗?

喜欢就关注我们吧!微软近日发布通知,称更新了关于 Adobe Flash Player 的删除。微软更新目录站点可下载更新 KB4577586,用于删除 Flash Player。此更新适用于所有受支持的操作系统版本。重要版本 Windows 10 和 Windows 8.1 的可选更新也将在…

4位加法器的设计代码verilog_HDLBits:在线学习Verilog(六 · Problem 25-29)

本系列文章将和读者一起巡礼数字逻辑在线学习网站 HDLBits 的教程与习题,并附上解答和一些作者个人的理解,相信无论是想 7 分钟精通 Verilog,还是对 Verilog 和数电知识查漏补缺的同学,都能从中有所收获。附上传送门:M…