文章说明

本文内容整理自《孙哥说Dubbo系列视频课程》,孙帅老师课程细致、全面、深入、性价比极高。B站搜孙帅suns可以找到对应的试听视频,或者直接添加老师微信号suns45与他直接联系

一:SpringBoot应用Dubbo开发应用的核心思路分析

深度封装,把公共的配置放置到application.yml中,把个性化得配置基于注解进行设置

1:Spring集成Dubbo的时候都有那些配置内容?

Spring使用Dubbo的时候,我们大致有四类非常核心的配置内容:应用名、应用通信协议和端口号、Service发布为Rpc服务、Service实例化的Bean对象或者是代理对象

公共配置:应用名、应用通信协议和端口号

个性化配置:Service发布为Rpc服务、Service实例化的Bean对象或者是代理对象

配置示例:

<dubbo:application name="dubbo-02-provider"/>
<dubbo:protocol name="dubbo" port="20880"/>
<bean id="userService" class="com.suns.service.UserServiceImpl"/>
<dubbo:service interface="com.suns.service.UserService" ref="userService"/>
<dubbo:application name="dubbo-03-consuemer">
     <dubbo:parameter key="qos.enable" value="false"/>
</dubbo:application>

<!--id指定的指定是消费者里边获取远端的服务的一个ID-->
<dubbo:reference interface="com.suns.service.UserService" id="userService"
url="dubbo://192.168.8.1:20880/com.suns.service.UserService"/>

2:这些配置在SpringBoot整合Dubbo之后如何体现呢?

首先想跟大家明确一个概念:Spring在整合一些技术的时候,会有大量的配置存在于XML配置当中。这些配置在使用SpringBoot整合之后,仿佛一下子简化了很多。配置不会凭空减少的,一部分原因是框架已经帮我们进行封装配置了,另一部分是基于注解等其他形式进行简化了,才让我们有了SpringBoot简化了技术资源整合的感觉

(一):provider的处理

1):公共配置抽取为YML
spring:
    application:
        name: aaa

dubbo:
    application:
        name: aaa
    protocol:
        name: dubbo
        port: -1

补充说明:

Dubbo与SpringBoot整合的时候给Dubbo服务起名字的话,是有两种方式的:1:基于yml配置当红当中的那种配置,这是最标准的配置方式。另外,还有一种更加SpringBoot的方式,就是上图中Spring开头的那个,这两个起到的作用是玩全一致的。优先去找dubbo开头的那个配置,如果那个没有找到,默认会去找spring开头的那个配置项。二者写哪个都行,写一个就完事了,在我们后续使用SpringCloud的里边,也需要设置应用名,spring开头是非常方便的,Dubbo服务和Spring服务名称保持了一致。

dubbo:application:name == spring:application:name作用一致,但是后者功能强大!

2):个性化配置基于注解解决
@DubboService
public class UserServiceImpl implements UserService {
    @Override
    public boolean login(String name, String password) {
        System.out.println("UserServiceImpl.login name " + name + " password " + password);
        return false;
    }
}

个性化配置基于@DubboService注解即可,这样的一个注解就起到了两个作用:注册Spring容器实例的标签+将Service发布为一个Dubbo服务。

(二):consumer的处理

1):公共配置抽取为YML
spring:
    application:
        name: consumer

dubbo:
    protocol:
        qos-enable: false
       
2):个性化配置基于注解解决
@DubboReference(url="dubbo://192.168.8.1:20880/com.suns.service.UserService")
public UserService  userService;

这种方式可以注入给

二:SpringBoot应用与Dubbo开发整合编码开发

1:构建多模块的SpringBoot应用

(一):引入依赖jar包

        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.suns</groupId>
            <artifactId>dubbo-01-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

dubbo的SpringBoot启动器,提供者和消费者都需要使用的启动器。

(二):构建provider模块

公共配置:

共有配置:application.yml
spring:
  application:
    name: DUBBO-04-BOOT-PROVIDER
dubbo:
  protocol:
    name: dubbo
    port: -1

 个性化配置:@DubboService

@DubboService
public class UserServiceImpl implements UserService {
    @Override
    public boolean login(String name, String password) {
        System.out.println("UserServiceImpl.login name " + name + " password " + password);
        return false;
    }
}

 启动类:@EnableDubbo

@SpringBootApplication
@EnableDubbo
public class Dubbo04BootProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(Dubbo04BootProviderApplication.class, args);
    }

}
2023-08-02 21:32:18.707  INFO 12844 --- [           main] o.a.d.remoting.transport.AbstractServer  :  [DUBBO] Start NettyServer bind /0.0.0.0:20880, export /192.168.8.1:20880, dubbo version: 3.2.0, current host: 192.168.8.1
2023-08-02 21:32:18.710  INFO 12844 --- [           main] .c.m.ConfigurableMetadataServiceExporter :  [DUBBO] The MetadataService exports urls : [dubbo://192.168.8.1:20880/org.apache.dubbo.metadata.MetadataService?anyhost=true&application=DUBBO-04-BOOT-PROVIDER&background=false&bind.ip=192.168.8.1&bind.port=20880&delay=0&deprecated=false&dubbo=2.0.2&dynamic=true&executor-management-mode=isolation&file-cache=true&generic=false&getAndListenInstanceMetadata.1.callback=true&getAndListenInstanceMetadata.return=true&getAndListenInstanceMetadata.sent=true&group=DUBBO-04-BOOT-PROVIDER&interface=org.apache.dubbo.metadata.MetadataService&methods=exportInstanceMetadata,getAndListenInstanceMetadata,getExportedServiceURLs,getExportedURLs,getExportedURLs,getExportedURLs,getExportedURLs,getExportedURLs,getInstanceMetadataChangedListenerMap,getMetadataInfo,getMetadataInfos,getMetadataURL,getServiceDefinition,getServiceDefinition,getSubscribedURLs,isMetadataService,serviceName,toSortedStrings,toSortedStrings,version&pid=12844&prefer.serialization=fastjson2,hessian2&qos.enable=true&register=false&release=3.2.0&revision=3.2.0&side=provider&timestamp=1690983137775&version=1.0.0], dubbo version: 3.2.0, current host: 192.168.8.1
2023-08-02 21:32:18.712  INFO 12844 --- [           main] o.a.d.r.c.m.ServiceInstanceMetadataUtils :  [DUBBO] Start registering instance address to registry., dubbo version: 3.2.0, current host: 192.168.8.1
2023-08-02 21:32:18.719  INFO 12844 --- [           main] o.a.d.c.d.DefaultApplicationDeployer     :  [DUBBO] Dubbo Application[1.1](DUBBO-04-BOOT-PROVIDER) is ready., dubbo version: 3.2.0, current host: 192.168.8.1
2023-08-02 21:32:18.725  INFO 12844 --- [           main] com.suns.Dubbo04BootProviderApplication  : Started Dubbo04BootProviderApplication in 3.018 seconds (JVM running for 3.866)
2023-08-02 21:32:18.733  INFO 12844 --- [pool-1-thread-1] .b.c.e.AwaitingNonWebApplicationListener :  [Dubbo] Current Spring Boot Application is await...

(三):构建consumer模块

公共配置:application.yml

共有配置application.yml
spring:
  application:
    name: DUBBO-05-BOOT-CONSUMER

dubbo:
  application:
    qos-enable: false

个性化配置:@DubboService

    @DubboReference(url = "dubbo://192.168.8.1:20880/com.suns.service.UserService")
    private UserService userService;

通过Junit的方式去测试:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
@SpringBootTest
class Dubbo05BootConsumerApplicationTests {
    
    //通过此注解进行注入
    @DubboReference(url = "dubbo://192.168.50.62:20880/com.suns.service.UserService")
    private UserService userService;

    @Test
    void contextLoads() {
    }

    @Test
    public void test1() {
        boolean ret = userService.login("xiaohei", "123456");
        System.out.println("ret = " + ret);
    }
}

test1方法执行结果:

2023-08-02 22:06:43.411  INFO 6584 --- [lientWorker-4-1] o.a.d.r.t.netty4.NettyClientHandler      :  [DUBBO] The connection of /192.168.8.1:29212 -> /192.168.8.1:20880 is established., dubbo version: 3.2.0, current host: 192.168.8.1
2023-08-02 22:06:43.419  INFO 6584 --- [           main] o.a.d.remoting.transport.AbstractClient  :  [DUBBO] Successfully connect to server /192.168.8.1:20880 from NettyClient 192.168.8.1 using dubbo version 3.2.0, channel is NettyChannel [channel=[id: 0xa68c5420, L:/192.168.8.1:29212 - R:/192.168.8.1:20880]], dubbo version: 3.2.0, current host: 192.168.8.1
2023-08-02 22:06:43.419  INFO 6584 --- [           main] o.a.d.remoting.transport.AbstractClient  :  [DUBBO] Start NettyClient /192.168.8.1 connect to the server /192.168.8.1:20880, dubbo version: 3.2.0, current host: 192.168.8.1
2023-08-02 22:06:43.467  INFO 6584 --- [           main] org.apache.dubbo.config.ReferenceConfig  :  [DUBBO] Referred dubbo service: [com.suns.service.UserService]. it's not GenericService reference, dubbo version: 3.2.0, current host: 192.168.8.1
2023-08-02 22:06:43.468  WARN 6584 --- [           main] o.a.d.r.client.metadata.MetadataUtils    :  [DUBBO] Remote Metadata Report Server is not provided or unavailable, will stop registering service definition to remote center!, dubbo version: 3.2.0, current host: 192.168.8.1, error code: 1-39. This may be caused by , go to https://dubbo.apache.org/faq/1/39 to find instructions. 
ret = false

 记录一次失败的原因:

消费者日志:

org.apache.dubbo.rpc.RpcException: Failed to invoke the method login in the service com.suns.service.UserService. Tried 3 times of the providers [192.168.8.1:20880] (1/1) from the registry 192.168.8.1:20880 on the consumer 192.168.8.1 using the dubbo version 3.2.0. Last error is: Failed to invoke remote method: login, provider: dubbo://192.168.8.1:20880/com.suns.service.UserService?application=DUBBO-05-BOOT-CONSUMER&background=false&executor-management-mode=isolation&file-cache=true&interface=com.suns.service.UserService&pid=13808&qos.enable=false&register.ip=192.168.8.1&side=consumer&sticky=false&unloadClusterRelated=false, cause: org.apache.dubbo.remoting.RemotingException: Fail to decode request due to: RpcInvocation [methodName=login, parameterTypes=null]

	at org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker.doInvoke(FailoverClusterInvoker.java:115)
	at org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker.invoke(AbstractClusterInvoker.java:341)
	at org.apache.dubbo.rpc.cluster.router.RouterSnapshotFilter.invoke(RouterSnapshotFilter.java:46)
	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
	at org.apache.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:101)
	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
	at org.apache.dubbo.rpc.cluster.filter.support.MetricsClusterFilter.invoke(MetricsClusterFilter.java:51)
	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
	at org.apache.dubbo.rpc.protocol.dubbo.filter.FutureFilter.invoke(FutureFilter.java:52)
	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
	at org.apache.dubbo.spring.security.filter.ContextHolderParametersSelectedTransferFilter.invoke(ContextHolderParametersSelectedTransferFilter.java:41)
	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
	at org.apache.dubbo.rpc.cluster.filter.support.ConsumerClassLoaderFilter.invoke(ConsumerClassLoaderFilter.java:40)
	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
	at org.apache.dubbo.rpc.cluster.filter.support.ConsumerContextFilter.invoke(ConsumerContextFilter.java:118)
	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CallbackRegistrationInvoker.invoke(FilterChainBuilder.java:194)
	at org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster$ClusterFilterInvoker.invoke(AbstractCluster.java:91)
	at org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker.invoke(MockClusterInvoker.java:103)
	at org.apache.dubbo.rpc.cluster.support.wrapper.ScopeClusterInvoker.invoke(ScopeClusterInvoker.java:124)

提供者日志:

java.io.IOException: Service com.suns.service.UserService:0.0.0 not found, invocation rejected.
	at org.apache.dubbo.rpc.protocol.PermittedSerializationKeeper.checkSerializationPermitted(PermittedSerializationKeeper.java:55) ~[dubbo-3.2.0.jar:3.2.0]
	at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:148) ~[dubbo-3.2.0.jar:3.2.0]
	at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:102) ~[dubbo-3.2.0.jar:3.2.0]
	at org.apache.dubbo.rpc.protocol.dubbo.DubboCodec.decodeBody(DubboCodec.java:173) [dubbo-3.2.0.jar:3.2.0]

最终原因:

@SpringBootApplication
@EnableDubbo
//@DubboComponentScan(basePackages = {"org.suns.service"})
public class Dubbo04BootProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(Dubbo04BootProviderApplication.class, args);
    }

}

服务没有被注册,也没有被暴露,调用的时候才会抛此异常!

08-03 04:09