当前位置:首页 > 科技  > 软件

我试图通过这篇文章告诉你,什么是神奇的泛化调用。

来源: 责编: 时间:2023-11-30 09:26:53 147观看
导读你好呀,我是歪歪。关于 RPC 调用,大家肯定都是比较熟悉的了,就是在微服务架构下解决系统间通信问题的一个玩意。其中的典型代表之一就是 Dubbo 了:图片在微服务架构下,我们针对某个 RPC 接口,我们一般有两个角色。服务消费

你好呀,我是歪歪。soX28资讯网——每日最新资讯28at.com

关于 RPC 调用,大家肯定都是比较熟悉的了,就是在微服务架构下解决系统间通信问题的一个玩意。soX28资讯网——每日最新资讯28at.com

其中的典型代表之一就是 Dubbo 了:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

在微服务架构下,我们针对某个 RPC 接口,我们一般有两个角色。soX28资讯网——每日最新资讯28at.com

  • 服务消费者 (Dubbo Consumer),发起业务调用或 RPC 通信的 Dubbo 进程
  • 服务提供者 (Dubbo Provider),接收业务调用或 RPC 通信的 Dubbo 进程

假设我是服务消费者,想要调用某个服务,只要我们链接到的是同一个服务注册中心,那么找对应服务要到 API 包对应的 Maven 坐标,引入到项目中,就类似于这样的东西:soX28资讯网——每日最新资讯28at.com

<dependency>    <groupId>org.apache.dubbo</groupId>    <artifactId>dubbo-spring-boot-demo-interface</artifactId>    <version>${project.parent.version}</version></dependency>

那么对于这个 API 包中的接口,虽然我们没有具体的实现类,但是我们还是能像调用本地方法一样调用该服务提供的接口。soX28资讯网——每日最新资讯28at.com

这些都是常规的东西了,你肯定是门清。soX28资讯网——每日最新资讯28at.com

那我现在问你一个问题啊:soX28资讯网——每日最新资讯28at.com

我是服务消费者,我要调用一个服务提供者的 RPC 接口,但是我又不想引入它的 API 包,或者我根本就拉取不到它的 API 包,那么我应该怎么办?soX28资讯网——每日最新资讯28at.com

如果你要非给我说:这不可能,既然是要消费别人的接口,那么肯定要拿到 API 包才对,你不拿就是你偷懒。soX28资讯网——每日最新资讯28at.com

那我再给你举个歪师傅在实际开发过程中遇到的具体的例子:网关服务。soX28资讯网——每日最新资讯28at.com

网关是个什么玩意?soX28资讯网——每日最新资讯28at.com

是你对外请求的统一入口,做接受请求、分发请求用的,作为链接各个微服务的角色,你势必要使用到下游的若干个 RPC 服务。soX28资讯网——每日最新资讯28at.com

你怎么办?soX28资讯网——每日最新资讯28at.com

引入所有的服务提供方的 API 包,然后发起调用吗?soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

可以是可以,但是不够优雅。soX28资讯网——每日最新资讯28at.com

你想,如果有一个服务提供方发布了新的 API 包,你也需要更新版本,重新发版?soX28资讯网——每日最新资讯28at.com

或者新来一个服务提供者 E,你需要引入其 API 包,然后重新发版?soX28资讯网——每日最新资讯28at.com

网关应该是一个稳定的基础服务,它提供的是聚拢 API 接口、转发调用的基础功能,不应该频繁发版,不应该主动去关注下游的服务接口变化。平台本身不应该依赖于服务提供方的接口 API。soX28资讯网——每日最新资讯28at.com

不主动,才能更加优雅,也能让自己更加轻松。soX28资讯网——每日最新资讯28at.com

那么怎么才能做到不主动关注呢?soX28资讯网——每日最新资讯28at.com

这个事情,总有一方要主动的,所以网关层不主动,那么服务提供者就需要主动起来。soX28资讯网——每日最新资讯28at.com

我们可以搞成这样:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

网关层提供一个 API 接口发布平台,当服务提供者的接口有新增或者发生变化的时候,由对应系统的接口管理人员把接口信息,比如接口路径、方法、入参、出参、方法功能说明、方法负责团队、接口对接人等等这些消息维护到 API 接口发布平台上。soX28资讯网——每日最新资讯28at.com

这样网关层就可以从 API 接口发布平台获取到所有服务的所有接口,并不需要引入任何服务提供者的 API 包。soX28资讯网——每日最新资讯28at.com

这样就解决了“主动”的问题,如果接口有变化,请在 API 接口发布平台进行登记,从而解决了网关频繁发布的问题。soX28资讯网——每日最新资讯28at.com

在官网上,除了网关的场景外,还提到一个测试平台的场景,道理是一样的,我就不赘述了:soX28资讯网——每日最新资讯28at.com

https://cn.dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/generic-reference/soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

解决了“主动”的问题,那么下一个问题就随之而来了:知道所有服务的所有接口然后呢,怎么发起调用呢?soX28资讯网——每日最新资讯28at.com

这个时候泛化调用,啪的一下就站出来了:铺垫了这么多,终于该老子上场了。soX28资讯网——每日最新资讯28at.com

泛化调用

啥是泛化调用呢?soX28资讯网——每日最新资讯28at.com

在 Dubbo 官网上是这样介绍的:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

首先需要强调的是“泛化调用”不是 Dubbo 特有的,它是一个功能,很多的框架都支持泛化调用,只是我这里用的 Dubbo 做演示而已。soX28资讯网——每日最新资讯28at.com

老规矩,先花五分钟时间搭个 Demo 出来再说。soX28资讯网——每日最新资讯28at.com

这个 Demo 我也是跟着网上的 quick start 搞的:soX28资讯网——每日最新资讯28at.com

https://cn.dubbo.apache.org/zh-cn/overview/quickstart/java/spring-boot/soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

可以说写的非常详细了,你就跟着官网的步骤一步步的搞就行了。soX28资讯网——每日最新资讯28at.com

我这个 Demo 稍微不一样的是我在消费者模块里面搞了一个 Http 接口:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

在接口里面发起了 RPC 调用,模拟从前端页面发起请求的场景,更加符合我们的开发习惯。soX28资讯网——每日最新资讯28at.com

为了起到强调作用,我再次把这个部分给你框起来:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

DemoService 是 RPC 接口,它的实现类是这样的:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

在我的消费者模块里面为什么能注入这个 DemoService 并调用它的 sayHello 方法呢?soX28资讯网——每日最新资讯28at.com

因为我引入了对应的依赖包。soX28资讯网——每日最新资讯28at.com

那么,如果我把这个依赖包去掉,也就是模拟我们前面说的“不主动”的动作,这个 DemoService 肯定会报错,找不到这个类:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

那么我们应该怎么去修改一下这个 Demo,让它泛化起来呢?soX28资讯网——每日最新资讯28at.com

非常简单:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

注入 DemoService 修改为注入 GenericService。soX28资讯网——每日最新资讯28at.com

有的小伙伴可能会问 GenericService 是怎么冒出来的?soX28资讯网——每日最新资讯28at.com

你先别管它是怎么冒出来的,我现在是在给你铺垫 Demo,后面要撕给你看。你现在只需要知道它是 Dubbo 框架里面的包,并不会让你引用额外的包就行了:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

现在 Demo 就算是搭好了,本地启动一个 zk,然后把服务提供者启动起来,再把消费者启动起来,最后轻轻的发起一个调用:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

朋友,它不就跑起来了吗?soX28资讯网——每日最新资讯28at.com

我没有引用接口的 api 包,我不也正常发起了调用,然后拿到了返回值吗?soX28资讯网——每日最新资讯28at.com

啥原理

你就想,远程调用,你把一些花里胡哨的东西都拿掉之后,它的本质是什么?soX28资讯网——每日最新资讯28at.com

本质就是帮助解决微服务组件之间的通信问题,不管是基于  HTTP、HTTP/2、TCP 还是什么其他的通信协议,解决的是网络连接管理、数据传输等基础问题。soX28资讯网——每日最新资讯28at.com

虽然我没有引用 API 的对应的包,但是我前面我不是说了吗,我们有一个 API 接口发布平台,这个平台里面有接口维护人员提供的接口路径、方法、入参、出参这些关键信息。soX28资讯网——每日最新资讯28at.com

所以我在调用的时候可以拿到相关的信息,以一种通用的方式,比如字符串的方式告诉 RPC 框架,我要调用的是 DemoService 接口的 sayHello 方法,入参是 String 类型的 world 字符串:soX28资讯网——每日最新资讯28at.com

如果是你来开发一个 RPC 框架,调用方都把这些关键信息给你了,无非就是你帮忙多做几步类似于反射、序列化之类的处理。而处理的这个过程,就是泛化调用的过程。soX28资讯网——每日最新资讯28at.com

泛化调用不是 Dubbo 特有的,但是具体到 Dubbo 这个框架里面,具体是这样的。soX28资讯网——每日最新资讯28at.com

首先,Dubbo 里面有一层 Filter,这些 Filter 构成了一个 Filter 链条:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

Filter 用来对每次服务调用做一些预处理、后处理动作,使用 Filter 可以完成访问日志、加解密、流量统计、参数验证等任务。soX28资讯网——每日最新资讯28at.com

一次请求过程中可以植入多个 Filter,Filter 之间相互独立没有依赖。soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

从消费端视角,它在请求发起前基于请求参数等做一些预处理工作,在接收到响应后,对响应结果做一些后置处理。soX28资讯网——每日最新资讯28at.com

从提供者视角,在接收到访问请求后,在返回响应结果前做一些预处理。soX28资讯网——每日最新资讯28at.com

所以我们的泛化调用,也是通过下面这两个 Filter 来搞事情的:soX28资讯网——每日最新资讯28at.com

  • org.apache.dubbo.rpc.filter.GenericFilter
  • org.apache.dubbo.rpc.filter.GenericImplFilter

那么问题就来了?soX28资讯网——每日最新资讯28at.com

为什么要两个 Filter 呢?soX28资讯网——每日最新资讯28at.com

因为要完成一次泛化调用,消费端和服务提供者都需要感知到并做相关的处理,所以一个是消费端的 Fliter,一个是服务提供者的 Fliter:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

知道了对应的 Filter,关于泛化调用的所有秘密都藏在 Filter 对应的源码里面。soX28资讯网——每日最新资讯28at.com

歪师傅带着你简单的看一眼。soX28资讯网——每日最新资讯28at.com

GenericImplFilter.invoke

首先,我们在方法的消费者对应的 Fliter 的入口处打上断点:soX28资讯网——每日最新资讯28at.com

org.apache.dubbo.rpc.filter.GenericImplFilter#invokesoX28资讯网——每日最新资讯28at.com

可以看到分为了三个模块。soX28资讯网——每日最新资讯28at.com

  • isCallingGenericImpl:calling a generic impl service,判断是否调用的是一个实现了泛化接口的接口。
  • isMakingGenericCall:making a generic call to a normal service,把泛化调用转换为一个常规调用。
  • invoker.invoke(invocation):常规调用。

我们研究的情况属于 isMakingGenericCall 这个分支。soX28资讯网——每日最新资讯28at.com

既然是要把泛化调用转换为一个常规调用,那么 Dubbo 是怎么判断这是一个泛化调用的呢?soX28资讯网——每日最新资讯28at.com

org.apache.dubbo.rpc.filter.GenericImplFilter#isMakingGenericCallsoX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

  • 判断本次调用的方法名称是否是 或者invokeAsync
  • 判断本次调用的入参个数是否是 3 个
  • 判断容器上下文中的 generic 参数是否对应着泛化调用的序列化方法。

我们一个个的看。soX28资讯网——每日最新资讯28at.com

或者invokeAsync 方法是 GenericService 这个接口里面的方法。而这两个方法的入参个数都是三个。soX28资讯网——每日最新资讯28at.com

然后有个 generic 参数,在我的 Demo 里面这个参数是 true:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

当我啪的一下跟进到 isGeneric 方法中,才发现这里面别有洞天:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

原来 generic 这个参数不只是可以为 “true”,它不同的值,代表着不同的序列化方式。soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

通过这部分源码可以看出来,泛化调用对于客户端,即在 GenericImplFilter 里面,并没有做什么特别的操作,注意还是参数校验。soX28资讯网——每日最新资讯28at.com

如果入参和对应的序列化方法不能匹配起来,即使的抛出异常,这样符合 Dubbo 框架的 fast-fail 思想。soX28资讯网——每日最新资讯28at.com

但是其实看到这里的时候,我有一个小疑问,如果我写一个这样的类:soX28资讯网——每日最新资讯28at.com

public interface WhyService {    Object $invoke(String a,String b,String c);}

和 GenericService 类一样,有 $invoke 方法,而且也是三个参数。soX28资讯网——每日最新资讯28at.com

然后在上下文中塞个 generic=true 进去,那么是不是也能骗过这段代码呢,也能进入到 isMakingGenericCall 方法里面呢?soX28资讯网——每日最新资讯28at.com

从代码上看确实是这样的,那么 Dubbo 到底是怎么规避这些“恶意”冒充者的呢?soX28资讯网——每日最新资讯28at.com

我也不知道。soX28资讯网——每日最新资讯28at.com

先存个疑吧,接着往下看。soX28资讯网——每日最新资讯28at.com

GenericFilter.invoke

我们同样在服务端打上断点,当这个请求来到服务端的时候,我们再看看服务端的情况。soX28资讯网——每日最新资讯28at.com

org.apache.dubbo.rpc.filter.GenericFilter#invokesoX28资讯网——每日最新资讯28at.com

可以看到这个方法逻辑都在 if 判断为 true 的时候。soX28资讯网——每日最新资讯28at.com

而这个判断我们刚刚在客户端已经解析过了,只是多了一个判断:soX28资讯网——每日最新资讯28at.com

!GenericService.class.isAssignableFrom(invoker.getInterface())soX28资讯网——每日最新资讯28at.com

看看发起调用的接口类是不是 GenericService 类的子类,如果是,则进入到 if 分支里面。soX28资讯网——每日最新资讯28at.com

朋友,这就有点意思了。几秒钟之前我们还在存疑,然后啪的一下疑问就解开了。soX28资讯网——每日最新资讯28at.com

直接就是恍然大悟了。soX28资讯网——每日最新资讯28at.com

我这个类:soX28资讯网——每日最新资讯28at.com

public interface WhyService {    Object $invoke(String a,String b,String c);}

过不了服务提供者的 GenericFilter 里面的这个判断:soX28资讯网——每日最新资讯28at.com

!GenericService.class.isAssignableFrom(invoker.getInterface())soX28资讯网——每日最新资讯28at.com

在 invoke 方法里面,可以看到经过了一个 findMethodByMethodSignature 方法,获取了我们想要调用的 method 方法:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

这个方法,从名字上也可以看出,是根据方法签名反射出具体的方法:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

在服务端,是有 DemoService 接口对应的类的,所以可以通过反射找到它。soX28资讯网——每日最新资讯28at.com

然后再解析出入参的具体值:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

这样你就有了构建一个 RpcInvocation 对象,即发起 RPC 调用的对象的所有关键消息。soX28资讯网——每日最新资讯28at.com

直接就是发动一招“狸猫换太子”的大动作,重新构建一个 RpcInvocation 对象,然后自己发起一个 invoke 调用。soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

这样整体看起来似乎一次泛化调用也是很简单的,当你去看服务提供端的源码的时候,你会发现这里面的源码特别多。soX28资讯网——每日最新资讯28at.com

不过是因为 Dubbo 支持了多种不同的序列化方式而已,本质是一样的:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

onResponse 方法也是同理,就不赘述了:soX28资讯网——每日最新资讯28at.com

org.apache.dubbo.rpc.filter.GenericFilter#onResponsesoX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

到这里就算是扯下了泛化调用的神秘面纱,和我们预想的一样,无非是拿到接口调用的关键信息之后,重新构建一个请求而已,整体逻辑并不复杂。soX28资讯网——每日最新资讯28at.com

复杂的逻辑是什么?soX28资讯网——每日最新资讯28at.com

我演示的是最简单的,入参是一个 String 类型的情况。如果我是一个复杂对象呢,对象里面的成员变量特别多,对象里面套对象,对象里面有 List 或者 Map 的情况呢?soX28资讯网——每日最新资讯28at.com

复杂的地方在于怎么处理这些复杂对象,把复杂对象搞成服务提供者的 Java 对象入参。soX28资讯网——每日最新资讯28at.com

我这里只是一个导读而已,如果你对这部分有兴趣的话,自己搞个复杂对象去研究研究吧,老有意思了。soX28资讯网——每日最新资讯28at.com

就当是家庭作业了。soX28资讯网——每日最新资讯28at.com

意外收获

歪师傅在扯面纱的时候,没想到还有意外收获。soX28资讯网——每日最新资讯28at.com

给你看一段代码,也是前面出现过的一个方法,我把完整的代码都截图放出来:soX28资讯网——每日最新资讯28at.com

org.apache.dubbo.common.utils.ReflectUtils#findMethodByMethodSignaturesoX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

你瞅瞅我框起来部分的 signature 字段,是不是没有任何卵用?soX28资讯网——每日最新资讯28at.com

自信一点,不要怀疑,确实没有任何用处,signature 只是赋了个值而已,后续的代码中并没有使用。soX28资讯网——每日最新资讯28at.com

所以,我小脑瓜子一转,立刻察觉到这又是一个水 pr 的好机会。soX28资讯网——每日最新资讯28at.com

于是...soX28资讯网——每日最新资讯28at.com

https://github.com/apache/dubbo/pull/13382soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

晚上 10 点半的时候,直接就是一个贡献源码的大动作,小手一挥,带走四行代码:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

当时我没细想,但是后来躺在床上的时候我突然想起来:不应该啊,这个地方为什么会留着几行看起来是没有删除不干净的代码呢?soX28资讯网——每日最新资讯28at.com

隐隐觉得这里面应该是有故事的。soX28资讯网——每日最新资讯28at.com

于是看了这个类的提交记录,主要找两个地方:这个 signature 是什么时候有的,又是什么时候没的。soX28资讯网——每日最新资讯28at.com

在 2012 年 6 月 15 日,针对这个类做了一次性能优化:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

优化的具体内容就是用 Map 把方法缓存起来,以免每次都需要去走反射的逻辑。soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

看完这个提交之后我觉得很合理啊,使用 Map 缓存一下确实属于性能优化。soX28资讯网——每日最新资讯28at.com

那么为什么又把这个 Map 拿走了呢?soX28资讯网——每日最新资讯28at.com

于是我在 2021 年 9 月 6 日的提交中找到了拿走 Map 对应的提交记录:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

这次提交的内容非常的多,而从提交记录的 log 中并没有找到为什么要移除这个 Map 的原因:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

怎么办?soX28资讯网——每日最新资讯28at.com

很简单,社区提问就行了。soX28资讯网——每日最新资讯28at.com

于是我在我的 pr 下面抛出了自己的问题:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

我查看了该类的提交历史,发现 #8684 删除了 ReflectUtils.java 中的所有 Map 缓存,遗留了对 signature  字段的处理。
但是我不明白为什么要删除缓存,在我看来应该保留缓存。能说一下官方是怎么考虑的吗?soX28资讯网——每日最新资讯28at.com

很快我就得到了官方的回复:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

删除缓存的原因是因为这些 Map 缓存是全局变量,这会导致从 Dubbo 的类(通常是 GC root)到对应类的引用,而这些类在 ClassLoader 被闲置后无法释放。soX28资讯网——每日最新资讯28at.com

啥意思呢?soX28资讯网——每日最新资讯28at.com

我大概的解释一下。soX28资讯网——每日最新资讯28at.com

首先,我们看一下这个 Map 的定义是怎么样的:soX28资讯网——每日最新资讯28at.com

private static final ConcurrentMap<String, Method> SIGNATURE_METHODS_CACHE = new ConcurrentHashMap<String, Method>();soX28资讯网——每日最新资讯28at.com

它是个 static 对象,那么它是不是会被作为一个 GC root?soX28资讯网——每日最新资讯28at.com

如果它作为一个 GC root,它里面缓存的这些方法,是不是都是“可达的”?soX28资讯网——每日最新资讯28at.com

方法是可达的,那么这些方法对应的 Class 类是不是也是“可达的”?soX28资讯网——每日最新资讯28at.com

但是在这些方法对应的 Class 类的 ClassLoader 完成自己的使命,被回收之后,那么这个 Class 类是不是理论上也可以被回收了?soX28资讯网——每日最新资讯28at.com

但是实际情况是什么呢?soX28资讯网——每日最新资讯28at.com

实际情况是因为这个 static 对象还持有其引用,导致它不会被回收。soX28资讯网——每日最新资讯28at.com

基于这个考虑,官方决定移除这个 Map。soX28资讯网——每日最新资讯28at.com

其实我个人觉得,如果我上面的理解没有错的话,那么讨论这个 Map 的效果,可以得两个分情况:soX28资讯网——每日最新资讯28at.com

如果一个泛化调用的调用频率非常低,那么你把对应的方法缓存起来,导致 GC 一直回收不了,确实没啥意思。soX28资讯网——每日最新资讯28at.com

如果一个泛化调用的调用频率比较高,那么你把对应的方法缓存起来,确实能起到“性能优化”的效果。soX28资讯网——每日最新资讯28at.com

那么 Dubbo 作为一个框架怎么知道你的这个方法调用的频率高不高呢?soX28资讯网——每日最新资讯28at.com

它也不知道,所以干脆不要替用户多做这一步,做多了,反而容易出错。soX28资讯网——每日最新资讯28at.com

其实它也是可以知道的,比如可以提供一个参数给用户进行配置,把选择权给到用户,让用户通过配置来告诉你。甚至它可以不用用户提供信息,可以自己来做数据收集,来评判这个方法是否应该被缓存起来。soX28资讯网——每日最新资讯28at.com

但是,这玩意收益也不高啊。soX28资讯网——每日最新资讯28at.com

本来泛化调用就不是 RPC 调用里面非常核心的东西,在这上面搞这么多心思,投入产出比不高啊。soX28资讯网——每日最新资讯28at.com

有这时间,还不如想想主链路上还有没有什么地方可以优化优化,在主链路上干事情,才是收益最大的事情。soX28资讯网——每日最新资讯28at.com

就像是你在公司里面,在边缘部门里面干得再出色,也很少能让人注意到。但是如果你在核心部门里面,做出一点稍微亮眼的成绩,大家都能看到。soX28资讯网——每日最新资讯28at.com

所以,你以为你敲的只是代码吗?soX28资讯网——每日最新资讯28at.com

不是的,你敲的,是人情世故。soX28资讯网——每日最新资讯28at.com

最后,这个 pr 也合并到源码中去了,再次查看这个类的提交记录,你会发现一个熟悉的名称:soX28资讯网——每日最新资讯28at.com

图片图片soX28资讯网——每日最新资讯28at.com

说真的,删除这三行代码没有任何技术含量,这部分代码让任何一个有 Java 基础的人来看,都会发现这个问题。soX28资讯网——每日最新资讯28at.com

我不过是在调试源码的过程中捡了个漏而已。soX28资讯网——每日最新资讯28at.com

但是为什么这部分代码存在了很久时间了,是我捡到了这个漏呢?soX28资讯网——每日最新资讯28at.com

我想,大概是我真的搭了个 Demo 然后一行行的跟了一下源码吧。soX28资讯网——每日最新资讯28at.com

所以,朋友,别只是看,要动手,说不定有意外收获。soX28资讯网——每日最新资讯28at.com

好了,价值也上完了,本文的技术部分就到这里啦。soX28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-35273-0.html我试图通过这篇文章告诉你,什么是神奇的泛化调用。

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: Python的三元表达式,你知道吗?

下一篇: CSS:这几个伪类,你用了吗

标签:
  • 热门焦点
  • 一加Ace2 Pro官宣:普及16G内存 引领24G

    一加Ace2 Pro官宣:普及16G内存 引领24G

    一加官方今天继续为本月发布的新机一加Ace2 Pro带来预热,公布了内存方面的信息。“淘汰 8GB ,12GB 起步,16GB 普及,24GB 引领,还有呢?#一加Ace2Pro#,2023 年 8 月,敬请期待。”同时
  • 俄罗斯:将审查iPhone等外国公司设备 保数据安全

    俄罗斯:将审查iPhone等外国公司设备 保数据安全

    iPhone和特斯拉都属于在各自领域领头羊的品牌,推出的产品也也都是数一数二的,但对于一些国家而言,它们的产品可靠性和安全性还是在限制范围内。近日,俄罗斯联邦通信、信息技术
  • 天猫精灵Sound Pro体验:智能音箱没有音质?来听听我的

    天猫精灵Sound Pro体验:智能音箱没有音质?来听听我的

    这几年除了手机作为智能生活终端最主要的核心之外,第二个可以成为中心点的产品是什么?——是智能音箱。 手机在执行命令的时候有两种操作方式,手和智能语音助手,而智能音箱只
  • 印度登月最关键一步!月船三号今晚进入环月轨道

    印度登月最关键一步!月船三号今晚进入环月轨道

    8月5日消息,据印度官方消息,月船三号将于北京时间今晚21时30分左右开始近月制动进入环月轨道。这是该探测器能够成功的最关键步骤之一,如果成功将开始围
  • 三言两语说透设计模式的艺术-简单工厂模式

    三言两语说透设计模式的艺术-简单工厂模式

    一、写在前面工厂模式是最常见的一种创建型设计模式,通常说的工厂模式指的是工厂方法模式,是使用频率最高的工厂模式。简单工厂模式又称为静态工厂方法模式,不属于GoF 23种设计
  • 一篇文章带你了解 CSS 属性选择器

    一篇文章带你了解 CSS 属性选择器

    属性选择器对带有指定属性的 HTML 元素设置样式。可以为拥有指定属性的 HTML 元素设置样式,而不仅限于 class 和 id 属性。一、了解属性选择器CSS属性选择器提供了一种简单而
  • 一文掌握 Golang 模糊测试(Fuzz Testing)

    一文掌握 Golang 模糊测试(Fuzz Testing)

    模糊测试(Fuzz Testing)模糊测试(Fuzz Testing)是通过向目标系统提供非预期的输入并监视异常结果来发现软件漏洞的方法。可以用来发现应用程序、操作系统和网络协议等中的漏洞或
  • 破圈是B站头上的紧箍咒

    破圈是B站头上的紧箍咒

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之每年的暑期档都少不了瞄准追剧女孩们的古偶剧集,2021年有优酷的《山河令》,2022年有爱奇艺的《苍兰诀》,今年却轮到小破站抓住了追
  • 大厂卷向扁平化

    大厂卷向扁平化

    来源:新熵作者丨南枝 编辑丨月见大厂职级不香了。俗话说,兵无常势,水无常形,互联网企业调整职级体系并不稀奇。7月13日,淘宝天猫集团启动了近年来最大的人力制度改革,目前已形成一
Top