soul网关dubbo学习(2):dubbo测试用例测试过程分析

前言

今天主要内容是学习了soul网关代理dubbo服务的过程,在讲述主要内容之前,先回顾下上回遇到的问题,上回在启动了alibaba dubbo example之后,发现dubbo服务无法调用,但是今天启动却没发现该问题,dubbo服务可以正常代理,中间没有改过什么代码或配置,倒是有一次电脑重启,也许是重启大法的功效,上次出问题的具体原因暂时也无法追溯。另外,soul-examples-alibaba-dubbo-service启动报如下异常(暂未影响到我测试的功能,未细查):

2021-01-24 00:31:20.980  WARN 13588 --- [           main] c.a.d.qos.protocol.QosProtocolWrapper    :  [DUBBO] Fail to start qos server: , dubbo version: 2.6.5, current host: 172.30.82.27

java.lang.NoClassDefFoundError: io/netty/channel/EventLoopGroup
	at com.alibaba.dubbo.qos.protocol.QosProtocolWrapper.startQosServer(QosProtocolWrapper.java:95) [dubbo-2.6.5.jar:2.6.5]
	at com.alibaba.dubbo.qos.protocol.QosProtocolWrapper.export(QosProtocolWrapper.java:59) [dubbo-2.6.5.jar:2.6.5]
	at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper.export(ProtocolFilterWrapper.java:98) [dubbo-2.6.5.jar:2.6.5]
	at com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper.export(ProtocolListenerWrapper.java:55) [dubbo-2.6.5.jar:2.6.5]
	at com.alibaba.dubbo.rpc.Protocol$Adaptive.export(Protocol$Adaptive.java) [dubbo-2.6.5.jar:2.6.5]
	at com.alibaba.dubbo.config.ServiceConfig.doExportUrlsFor1Protocol(ServiceConfig.java:513) [dubbo-2.6.5.jar:2.6.5]
	at com.alibaba.dubbo.config.ServiceConfig.doExportUrls(ServiceConfig.java:358) [dubbo-2.6.5.jar:2.6.5]
	at com.alibaba.dubbo.config.ServiceConfig.doExport(ServiceConfig.java:317) [dubbo-2.6.5.jar:2.6.5]
	at com.alibaba.dubbo.config.ServiceConfig.export(ServiceConfig.java:216) [dubbo-2.6.5.jar:2.6.5]
	at com.alibaba.dubbo.config.spring.ServiceBean.export(ServiceBean.java:291) [dubbo-2.6.5.jar:2.6.5]
	at com.alibaba.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:131) [dubbo-2.6.5.jar:2.6.5]
	at com.alibaba.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:53) [dubbo-2.6.5.jar:2.6.5]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) [spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) [spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) [spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:403) [spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:360) [spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:897) [spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:162) [spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553) [spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) [spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.dromara.soul.examples.alibaba.dubbo.service.TestAlibabaDubboApplication.main(TestAlibabaDubboApplication.java:38) [classes/:na]
Caused by: java.lang.ClassNotFoundException: io.netty.channel.EventLoopGroup
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_60]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_60]
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[na:1.8.0_60]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_60]
	... 27 common frames omitted

RPC服务向网关注册

正常情况下,启动alibaba dubbo example,服务会自动向网关注册相应的服务信息,包括选择器,规则以及元数据,如下图所示:
在这里插入图片描述
在这里插入图片描述
根据上回http服务注册的经验,先去soul-spring-boot-starter-client-alibaba-dubbo找到config类(SoulAlibabaDubboClientConfiguration),然后从该类的bean配置进入 AlibabaDubboServiceBeanPostProcessor,看到如下的注册函数(可以打断点验证):

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 = method.getAnnotation(SoulDubboClient.class);
            if (Objects.nonNull(soulDubboClient)) {
                RegisterUtils.doRegister(buildJsonParams(serviceBean, soulDubboClient, method), url, RpcTypeEnum.DUBBO);
            }
        }
    }

其中doRegister就是向admin注册的函数,注册的url后缀为/soul-client/dubbo-register,根据这个url,可以在admin中搜索到对应的注册入口,admin注册函数通过如下函数(org.dromara.soul.admin.service.impl.SoulClientRegisterServiceImpl.registerDubbo(MetaDataDTO))保存注册上来的选择器、规则以及元数据:

 public String registerDubbo(final MetaDataDTO dto) {
        MetaDataDO exist = metaDataMapper.findByPath(dto.getPath());
        saveOrUpdateMetaData(exist, dto);
        String selectorId = handlerDubboSelector(dto);
        handlerDubboRule(selectorId, dto);
        return SoulResultMessage.SUCCESS;
    }

RPC服务代理

与http代理类似,soul网关代理dubbo服务也是从接收http服务开始,入口一样是org.dromara.soul.web.handler.SoulWebHandler.handle(ServerWebExchange),在此入口前面有涉及到netty相关,这块需要另外补充。
进入入口之后,就是一系列的插件都过一遍,网关bootstrap后台可以看到如下的日志:

 INFO 19448 --- [oul-netty-nio-2] o.d.soul.plugin.base.AbstractSoulPlugin  : dubbo selector success match , selector name :/dubbo
 INFO 19448 --- [oul-netty-nio-2] o.d.soul.plugin.base.AbstractSoulPlugin  : dubbo rule success match , rule name :/dubbo/insert

接下来可以从AbstractSoulPlugin这个类直接入手,一步步查看其调用情况,由于时间关系,具体就不再记录。

额外小知识

  1. soul网关不关注具体http方法,GET、POST、甚至DELETE等都一样,只要url和相关参数完整即可;
  2. 变量名称可以包含美元符号$,并且还可以放在开头,这个我居然现在才知道;
  3. ImmutablePair是个不错的东西,可以试着用起来。
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页