【Soul源碼閱讀-03】dubbo插件SoulDubboClient註解解析

目標

  • 運行 examples下面的 apache-dubbo 服務
  • 學習文檔,結合 dubbo 插件,發起 http 請求 soul 網關,體驗 dubbo 代理

soul 網關接入 Dubbo 應用

  • 參考官方文檔:https://dromara.org/zh-cn/doc...html

    • 引入相關依賴(官方示例默認開啓的alibaba-dubbo,具體參考:soul-examples-dubbojava

      soul-bootstrap新增以下依賴:git

      <!--soul  apache dubbo plugin start-->
               <dependency>
                  <groupId>org.dromara</groupId>
                  <artifactId>soul-spring-boot-starter-plugin-apache-dubbo</artifactId>
                  <version>${project.version}</version>
              </dependency>
              <dependency>
                  <groupId>org.apache.dubbo</groupId>
                  <artifactId>dubbo</artifactId>
                  <version>2.7.5</version>
              </dependency>
              
              <!-- Dubbo zookeeper registry dependency start -->
            <dependency>
                  <groupId>org.apache.curator</groupId>
                  <artifactId>curator-client</artifactId>
                  <version>4.0.1</version>
              </dependency>
              <dependency>
                  <groupId>org.apache.curator</groupId>
                  <artifactId>curator-framework</artifactId>
                  <version>4.0.1</version>
              </dependency>
              <dependency>
                  <groupId>org.apache.curator</groupId>
                  <artifactId>curator-recipes</artifactId>
                  <version>4.0.1</version>
              </dependency>
               <!-- Dubbo zookeeper registry dependency end -->

      soul-examples-apache-dubbo-service新增以下依賴:github

      <!--soul apache dubbo plugin start-->
                 <dependency>
                     <groupId>org.dromara</groupId>
                     <artifactId>soul-spring-boot-starter-plugin-apache-dubbo</artifactId>
                     <version>2.2.1</version>
                 </dependency>
                 <!--soul apache dubbo plugin end-->
                 
                 <!-- Dubbo dependency -->
                 <dependency>
                     <groupId>org.apache.dubbo</groupId>
                     <artifactId>dubbo</artifactId>
                     <version>2.7.5</version>
                 </dependency>
                 
                <!-- Dubbo zookeeper registry dependency start-->
                 <dependency>
                  <groupId>org.apache.zookeeper</groupId>
                  <artifactId>zookeeper</artifactId>
                  <version>3.5.6</version>
                  <exclusions>
                      <exclusion>
                          <groupId>org.slf4j</groupId>
                          <artifactId>slf4j-log4j12</artifactId>
                      </exclusion>
                      <exclusion>
                          <groupId>log4j</groupId>
                          <artifactId>log4j</artifactId>
                      </exclusion>
                  </exclusions>
              </dependency>
             <!-- Dubbo zookeeper registry dependency end -->
    • application.yml添加相關配置spring

      soul:
           dubbo:
             adminUrl: http://localhost:9095
             contextPath: /dubbo
             appName: dubbo
            # adminUrl: 爲你啓動的soul-admin 項目的ip + 端口,注意要加 http://
            # contextPath: 爲你的這個項目在soul網關的路由前綴,好比/order ,/product 等等,網關會根據你的這個前 綴來進行路由.
            # appName:你的應用名稱,不配置的話,會默認取 dubbo配置中application 中的名稱
  • dubbo 插件設置數據庫

    soul-admin 插件管理中,dubbo 插件設置爲開啓
    image-20210116223835118apache

    dubbo 插件中配置你的註冊地址
    image-20210116201405bootstrap

  • 接口註冊到網關緩存

    • dubbo 服務實現類的方法上加上 @SoulDubboClient 註解,表示該接口方法註冊到網關
  • 先啓動zk,而後再啓動TestApacheDubboApplication,輸出日誌 dubbo client register success,表示dubbo接口已經發布到 soul 網關

    image-20210116201725

@SoulDubboClient 註解解析

服務在啓動時會將類方法上的 @SoulDubboClient 註解註冊到網關,接下來分析一下@SoulDubboClient 註冊邏輯。app

soul-examples-apache-dubbo-service添加了soul-spring-boot-starter-plugin-apache-dubbo依賴,註冊邏輯應該就在這個自定義的spring-boot-starter中。

首先註釋掉DubboTestServicel類中findById方法上的@SoulDubboClient註解

@Override
    //@SoulDubboClient(path = "/findById", desc = "Query by Id")
    public DubboTest findById(final String id) {
        DubboTest dubboTest = new DubboTest();
        dubboTest.setId(id);
        dubboTest.setName("hello world Soul Apache, findById");
        return dubboTest;
    }

soul-spring-boot-starter-client-apache-dubbo 自定義spring-boot-starter經過 spring.factories 加載了SoulApacheDubboClientConfiguration類:

@Configuration
public class SoulApacheDubboClientConfiguration {
    
    /**
     * Apache dubbo service bean post processor alibaba dubbo service bean post processor.
     *
     * @param dubboConfig the dubbo config
     * @return the alibaba dubbo service bean post processor
     */
    @Bean
    public ApacheDubboServiceBeanPostProcessor apacheDubboServiceBeanPostProcessor(final DubboConfig dubboConfig) {
        return new ApacheDubboServiceBeanPostProcessor(dubboConfig);
    }
    
    /**
     * Dubbo config dubbo config.
     *
     * @return the dubbo config
     */
    @Bean
    @ConfigurationProperties(prefix = "soul.dubbo")
    public DubboConfig dubboConfig() {
        return new DubboConfig();
    }
}

SoulApacheDubboClientConfiguration加載了ApacheDubboServiceBeanPostProcessor實例,該實例實現了ApplicationListener<ContextRefreshedEvent> 接口,該類中的主要方法:

public ApacheDubboServiceBeanPostProcessor(final DubboConfig dubboConfig) {
        //獲取 application.yml 文件中的配置信息
        String contextPath = dubboConfig.getContextPath();
        String adminUrl = dubboConfig.getAdminUrl();
        if (StringUtils.isEmpty(contextPath)
                || StringUtils.isEmpty(adminUrl)) {
            throw new RuntimeException("apache dubbo client must config the contextPath, adminUrl");
        }
        this.dubboConfig = dubboConfig;
        url = dubboConfig.getAdminUrl() + "/soul-client/dubbo-register";
        executorService = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
    }
@Override
    public void onApplicationEvent(final ContextRefreshedEvent contextRefreshedEvent) {
        if (Objects.nonNull(contextRefreshedEvent.getApplicationContext().getParent())) {
            return;
        }
        // Fix bug(https://github.com/dromara/soul/issues/415), upload dubbo metadata on ContextRefreshedEvent
        
        //根據 beanType 獲取全部的 bean,這裏獲取的是 spring-dubbo.xml 中 <dubbo:service/>中的DubboTestService和               //DubboMultiParamService         
        //ServiceBean.class:org.apache.dubbo.config.spring.ServiceBean.class
        Map<String, ServiceBean> serviceBean = contextRefreshedEvent.getApplicationContext().getBeansOfType(ServiceBean.class);
        for (Map.Entry<String, ServiceBean> entry : serviceBean.entrySet()) {
            executorService.execute(() -> handler(entry.getValue()));
        }
    }

處理類中的每一個方法

private void handler(final ServiceBean serviceBean) {
        Class<?> clazz = serviceBean.getRef().getClass();
        if (ClassUtils.isCglibProxyClass(clazz)) {
            String superClassName = clazz.getGenericSuperclass().getTypeName();
            try {
                clazz = Class.forName(superClassName);
            } catch (ClassNotFoundException e) {
                log.error(String.format("class not found: %s", superClassName));
                return;
            }
        }
       // 獲取類中每一個方法
        final Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(clazz);
        for (Method method : methods) {
            //獲取類上的 @SoulDubboClient 註解
            SoulDubboClient soulDubboClient = method.getAnnotation(SoulDubboClient.class);
            if (Objects.nonNull(soulDubboClient)) {
                //遠程調用,註冊方法信息到 soul-admin
                RegisterUtils.doRegister(buildJsonParams(serviceBean, soulDubboClient, method), url, RpcTypeEnum.DUBBO);
            }
        }
    }

當獲取到DubboTestServicel類中findById的方法時,因爲咱們上面註釋了 @SoulDubboClient註解,全部以這裏獲取 SoulDubboClient 的值爲 null。

img

至此,@SoulDubboClient註解分析完畢

問題

先記錄一個問題,明天再看:soul 的數據同步是將數據庫中的信息同步到本地緩存中,若是是已經經過 @SoulDubboClient註解註冊到soul-admin的方法被刪除了,數據庫中的信息何時刪除?例如上面findById方法已經註釋掉了 @SoulDubboClient註解,服務重啓時輸出的註冊信息已經沒有了findById方法,可是soul-admin中dubbo 插件列表和元數據列表中依然存在findById方法信息。

image-20210116223835118

image-20210116224221733

相關文章
相關標籤/搜索