小白也能看懂的dubbo3应用级服务发现详解

捉虫大师
• 阅读 2145

搜索关注微信公众号"捉虫大师",后端技术分享,架构设计、性能优化、源码阅读、问题排查、踩坑实践。

本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。

dubbo 是一款开源的 RPC 框架,主要有3个角色: 提供者(provider)消费者(consumer)注册中心(registry)

小白也能看懂的dubbo3应用级服务发现详解

提供者启动时向注册中心注册服务地址,消费者启动时订阅服务,并通过获取到的提供者地址发起调用,当提供者地址变更时,通过注册中心向消费者推送变更。这就是 dubbo 主要的工作流程。

在2.7.5之前,dubbo 只支持接口级服务发现模型,>=2.7.5的版本提供了接口级与应用级两种服务发现模型,3.0之后的版本应用级服务发现更是非常重要的一个功能。

本文将从为什么需要引入应用级服务发现,dubbo 实现应用级服务发现的难点以及dubbo3 是如何解决这些问题这三个部分进行讲解。

开始前,我们先了解下 dubbo 最初提供的接口级服务发现是怎样的。

接口级服务发现长啥样?

dubbo 服务的注册发现是以接口为最小粒度的,在 dubbo 中将其抽象为一个URL,大概长这样:

dubbo://10.1.1.123:20880/org.newboo.basic.api.MyDemoService?anyhost=true&application=ddog-my-demo&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.newboo.basic.api.MyDemoService&methods=setUser,getUser&owner=roshilikang&release=2.7.6&side=provider&threads=500

看着很乱?捋一捋:

小白也能看懂的dubbo3应用级服务发现详解

  • 协议代表提供服务的协议,如果注册了 grpc 服务,这里就是 grpc://

  • ipport 代表是哪台机器的哪个端口提供服务

  • interface 代表了注册的接口名,它直接对应到代码中需要暴露服务的 interface,如下:

package org.newboo.basic.api;

import org.newboo.basic.model.User;

public interface MyDemoService {
    void setUser(User user);
    User getUser(String uid);
}
  • 参数代表了服务的一些参数,可能是元数据,也可能是配置信息

细心的你一定发现了,一个 interface 可以包含多个 dubbo 接口,所以把它称为接口级服务发现有些不妥,应该是服务级服务发现,但服务的定义比较模糊,可能会被误认为是应用,甚至后面介绍的 dubbo 应用级服务发现使用的关键字也是 service,所以我们用接口级这个更加易懂的概念来代替。

接口级服务发现有什么问题?

数据太多

无论是存储还是变更推送压力都可能遇到瓶颈,数据多表现在这两个方面:

  • 注册的单条数据太大

这个问题好解决:拆!

dubbo 在 2.7 之后的版本支持了元数据中心配置中心,对于URL的参数进行分类存储。持久不变的(如application、method等)参数存储到元数据中心中,可能在运行时变化(timeout、tag)的存储到配置中心中

小白也能看懂的dubbo3应用级服务发现详解

  • 注册数据条数太多

小白也能看懂的dubbo3应用级服务发现详解

无论是增加一台机器还是增加一个接口,其增长都是线性的,这个问题比单条数据大更严重。

当抹去注册信息中的 interface 信息,这样数据量就大大减少

小白也能看懂的dubbo3应用级服务发现详解

非主流

只用过 dubbo 的同学可能觉得这很主流。

但从服务发现的角度来看:

无论是用的最多的服务注册发现系统 DNS,又或者是 SpringCloud 体系、K8S 体系,都是以应用为维度进行服务注册发现的,只有和这些体系对齐,才能更好地与之进行打通。

在我了解的范围里,目前只有 dubboSOFARPCHSF 三个阿里系的 RPC 框架支持了接口级的服务发现。

接口级服务发现如何使用

provider端暴露服务:

<dubbo:registry address="zookeeper://127.0.0.1:2181"/>

<dubbo:service interface="org.newboo.basic.api.MyDemoService" ref="myNewbooDemoService"/>

consumer端引用服务:

<dubbo:registry address="zookeeper://127.0.0.1:2181"/>

<dubbo:reference id="myNewbooDemoService" interface="org.newboo.basic.api.MyDemoService"/>

小白也能看懂的dubbo3应用级服务发现详解

本地调用远程的方法时,只需要配置一个 reference,然后直接使用 interface 来调用,我们不必去实现这个 interaface,dubbo 自动帮我们生成了一个代理进行 RPC 调用,屏蔽了通信的细节,让我们有种像调用本地方法一样调用远程方法的感觉,这也是 dubbo 的优势。

从这里我们能看出为什么 dubbo 要设计成接口级服务发现,因为要为每一个 interface 生成一个代理,就必须定位到该 interface 对应服务暴露的服务地址,为了方便,dubbo 就这么设计了。

如果要实现应用级服务发现你会怎么做?

如果让我来设计应用级服务发现,注册不必多说,按应用名注册即可。

但这里有个隐藏问题是应用名的唯一性,应用名必须得很好的管理起来,否则重复、随意改动都可能导致服务发现失效

至于订阅,在目前 dubbo 机制下,必须得告诉消费者消费的每个接口是属于哪个应用,这样才能定位到接口部署在哪里。

难点是什么

实现 dubbo 应用级服务发现,难点在于

  • 兼容性,除了服务发现,其他改动点尽量少,且能兼容接口级到应用级的过渡
  • 接口到应用的部署关系,在接口级服务发现中,是不需要关心接口部署在哪个应用上的,但换做应用级,必须得知道这点,但这点就增加了开发者的使用难度,有没有方案尽量屏蔽细节?

小白也能看懂的dubbo3应用级服务发现详解

dubbo3 是如何解决这些问题的?

兼容性

保留接口级服务发现,且默认采取双注册方式,可配置使用哪种服务发现模型,如下配置使用应用级服务发现

<dubbo:registry address="zookeeper://127.0.0.1:2181?registry-type=service"/>

居然使用了service这个关键字😅

如何查找接口对应的应用

  • 方案1:手动配置,实现简单,架构简单,但用户使用成本高,这种方式 dubbo3 已支持
<dubbo:service services="ddog-my-demo-p0" interface="org.newboo.basic.api.MyDemoService" ref="myNewbooDemoService"/>
  • 方案2:服务自省

名词有点高大上,但道理很简单,让 dubbo 自己去匹配,提供者注册的时候把接口和应用名的映射关系存储起来,消费者消费时根据接口名获取到部署的应用名,再去做服务发现。

数据存储在哪里?显然元数据中心非常合适。该方案用户使用起来和之前接口级没有任何不同,但需要增加一个元数据中心,架构变得复杂。

且有一个问题是,如果接口在多个应用下部署了,dubbo 查找的策略是都去订阅,这可能在某些场景下不太合适。

小白也能看懂的dubbo3应用级服务发现详解

最后

本文从接口级服务发现讲到应用级服务发现,包含了为什么 dubbo 设计成接口级服务发现,接口级服务发现有什么痛点?基于 dubbo 现状如何设计应用级服务发现,应用级服务发现实现有什么难点等等问题进行解答,相信看完的小伙伴一定有所收获。


小白也能看懂的dubbo3应用级服务发现详解

点赞
收藏
评论区
推荐文章
捉虫大师 捉虫大师
2年前
大厂偏爱的Agent技术究竟是个啥
搜索关注微信公众号"捉虫大师",后端技术分享,架构设计、性能优化、源码阅读、问题排查、踩坑实践。hello大家好,我是小楼,今天给大家分享一个关于Agent技术的话题,也是后端启示录的第3篇文章。通过本文你可以了解到如下内容:什么是Agent技术为了解释什么是Agent技术,我在网上搜了一圈,但没有找到想要的结果。反倒是搜到了不少JavaAgent技术,
捉虫大师 捉虫大师
3年前
dubbo 2.7应用级服务发现踩坑小记
本文已收录https://github.com/lkxiaolou/lkxiaolou欢迎star。背景本文记录最近一位读者反馈的dubbo2.7.x中应用级服务发现的问题,关于dubbo应用级服务发现的相关介绍可以参考之前的文章,这里不再赘述。读者反馈他们在基于dubbo2.7应用级服务发现开发dubbo网关,根据文章《dubbo应用级服务发现初
捉虫大师 捉虫大师
3年前
给dubbo贡献源码,做梦都在修bug
本文已收录https://github.com/lkxiaolou/lkxiaolou欢迎star。一在之前的文章《redis在微服务领域的贡献》中,从一次面试经历中了解了redis可以在微服务中玩的这么溜,同时也从源码角度分析了dubbo的redis注册中心。最后得出了dubbo的redis注册中心不能用于生产的结论,其中原因有如下两点:使用了ke
捉虫大师 捉虫大师
3年前
zookeeper到nacos的迁移实践
本文已收录https://github.com/lkxiaolou/lkxiaolou欢迎star。技术选型公司的RPC框架是dubbo,配合使用的服务发现组件一直是zookeeper,长久以来也没什么大问题。至于为什么要考虑换掉zookeeper,并不是因为它的性能瓶颈,而是考虑往云原生方向演进。云原生计算基金会(CNCF)对云原生的定义是:云原生
捉虫大师 捉虫大师
3年前
rocketmq优雅停机往事
本文已收录https://github.com/lkxiaolou/lkxiaolou欢迎star。关于作者:滴滴中间件开发工程师,微信公众号"捉虫大师"。1时间追溯到2018年12月的某一天夜晚,那天我正准备上线一个需求完就回家,刚点下发布按钮,告警就响起,我擦,难道回不了家了?看着报错量只有一两个,断定只是偶发,稳住不要慌。把剩下的机器发完,又出
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
捉虫大师 捉虫大师
3年前
从nacos客户端的TIME_WAIT说起
本文已收录https://github.com/lkxiaolou/lkxiaolou欢迎star。问题起因前段时间调研nacos,用来代替zookeeper当作dubbo的注册中心,使用的是nacos的1.1.4版本。还用了nacosSync,一款nacos提供的迁移工具,可将常见的注册中心上的服务同步到nacos上。这玩意很不好用,至少不是生产级别
捉虫大师 捉虫大师
3年前
当我们谈注册中心时我们谈什么
本文已收录https://github.com/lkxiaolou/lkxiaolou欢迎star。最近工作重心转向了注册中心,于是想来写一篇关于注册中心的文章概念什么是注册中心,以大多数人熟悉的RPC框架来说,通常RPC中有三种角色:provider服务提供者consumer服务消费者,即调用方registry注册中心,让consumer
捉虫大师 捉虫大师
3年前
Cobar提出的一种在分库场景下对Order By / Limit 的优化
搜索关注微信公众号"捉虫大师",后端技术分享,架构设计、性能优化、源码阅读、问题排查、踩坑实践。本文已收录https://github.com/lkxiaolou/lkxiaolou欢迎star。Cobar虽然是一款“古老”的数据库中间件,但目前不少公司仍然在用它,且它包含了不少有意思的算法和实现,今天就来分享Cobar提出的一种在分库场景下对
捉虫大师 捉虫大师
3年前
案例分享 | dubbo 2.7.12 bug导致线上故障
本文已收录https://github.com/lkxiaolou/lkxiaolou欢迎star。搜索关注微信公众号"捉虫大师",后端技术分享,架构设计、性能优化、源码阅读、问题排查、踩坑实践。背景最近某天的深夜,刚洗完澡就接到业务方打来电话,说他们的dubbo服务出故障了,要我协助排查一下。电话里,询问了他们几点是线上有损故障吗?——是止损