Dubbo 框架适配模块及实现原理
适配 Dubbo 框架
Dubbo 是一款面向接口代理的高性能 RPC 调用框架,适用于数据量小但并发数大的服务调用场景,以及服务消费者机器数远大于服务提供者机器数的场景。
由于 Dubbo 与 Sentinel 出自同一家,因此 Sentinel 自然也会为 Dubbo 提供适配模块。
本节将介绍 Sentinel 的 Dubbo 适配模块的使用,并分析适配原理。
使用步骤
在项目的 pom.xml 依赖配置文件中添加 sentinel-apache-dubbo-adapter 模块的依赖配置,代码如下:
在导入依赖后,Dubbo 的服务接口和方法(包括调用端和服务端)就会成为 Sentinel 保护的资源。
Sentinel 适配 Dubbo 框架可支持两种限流粒度,不同粒度资源名称的生成规则不同。
接口级别:资源名称为接口全限定名。
方法级别:资源名称为接口全限定名+“:”+方法签名。
Sentinel 适配 Dubbo 框架可支持注册全局的 Fallback 处理器。在 Sentinel 抛出限流、熔断等 BlockException 时,Fallback 函数会被回调,可用于实现限流、熔断后的降级操作。在应用启动时,可以通过调用 DubboAdapterGlobalConfig#setConsumerFallback 方法注册,代码如下:
Sentinel 默认使用 Dubbo 配置项 dubbo.application.name 的值作为调用来源,由客户端在发起 RPC 调用时传递给服务端。如果需要针对某个调用来源限流,则限流规则的 limitApp 应该与客户端的 dubbo.application.name 配置一样。
适配原理
Dubbo 在采用分层架构设计实现解耦的同时方便了各层的扩展,总体可分为业务层、RPC 层和 Remote 层,而 RPC 层又可细分为代理层、注册中心层、集群负载层、监视器层和协议层。在 RPC 层中,协议层是核心层,也就是说,只要有 Protocol+Invoker+Exporter,就可以完成非透明的 RPC 远程调用。
无论是服务端还是客户端,都是通过实现相同的 RPC 接口来向外暴露服务及引用服务的。Dubbo 通过动态代理为接口生成代理类,代理类可将接口转换为 Invoker,将调用接口方法转换为调用 Invoker 的 invoke 方法,并将请求参数封装为 Invocation。而 Invoker 在暴露与引入的过程中又被包装器添加了过滤器,因此在向远程发起调用时,会先经过过滤器,在过滤器不过滤请求的情况下才会真正发起远程调用。
Sentinel 适配 Dubbo 框架的本质是向 Dubbo 注册自定义过滤器,在过滤器中使用 Sentinel 来包装 Invoker。
Dubbo 框架是由一个个组件构成的,每个组件实现的是不同分层的逻辑,同时 Dubbo 需要通过 SPI 机制加载所需的组件。Sentinel Dubbo Adapter 模块通过 Dubbo SPI 机制向 Dubbo 注册自定义的过滤器,并在源码的 resources/META-INF/dubbo 目录下的 org.apache.dubbo.rpc.Filter 配置文件中配置。
该文件配置的内容如下:
SentinelDubboConsumerFilter:Sentinel 适配 Dubbo 框架的过滤器,只在客户端生效。
SentinelDubboProviderFilter:Sentinel 适配 Dubbo 框架的过滤器,只在服务端生效。
DubboAppContextFilter:用于客户端向服务端传递调用来源,只在客户端生效。
1. 服务端
服务端通过 SentinelDubboProviderFilter 过滤器适配 Dubbo 框架,在 invoke 方法中使用 Sentinel 分别按接口粒度、方法粒度包装 RPC 请求,源码如下:
获取调用来源。
生成不同粒度的资源名称。
调用 ContextUtil#enter 方法,调用链入口名称为方法级别的资源名称。
为不同粒度资源调用 SphU#entry 方法,资源类型为 COMMON_RPC,流量类型为 IN。
当远程响应异常时,为不同粒度资源统计异常指标。
如果抛出 BlockException,则说明当前请求被拒绝,可调用注册的全局 Fallback 处理器完成降级逻辑处理。
当发起调用抛出异常时,为不同粒度资源分别统计异常指标。
为不同粒度资源分别调用 SphU#exit 方法。
调用 ContextUtil#exit 方法。
2. 客户端
客户端通过 SentinelDubboConsumerFilter 过滤器适配 Dubbo 框架,在 invoke 方法中使用 Sentinel 分别按接口粒度、方法粒度包装 RPC 请求,在不考虑适配异步调用的情况下,SentinelDubboConsumerFilter 与 SentinelDubboProviderFilter 在实现上没有多大差别。适配客户端还有一个 DubboAppContextFilter 过滤器,该过滤器用于向服务端传递调用来源。
DubboAppContextFilter 过滤器的源码如下:
在实际项目中,微服务之间的调用错综复杂,对于不同接口,客户端可能也是服务端,服务端可能也是客户端。因此,如果不需要注册 SentinelDubboConsumerFilter 过滤器或 SentinelDubboProviderFilter 过滤器,则可以在项目中添加如下配置以排除过滤器。
排除 Sentinel 适配 Dubbo 框架客户端的过滤器的配置如下:
排除 Sentinel 适配 Dubbo 框架服务端的过滤器的配置如下:
评论