dubbo:9个你不一定知道,但好用的功能

dubbo功能非常完善,很多时候我们不需要重复造轮子,下面列举一些你不一定知道,但是很好用的功能。

直连Provider

在开发及测试环境下,可能需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直连模式,将以服务接口为单位,忽略注册中心的提供者列表,A 接口配置点对点,不影响 B 接口从注册中心获取列表(说明:官方只建议开发&测试环境使用该功能),用法如下,url指定的地址就是直连地址:

<dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" version="1.0.0" url="dubbo://172.18.1.205:20888/" />

多版本

当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用,用法如下:

<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" version="1.0.0" />

利用dubbo该特性,我们能够实现一些功能的灰度发布,实现步骤如下:

  1. 接口旧的实现定义version="1.0.0",接口新的实现version="2.0.0"
  2. Consumer端定义version="*"

这样定义Provider和Consumer后,新旧接口实现各承担50%的流量;

利用dubbo该特性,还能完成不兼容版本迁移:

  1. 在低压力时间段,先升级一半Provider为新版本;
  2. 再将所有消费者升级为新版本;
  3. 然后将剩下的一半提供者升级为新版本。

回声测试

回声测试用于检测服务是否可用,回声测试按照正常请求流程执行,能够测试整个调用是否通畅,可用于监控。 所有服务自动实现EchoService接口,只需将任意服务引用强制转型为EchoService 即可使用,使用方式(demoService是spring管理的bean)

EchoService echoService = (EchoService) demoService;
System.out.println(echoService.$echo("hello"));

隐式参数

可以通过 RpcContextsetAttachment()getAttachment() 在Consumer和Provider之间进行参数的隐式传递,例如Controller层拦截登录token,把根据token得到的memberId传给dubbo服务就能使用隐式参数传递的方式,setAttachment()设置的 KV 对,在完成一次远程调用会被清空,即多次远程调用要多次设置。使用方式:

  1. 服务端set:
RpcContext.getContext().setAttachment("CRT_MEMBER_ID", "13828886888");
  1. 客户端get:
RpcContext.getContext().getAttachment("CRT_MEMBER_ID")

上下文

上下文中存放的是当前调用过程中所需的环境信息。所有配置信息都将转换为 URL 的参数 RpcContext 是一个 ThreadLocal 的临时状态记录器,当接收到 RPC 请求,或发起 RPC 请求时,RpcContext 的状态 都会变化。例如:A 调 B,B 再调 C,则 B 机器上,在 B 调 C 之前,RpcContext 记录的是 A 调 B 的信息,在 B 调 C 之后,RpcContext 记录的是 B 调 C 的信息。使用方式:

boolean isConsumerSide = RpcContext.getContext().isConsumerSide();

本地伪装

本地伪装通常用于服务降级,例如某验权服务,当服务提供方全部挂掉后,客户端不抛出异常,而是通过 Mock 数据 返回授权失败。使用方式如下,mock指定的实现类在Provider抛出RpcException异常时执行(一定要抛出RpcException异常才执行),取代远程返回结果:

<dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" version="1.0.0" mock="com.alibaba.dubbo.demo.consumer.mock.DemoServiceMock"/>

DemoServiceMock实现源码:

public class DemoServiceMock implements DemoService {
    public String sayHello(String name) {
        return "mock-value";
    }
}

泛化调用

泛化接口调用方式主要用于客户端没有 API 接口及模型类元的情况,参数及返回值中的所有 POJO 均用Map表示,通常用于框架集成,例如:实现一个通用的服务测试框架,可通过GenericService调用所有服务实现。使用方式:

<dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" generic="true"/>

调用源码:

/**
 * @author afei
 * @version 1.0.0
 * @since 2017年11月22日
 */
public class Main {

    public static void main(String[] args) {
        // 引⽤远程服务, 该实例⾥⾯封装了所有与注册中⼼及服务提供⽅连接,请缓存
        ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
        // 弱类型接⼝名
        reference.setInterface("com.alibaba.dubbo.demo.DemoService");
        reference.setVersion("1.0.0");
        // 声明为泛化接⼝
        reference.setGeneric(true);
        // ⽤com.alibaba.dubbo.rpc.service.GenericService可以替代所有接口引用⽤
        GenericService genericService = reference.get();
        // 基本类型以及Date,List,Map等不需要转换,直接调⽤
        Object result = genericService.$invoke("sayYes", new String[] {"java.lang.String"}, new Object[] {"afei"});
        System.out.println("result --> "+result);

        // ⽤Map表示POJO参数,如果返回值为POJO也将自动转成Map
        Map<String, Object> teacher = new HashMap<String, Object>();
        teacher.put("id", "1");
        teacher.put("name", "admin");
        teacher.put("age", "18");
        teacher.put("level", "3");
        teacher.put("remark", "测试");
        // 如果返回POJO将自动转成Map
        result = genericService.$invoke("justTest", new String[]
                {"com.alibaba.dubbo.demo.bean.HighTeacher"}, new Object[]{teacher});
        System.out.println("result --> "+result);
    }
}

访问日志

如果想记录每次请求信息,可开启访问日志,类似于Ngnix的访问日志。注意:此日志量比较大,请注意磁盘容量。使用方式(如果配置局部,全局访问日志就会失效): 配置全局:

<dubbo:provider accesslog="/app/dubbo-demo.log"/>

配置局部:

<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" accesslog="/app/demo.log"/> <dubbo:service interface="com.alibaba.dubbo.demo.TestService" ref="testService" accesslog="/app/test.log"/>

日志格式样式:

[2017-11-22 10:23:20] 172.18.1.205:56144 -> 172.18.1.205:20886 - com.alibaba.dubbo.demo.DemoService:1.0.0 sayHello(java.lang.String) ["afei"]

延迟暴露

如果服务需要预热时间,比如初始化本地缓存,等待相关资源就位等,可以使用delay进行延迟暴露。使Dubbo在Spring容器初始化完后延迟多少毫秒再暴露服务,这个真的很有用。使用方式:

<dubbo:provider delay="5000"/>

或者:

<dubbo:service delay="5000" interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" version="1.0.0"/>

本文分享自微信公众号 - Kirito的技术分享(cnkirito)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-01-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏jmeter相关技术交流

使用Jmeter测试Dubbo接口

16030
来自专栏idba

一次 Logback 发现的隐患

近期我们在线下环境进行了核心链路单接口的性能摸底,在使用我厂基于 Gatling 自研的 gatling-dubbo框架(详见Dubbo 压测插件 2.0 ——...

5810
来自专栏携程技术中心

干货 | 携程的 Dubbo 之路

实际上从 2013 年底起,携程内主要使用的就是基于 HTTP 协议的 SOA 微服务框架。这个框架是携程内部自行研发的,整体架构在这近6年中没有进行大的重构。...

9220
来自专栏兜兜毛毛

dubbo 和 zokeeper 是分别用来做什么的?他们的关系到底是怎么样的?

之前在因公司产品项目做微服务拆分时使用了dubbo和zokeeper但感觉对他们的认知还是不太清楚。所以最近重新复习看了一下。用通俗的方式些事一下(如有错误请指...

5600
来自专栏搜云库技术团队

有赞服务化架构演进

服务化是互联网公司成长的必经之路。随着微服务的兴起,很多公司如火如荼的搞起了自己的服务化,有兴奋有无奈。那服务化该怎么做,该做什么?本文试图从有赞的发展历程来体...

12530
来自专栏搜云库技术团队

Dubbo服务提供者发布过程

首先ServiceConfig类拿到对外提供服务的实际类ref(如:HelloServiceImpl),然后通过ProxyFactory类的getInvoker...

9250
来自专栏JAVA葵花宝典

携程的 Dubbo 之路

携程当初为什么要引入 Dubbo 呢?实际上从 2013 年底起,携程内主要使用的就是基于 HTTP 协议的 SOA 微服务框架。这个框架是携程内部自行研发的,...

6730
来自专栏搜云库技术团队

Dubbo服务消费者调用过程

首先通过 ReferenceConfig类的 private void init()方法会先检查初始化所有的配置信息后,调用 privateT createPr...

9440
来自专栏猿天地

Dubbo最佳实践,我整理了以下9点

Dubbo服务化,在当前互联网后端开发中,大部分都使用了Dubbo。截止目前github dubbo上,star也将近3万,使用dubbo的公司数量也很可观,D...

22940
来自专栏Kirito的技术分享

Dubbo 常见错误及解决方法

Dubbo 作为高性能 RPC(Remote Procedure Call)框架已经成为 Apache 的顶级项目,意味着在全球被数以千计的公司所采用来其实现...

25620

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励