文章目录

  • 什么是服务发现
    • 信息孤岛问题
    • Http通信
    • 微服务与Rpc框架
      • Dubbo2.0中的接口级服务发现
  • 应用级服务发现
    • 兼容性设计
    • Rpc元数据同步机制
  • 性能表现
  • 参考资料

什么是服务发现

信息孤岛问题

计算机诞生之初,往往信息系统都是以单机的形式存在,系统与系统交互较少,存在信息孤岛问题,数据的交换得通过硬件设备的拷贝、人工在不同系统之间进行拷贝(硬盘、U盘等)。随着互联网的兴起,任何一个系统都难以在互联网浪潮中“独善其身”,不同服务、系统之间往往存在信息互通的需求,比如浏览淘宝网是用户的电脑请求淘宝网的服务器获得相关商品信息,淘宝内部的服务器之间也存在信息互通的需求,比如订单服务器可能要去请求用户中心服务获取下单用户的数据,通过网络交换数据显然比通过线下硬件复制拷贝来的方便的多。

这里我们把通信方式交互图最简化,请求资源一方为客户端,接受请求并返回资源一方为服务端

发展至今,不同系统之间通信的方式有很多,比如HTTP、TCP、UDP、以及各类RPC框架(Dubbo、gRpc、SpringCloud、Motan、HSF、Tars)等

Http通信

HTTP是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP)
通常,由HTTP客户端发起一个请求,创建一个到服务器指定端口(默认是80端口)的TCP连接。HTTP服务器则在那个端口监听客户端的请求。一旦收到请求,服务器会向客户端返回一个状态,比如"HTTP/1.1 200 OK",以及返回的内容,如请求的文件、错误消息、或者其它信息


在接口不多、系统与系统交互较少的情况下,Http协议通信的优点就是简单、直接、开发方便。当然其缺点也比较明显,也就是客户端需要指定服务端的地址(即ip和端口)

试想如果某个服务器上有N(N比较大)个接口,如果客户端要接入这些接口,那么服务端的相关开发人员必然需要提供一些离线文档来描述这些接口的入参及调用方式,因此如果请求接口比较多,对这份接口文档的维护成本也是不可忽略的

大家都知道,现实中任何一个机器都存着故障的可能,如果哪一天该服务器故障了,那么所有的客户端都无法正常请求到正常的资源。因此也就诞生出了服务端集群部署、请求负载均衡的机制,来避免单点故障的发生。Nginx就是这样一种反向代理软件,能够将用户的所有HTTP请求均衡(通过一定的负载均衡机制)的分配到每一台应用机器上,以此来避免单点故障对整体服务产生影响


如果所示就是典型的一种基于Nginx的网络通信交互实现,可以看到此时客户端直接请求的是Nginx服务器的ip和端口(当然大部分请求下请求的是域名,此处只为简单描述),通过在Nginx服务器的配置文件里配置N个WEB应用服务的ip和端口和负载均衡策略来达到请求分发的目的。

这个方案看似挺美的,但考虑如下场景

  1. 随着业务发展,发现3台服务不够承载流量了,需要扩展到4台,那么此时首先得把服务部署到第四台机器上,同时还得修改Nginx服务器上的路由配置,加入第四台机器的ip端口,Nginx并不能自动感知到你部署了第四个机器
  2. 如果你有N个服务,你可能需要维护N个Nginx服务配置文件,维护成本随着应用服务增加线性增加

因此:Nginx服务配置文件的维护成本不可忽略。服务发现的背景也是基于此,在应用服务器的数量、地址不断变化、存在上下线的情况下,如何对调用客户端、甚至开发者屏蔽掉这些服务端变化的细节,显得尤为重要

回过头来想,类似Nginx的配置对于开发者来说显得有些累赘,更是一些偏运维层面的东西,随着后续微服务和Rpc框架的发展,就演化出了动态服务发现的能力,在框架层面去动态感知服务实例的变化

微服务与Rpc框架

在使用微服务构建复杂的分布式系统时,如何感知服务实例的动态上下线,也是微服务框架最需要关心并解决的问题之一。业界将这个问题称之为 - 微服务的地址发现(Service Discovery),业界比较有代表性的微服务框架如 SpringCloud、Dubbo 等都抽象了强大的动态地址发现能力

这些框架通常会引入一个注册中心的组件来实现传递服务提供者的ip、端口信息,如图所示

而不同Rpc框架实现间最主要的区别就体现在注册中心数据的组织:地址如何组织、以什么粒度组织、除地址外还同步哪些数据。下面以Dubbo为例说明

Dubbo2.0中的接口级服务发现

提供者启动时向注册中心注册服务地址,消费者启动时订阅服务,并通过获取到的提供者地址发起调用,当提供者地址变更时,通过注册中心向消费者推送变更,如下图所示,提供者将自己的ip、port、以及接口信息全量注册到了注册中心,消费者通过注册中心拿到对应接口的提供者信息来发起调用,这就是 dubbo 中服务地址发现主要的工作流程

同时回过头来想,为什么现在很多公司采用dubbo做为Rpc服务框架,就是因为Dubbo在底层利用代理机制对开发者屏蔽了很多实现细节,而服务发现注册机制即使其中一种,同时屏蔽了服务调用时的负载均衡及失败容错机制

在测试环境,我以Dubbo服务A为例(ZK为注册中心),A中暴露了N个服务接口,同时在2台机器10.190.40.217、10.190.9.129上部署,此时zk上的注册信息如下

可以看到,每一个接口都对应了一个地址目录,同时每一个地址目录下又会有Provider注册信息和Consumer消费者信息。

这里大家有可能会问:为什么同一个ip同一个接口会有两条注册信息,即如图所示,这是因为该接口使用了dubbo的group特性暴露了2次,不同group提供给不同的业务方使用,来达到一个不同业务调用接口集群隔离的目的,因此zk中注册信息会有2份

从这两个图片里也就可以得出两个结论

  1. dubbo往注册中心写入的provider注册数据量级与提供者的应用实例数成正比,同时也与业务接口量级成正比
  2. 以接口为单位的服务地址注册方式冗余了大量提供者的ip、port信息

同时,这也是接口级服务地址发现的一个重要缺点,随着实例数的膨胀和应用接口数的不断变多,应用服务向注册中心推送/拉取地址的压力会变大,而且接口数量与业务变化相关,随着业务发展,接口数量可能会不断变多,这种变化通常不在运维人员可控范围内,运维人员无法很好的评估应用服务所面临的地址推送/拉取压力

当然从dubbo发展角度来讲,dubbo也需要更多的与springCloud、k8s等主流服务地址发现体系对齐,后面两者的服务地址发现时抽象方法比较接近,即只关注服务实例(应用级别)的注册与发现,接口信息这种更多的是业务层面的东西,理论不应交由注册中心来存储业务接口信息

应用级服务发现

应用级服务发现,顾名思义,注册中心中只存储提供者的ip、port等应用实例级别的数据,如图所示

接口级别注册发现,在注册中心中以 RPC 服务为 key,以实例列表作为 value 来组织数据的,而新引入的“应用粒度的服务发现”,它以应用名(Application)作为 key,以这个应用部署的一组实例(Instance)列表作为 value

应用级服务发现中 Provider不再向注册中心中写入Rpc接口信息,这里就会引入两个问题

  1. 兼容性问题:接口级服务发现中消费者可以根据接口全路径找到对应的服务提供者ip、port从而发起调用,此时注册中心中接口信息没了,只有应用和ip、port的映射关系,如何平滑的做到接口级发现向应用级发现的迁移是个问题
  2. 消费者此时不知道提供者有哪些接口了,如何建立 Consumer 与 Provider 间的自动化 RPC 服务元数据协调机制也是一个问题

兼容性设计

在不改变任何 Dubbo 配置的情况下,可以将一个应用或实例升级到 3.x 版本,升级后的 Dubbo 实例会默保保证与 2.x 版本的兼容性,即会正常注册 2.x 格式的地址到注册中心,同时新的地址发现模型(注册应用级别的地址)也将会自动注册。

Dubbo3.0中的注册行为默认是双注册

服务提供者端Provider可以通过如下方式修改注册行为

dubbo.application.register-mode=all
// 可选值 interface、instance、all,默认是 all,即接口级地址、应用级地址都注册

同时消费端默认的订阅行为是双订阅

对于 3.x 的消费者,它具备同时发现 2.x 与 3.x 提供者地址列表的能力。在默认情况下,如果集群中存在可以消费的 3.x 的地址,将自动消费 3.x 的地址,如果不存在新地址则自动消费 2.x 的地址。Dubbo3 提供了开关来控制这个行为:

dubbo.application.service-discovery.migration=APPLICATION_FIRST
# 可选值
# FORCE_INTERFACE,只消费接口级地址,如无地址则报错,单订阅 2.x 地址
# APPLICATION_FIRST,智能决策接口级/应用级地址,双订阅
# FORCE_APPLICATION,只消费应用级地址,如无地址则报错,单订阅 3.x 地址

Rpc元数据同步机制

Dubbo官方文档中针对该问题的解决提到了“服务自省机制”,按简单点理解,就是服务的提供者和消费者自行协商解决接口级别元信息的同步问题

如果采用了应用级别的服务发现和服务注册,在注册中心中将采用“应用 – 实例列表”结构的数据组织形式,不再是以往的“接口 – 实例列表”结构的数据组织形式,而以往用接口级别的服务注册和服务发现的应用服务在迁移到应用级别时,得不到接口与应用之间的对应关系,从而无法从注册中心得到实例列表信息,所以Dubbo为了兼容这种场景,在Provider端启动时,会往元数据中心存储接口与应用的映射关系,在Dubbo中会默认将注册中心同时作为配置中心和元数据中心,这是Dubbo的默认行为

如果所示,dubbo将service(接口)与app(应用)的映射关系也维护在了元数据中心中,这样一来,消费者就可以通过接口(service)去找到应用(app),在去注册中心根据应用找到对应的provider实例ip、port

当然直接在消费端引用接口时,直接指定应用名也是一种方法。

性能表现

Dubbo3.0的应用级表现有效降低了服务发现模型中的内存占用,同时GC次数也有一定下降,具体性能表现查看性能测试报告

https://dubbo.apache.org/zh/docs/performance/benchmarking/

参考资料

Dubbo3 应用级服务发现
应用级地址发现迁移指南
基准测试

聊聊Dubbo3.0新特性之应用级服务发现相关推荐

  1. WCF4.0新特性体验(6):路由服务Routing Service(下)

    紧接前文WCF4.0新特性体验(5):路由服务Routing Service(上).今天我们介绍WCF4.0消息路由的实现机制,然后会讲解路由服务的实现过程. [4]WCF与路由服务: 其实在介绍WC ...

  2. 【收藏】C# 2.03.0新特性总结

    c#2.0新特性 范型 我们知道通用的数据结构可以采用object存储任何数据类型.使用object问题是: 显示的强制转带来的代码复杂性 换装箱拆箱的性能损失(为什么有性能损失?因为涉及动态内存分配 ...

  3. hadoop3.0新特性介绍

    hadoop3.0新特性介绍 1. 基于jdk1.8(最低版本要求) 2. mr采用基于内存的计算,提升性能(快spark 10倍) 3. hdfs 通过最近black块计算,加快数据获取速度(块大小 ...

  4. Dubbo 3.0新特性记录

    前言 Dubbo更新了3.0版本,博主抱着好奇的心态一睹芳华.最终的感受就是dubbo3.0针对之前版本的问题进行了一系列的改造和提升.且Dubbo3.0的特性有些还在开发当中.一些已经提供的功能也尚 ...

  5. Android5.0,6.0,7.0,8.0新特性整理

    背景 Android5.0(Android Lollipop)是谷歌公司2014年10月发布的全新安卓系统,至今已经两年多.然而由于国产手机对安卓ROM的深度定制或修改,以及手机厂商.芯片制造商.运营 ...

  6. Android5.0,6.0,7.0新特性整理

    背景 Android5.0(Android Lollipop)是谷歌公司2014年10月发布的全新安卓系统,至今已经两年多.然而由于国产手机对安卓ROM的深度定制或修改,以及手机厂商.芯片制造商.运营 ...

  7. Android5.0 6.0 7.0新特性

    原文链接:http://blog.csdn.net/haovip123/article/details/54618642 背景 Android5.0(Android Lollipop)是谷歌公司201 ...

  8. Java基础加强-(注解,动态代理,类加载器,servlet3.0新特性)

    1.   Annotation注解 1.1.  Annotation概述 Annotation是JDK 5.0以后提供对元数据的支持,可以在编译.加载和运行时被读取,并执行相应的处理.所谓Annota ...

  9. Portlet 2.0 新特性介绍(全)

    第一部分 Portlet 2.0 新特性介绍 ====================================================================== 关于本系列 ...

最新文章

  1. 马来西亚拟对打车软件巨头Grab罚款2000万美元
  2. json - 使用 json-lib
  3. 干货笔记|三分钟让你掌握360高级副总裁的产品之道
  4. lda 吗 样本中心化 需要_机器学习 —— 基础整理(四):特征提取之线性方法——主成分分析PCA、独立成分分析ICA、线性判别分析LDA...
  5. vue怎么给html元素加类选择器,Vue.js——获取Dom对象的类选择器名(className)
  6. ROS2学习(七).ROS概念 - ROS客户端库(Ros Client Library)
  7. Android SDK Manager 在win8.1上的闪退问题【转载】
  8. 尚学堂java答案解析 第三章
  9. nodejs express 学习
  10. Exchange Server 2007邮箱存储服务器的容量规划和性能调优(下)
  11. java.util.BitSet 研究
  12. 百度网站诚信认证现在是个什么情况呢?
  13. java读文件写文件
  14. 数据预处理--无量纲化
  15. TesterHome创始人思寒:如何从手工测试进阶自动化测试?十余年经验分享
  16. PAT1003 我要通过! (20 分)(C语言)
  17. 关于anchor的解释
  18. 皮卡车行业调研报告 - 市场现状分析与发展前景预测
  19. c语言读取midi文件举例子,c# – 使用NAudio从MIDI文件中读取音符
  20. npm login报错:npm notice Beginning October 4, 2021, all connections to the npm registry.......

热门文章

  1. 解决调试时候出现的“Encountered an improper argument”错误
  2. Informatica PowerCenter 简介(一)
  3. Clearing Floats清除浮动--clearfix的不同方法的使用概述
  4. Java初学者作业——为某超市设计管理系统,需要在控制台展示系统菜单,菜单之间可以完成跳转。
  5. android根据url加载图片路径,初学Android——通过URL加载图片
  6. sin和soi区别_FinFET和FD SOI的比较?
  7. umap算法_科学网—[转载]【源码】均匀流形近似与投影(UMAP)算法仿真 - 刘春静的博文...
  8. 安卓端哔哩哔哩下载文件存储处
  9. 惠普电脑收购货源Autonomy此起彼伏前质疑声
  10. I'm up to my ears