热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

利用Dubbo的SPI扩展容器

在实际开发中,很多Dubbo的服务提供者都会运行在web容器上,如果提供者服务上同时对外

在实际开发中,很多Dubbo的服务提供者都会运行在web容器上,如果提供者服务上同时对外提供http服务的话,这么做是有必要的,但如果你的服务提供者只是对外提供dubbo服务的话,那么用web容器就有些重了,因为毕竟web容器主要是用来响应http请求以及静态页面的。如果单独作为dubbo服务提供者,只需要通过一个main方法加载一个简单的spring容器将服务暴露出去即可。
注:本文以dubbo的2.6.5版本为例
  • 一、Dubbo的内置容器

dubbo内置了三种容器
Log4jContainer:只是针对log4j配置文件做了处理。

LogbackContainer:只是针对logback日志配置文件做了处理。

SpringContainer:
它的start方法会创建ClassPathXmlApplicationContext容器,然后分别执行refresh方法和start方法刷,暴露dubbo服务;其stop方法会执行ClassPathXmlApplicationContext的stop及close方法。

可以看到,这三种容器,只有SpringContainer真正的加载了容器并暴露了服务,所以要用dubbo自带的容器的话,SpringContainer是必选的,可以单独使用,另外两个需要配合SpringContainer使用,但是如果要使用SpringContainer的话,你需要把配置文件放到指定的为止,因为源码中已经定义死了:

所以我们用的时候一般是通过实现Container接口来自定义一个容器,然后重写Main类通过Dubbo的SPI机制加载自定义的容器,这样可以自定义加载配置文件。
  • 二、自定义Container

  • 2.1、首先用idea新建一个基于maven的java项目,添加dubbo,zk等依赖,具体的项目创建过程略过。

  • 2.2、写一个接口和实现类,用来对外暴露

  • 2.3、添加spring配置文件,dubbo配置文件等

  • 2.4、定义一个容器类,实现Container接口

    package com.ayo;


    import com.alibaba.dubbo.container.Container;
    import com.ayo.util.PathUtil;
    import org.springframework.context.support.FileSystemXmlApplicationContext;


    /**
    * 自定义一个容器
    */
    public class CustomContainer implements Container{


    /**
    * spring容器上下文
    */
    static FileSystemXmlApplicationContext context;


    /**
    * 启动容器
    */
    public void start() {
    try {
    String path = PathUtil.getAppConfPath().concat(PathUtil.sp()).concat("spring.xml");
    cOntext= new FileSystemXmlApplicationContext(path);
    }catch (Exception e){
    e.printStackTrace();
    }
    }


    /**
    * 停止容器
    */
    public void stop() {
    try {
    if (context != null){
    context.stop();
    context.close();
    cOntext= null;
    }
    }catch (Exception e){
    e.printStackTrace();
    }
    }
    }

    • 2.5、在resources下建一个文件夹命名为META-INF,然后在META-INF下再建一个文件夹命名为dubbo,然后建立一个文件命名为com.alibaba.dubbo.container.Container,里面写上内容

    为什么要这么做?这就是Dubbo的SPI,不知道的可以看下,传送门:

    Dubbo的SPI、适配器原理、动态编译原理

    • 2.6、写一个Main类用于加载和启动自定义的Container

      package com.ayo;


      import com.alibaba.dubbo.common.extension.ExtensionLoader;
      import com.alibaba.dubbo.container.Container;
      import java.text.SimpleDateFormat;
      import java.util.Date;




      /**
      * 自定义dubbo容器
      *
      * @author ayo
      */
      public class Main {


      /**
      * dubbo优雅关机
      */
      public static final String SHUTDOWN_HOOK_KEY = "dubbo.shutdown.hook";


      private static volatile boolean running = true;


      public static void main(String[] args) {
      try {
      final Container customCOntainer= ExtensionLoader.getExtensionLoader(Container.class).getExtension("custom");
      //在dubbo优雅关机的时候会触发此钩子函数
      if ("true".equals(System.getProperty(SHUTDOWN_HOOK_KEY))) {
      Runtime.getRuntime().addShutdownHook(new Thread() {
      public void run() {
      try {
      customContainer.stop();
      System.out.println("Dubbo " + customContainer.getClass().getSimpleName() + " stopped!");
      } catch (Throwable t) {
      t.printStackTrace();
      }
      synchronized (Main.class) {
      running = false;
      Main.class.notify();
      }
      }
      });
      }
      customContainer.start();
      System.out.println("Dubbo " + customContainer.getClass().getSimpleName() + " started!");
      System.out.println(new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss]").format(new Date()) + " Dubbo service server started!");
      } catch (RuntimeException e) {
      e.printStackTrace();
      System.exit(1);
      }
      synchronized (Main.class) {
      while (running) {
      try {
      Main.class.wait();
      } catch (Throwable e) {
      }
      }
      }
      }
      }

      • 2.7、运行Main类中的main方法

      • 2.8、看下服务有没有注册到zk

      • 2.9、写个dubbo消费者测试下接口是否正常

        package com.ayo;


        import com.alibaba.dubbo.config.ApplicationConfig;
        import com.alibaba.dubbo.config.ReferenceConfig;
        import com.alibaba.dubbo.config.RegistryConfig;
        import com.ayo.service.UserService;


        public class Consumer {


        public static void main(String[] args) {
        1.创建服务引用对象实例
        ReferenceConfig referenceCOnfig= new ReferenceConfig();


        2.设置应用程序信息
        ApplicationConfig applicatiOnConfig= new ApplicationConfig("dubbo-consumer");
        referenceConfig.setApplication(applicationConfig);


        //3.设置服务注册中心
        RegistryConfig registryCOnfig= new RegistryConfig("zookeeper://192.168.209.129:2181");
        referenceConfig.setRegistry(registryConfig);


        //3.设置服务接口和超时时间
        referenceConfig.setInterface(UserService.class);
        referenceConfig.setTimeout(5000);


        //5.引用服务
        UserService userService = referenceConfig.get();


        //6.调用服务
        System.out.println(userService.getUserName());
        }
        }

        需要demo的私我。


        推荐阅读
        author-avatar
        手机用户2502941011
        这个家伙很懒,什么也没留下!
        PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
        Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有