首页 > 其他分享 >两种方案实现Dubbo泛化调用

两种方案实现Dubbo泛化调用

时间:2022-11-14 19:58:44浏览次数:59  
标签:Dubbo 调用 服务 泛化 Object 接口 new referenceConfig

Dubbo的泛化调用是一个服务A在没有服务B的依赖,包的情况下,只知道服务B的服务名:服务的接口的全限定类名和方法名,以及参数,实现服务A调用服务B。
原文链接:http://blog.qiyuan.run/archives/dubbo泛化调用

方案一

服务A定义接口,服务B实现该接口,意味着是服务B需要服务A的依赖,是满足泛化调用的条件的,以下是具体的实现。

1,服务A接口定义

public interface SomethingService {
	String getSomethingById(Integer id)
}

2,服务B实现接口

2.1,依赖引入

服务B肯定是需要服务A的依赖的,不然没法找到这个interface去实现。
引入服务A的坐标即可。

2.2,实现接口
@Slf4j
@Service
@DubboService(protocol = "dubbo")
public interface MyBusinessServiceImpl implements SomethingService {
    String getSomethingById(Integer id) {
        Object result = xxxxMapper.getSomethingById(id);
        return result.toString();
    }
}

3,服务A定义GenericService

@Configuration
public class SpotterReferenceConfig extends ReferenceConfig<GenericService> {
    ReferenceConfig<GenericService> referenceConfig = new ReferenceConfig<>();
    @Bean
    public GenericService getReferenceConfig(){
        referenceConfig.setRegistry(new RegistryConfig("这里填写注册中心地址"));
        referenceConfig.setInterface("run.qiyuan.generic.SomethingService");//这里填写服务A定义的接口的全限定类名
        referenceConfig.setGeneric("true");//必须设置为true,才能进行泛化
        return referenceConfig.get();
    }
}

4,如何使用

这里如何使用,肯定是服务服务A如何去调用服务B的实现。

@Autowired
private GenericService genericService;

Object result = genericService.$invoke(
        "getSomethingById",//这里是服务方法名
        new String[]{"java.lang.Integer"},//这里是方法参数的类型
        new Object[]{101});//这里是方法参数值
System.out.println(result);//这里的返回值定义为Object,但是实际返回值的类型都是Map集合

5,总结

该方案适合固定的服务接口,方法,参数等,这种方案会发现注册中心中,关于提供服务SomethingService的都是服务A,虽说实现是服务B实现的。这样就会出现很不好的地方,如果有服务A需要调用不同的服务B,服务C,服务D等,这些服务都去实现该接口,就会在注册中心上发现该服务下面有多个实例,每个实例对应一个服务,服务发起调用的时候,没有传递关于到底是调用哪个实例的参数,就会出现混乱。

方案二

根据方案二的局限性,这里提出一种更加便利,可以说是更加泛化的一种方案。
假设有三个服务,【消费方:服务A】,【提供方:服务B,服务C】,需求是服务A可能会去调用服务B,C的服务,如何实现,且看下面。

1,服务B、C定义接口,实现接口

这里和方案一不同的是,提供方的接口和实现都是自己维护的,这个和平常的开发没有区别,例如:

接口定义

public interface UserService{
      Integer addUser(User user);
      User getUserById(Integer id);
}

接口实现

public interface UserServiceImpl implements UserService{
      Integer addUser(User user){
      	  return userMapper.addUser(user);
      }
      User getUserById(Integer id){
     	 //////
      }
}

2,服务A定义泛化调用工具类

public class DubboGenericInvoke {
    private static Map<String, ReferenceConfig<GenericService>> referenceConfigMap = new ConcurrentHashMap<>();
    public static Object invoke(String tag,String interfaceClass, String methodName, String[] paramTypes, Object[] params) {
        ReferenceConfig<GenericService> referenceConfig;
        String key = interfaceClass+"---"+tag;
        try {
            referenceConfig = referenceConfigMap.get(key);
            if (referenceConfig == null) {
                referenceConfig = new ReferenceConfig<>();
                RegistryConfig registry = new RegistryConfig("这里填写注册中心地址");
                referenceConfig.setRegistry(registry);
                referenceConfig.setRetries(4);//重试次数
                ConsumerConfig consumerConfig = new ConsumerConfig();
                referenceConfig.setConsumer(consumerConfig);
                referenceConfig.setGeneric(CommonConstants.GENERIC_SERIALIZATION_DEFAULT);
                referenceConfig.setInterface(interfaceClass);
                referenceConfig.setTimeout(3000);//ms,如果服务方超时时间超过了这里的时间,将进行重试,达到重试次数时,报超时异常。
                if(tag.length()!=0){
                    referenceConfig.setTag(tag);
                }
                referenceConfig.setCheck(true);
                referenceConfigMap.put(key, referenceConfig);
            }
            GenericService genericService = referenceConfigMap.get(key).get();
            Object result = genericService.$invoke(methodName, paramTypes, params);
            if (result == null) {
                log.info("远程服务结果返回为空,请注意查看远程服务的参数:{}", params);
            }
            return result;
        } catch (GenericException e) {
            log.info("发起远程调用失败,错误信息:{}", e.getMessage());
            referenceConfigMap.remove(key);
            return null;

        } catch (Exception e) {
            log.info("远程服务获取结果失败,错误信息:{}", e.getMessage());
            referenceConfigMap.remove(key);
            return null;
        }
    }
}

3,如何使用

服务A服务去使用该工具类呢,直接调用就可以了。

HashMap map = new HashMap();
map.put("userName","一只小Coder");
map.put("passWord","root");
DubboGenericInvoke.invoke("your_tag",//表示需要调用哪个实例的服务,通过Dubbo的tag属性来区分
                    "run.qiyuan.service.UserService",//需要调用的服务的全限定类名
                    "addUser", //方法
                    new Object[]{"run.qiyuan.model.User"},//参数类型,不仅支持java的基本数据类型,同时支持自定义类型 
                    new Object[]{map});//如果是基本数据类型,组装成Map集合就好了

通过以上代码可以发现,可以实现对同一个服务,不同实例进行调用;可以实现对不同的服务的调用,传递的interfaceClass也都是我们自己维护的。缺点就是第一次调用一个服务的时候有点慢,因为要去注册,我看网上有很多事通过一个ReferenceCache来存放的,我这里使用的是一个Map集合,都差不多,解决这个问题,可是在项目启动的时候,先去讲可能需要调用的服务都先去调用遍,这样每个服务就在Map集合中了。

标签:Dubbo,调用,服务,泛化,Object,接口,new,referenceConfig
From: https://www.cnblogs.com/onecoder/p/16890141.html

相关文章

  • 关于函数调用的总结
    首先强调的是:C语言中所有函数调用都是传值调用(数组是例外情况。C里数组名就表示了数组的首地址当把数组名当参数传递时,其实也就是传了个地址而已)1、传值调用......
  • GeoServer和ArcGISServer的WMTS服务怎么发布和调用
    ArcGISServerWMTS服务发布与使用:https://www.fengjinwei.com/blog-1116408.htmlgeoserver发布wmts服务并使用arcgisjs4.x调用:https://blog.csdn.net/FlyToTheWorld/art......
  • EasyCVR调用设备录像回放接口,无法播放录像是什么原因?
    EasyCVR视频融合云服务支持多协议、多类型的设备接入,平台可提供视频监控直播、云端录像、云存储、录像检索与回看、智能告警、级联等功能。在录像功能上,EasyCVR可支持云端......
  • EasyCVR调用设备录像回放接口,无法播放录像是什么原因?
    EasyCVR视频融合云服务支持多协议、多类型的设备接入,平台可提供视频监控直播、云端录像、云存储、录像检索与回看、智能告警、级联等功能。在录像功能上,EasyCVR可支持云端录......
  • 调用工具类方法的注意事项
    当我们调用一个工具类的方法的时候eg:工具类:@ComponentpublicclassConvertUtils{@ResourceprivateJcdeptMapperjcdeptMapper;@AutowiredprivateJcde......
  • 极客编程python入门-调用函数
    调用函数Python内置了很多有用的函数,我们可以直接调用。要调用一个函数,需要知道函数的名称和参数a=abs(100.123)print(a)a=abs(-123)print(a)a=abs(-123.123)print(a......
  • 21. 合并两个有序链表 ----- 递归调用、链表指针
    将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。  示例1:输入:l1=[1,2,4],l2=[1,3,4]输出:[1,1,2,3,4,4]示例......
  • .Net core 调用WebService
    在REST出现之前解决跨平台之间的通信问题基本都是采用基于XML的WebService进行。一、什么是WebServiceWebService是一个平台独立的,低耦合的,自包含的、基于可编程的web的......
  • 第6章Spring与Web-使用 Spring 的监听器 ContextLoaderListener使得将spring容器对象
    第6章Spring与Web在Web项目中使用Spring框架,首先要解决在web层(这里指Servlet)中获取到Spring容器的问题。只要在web层获取到了Spring容器,便可从容器中获取到......
  • 1.dubbo入门案例
    1.Dubbo的基本架构节点角色说明:节点角色说明Provider暴露服务的服务提供方。Consumer调用远程服务的服务消费方。Registry服务注册与发现的注册中心......