参考官方文档:https://dromara.org/zh-cn/doc...html
引入相关依赖(官方示例默认开启的alibaba-dubbo,具体参考:soul-examples-dubbo)java
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
插件设置为开启
apache
dubbo
插件中配置你的注册地址
bootstrap
接口注册到网关缓存
@SoulDubboClient
注解,表示该接口方法注册到网关zk
,而后再启动TestApacheDubboApplication
,输出日志 dubbo client register success
,表示dubbo
接口已经发布到 soul 网关服务在启动时会将类方法上的 @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。
至此,@SoulDubboClient
注解分析完毕
先记录一个问题,明天再看:soul 的数据同步是将数据库中的信息同步到本地缓存中,若是是已经经过 @SoulDubboClient
注解注册到soul-admin
的方法被删除了,数据库中的信息何时删除?例如上面findById
方法已经注释掉了 @SoulDubboClient
注解,服务重启时输出的注册信息已经没有了findById
方法,可是soul-admin
中dubbo 插件列表和元数据列表中依然存在findById
方法信息。