SpringBoot整合Dubbo实战

初始化项目

从本小节开始,将基于 IntelliJ IDEA 进行工程的搭建以及测试。

如上图所示,可以建立一个基础的项目。

搭建了基础项目之后,我们还需要创建 dubbo-spring-boot-demo-interface 、dubbo-spring-boot-demo-provider 和 dubbo-spring-boot-demo-consumer 三个子模块。

创建了三个子模块之后,需要创建一下几个文件夹:

  1. 在 dubbo-spring-boot-demo-consumer/src/main/java 下创建 org.apache.dubbo.springboot.demo.consumer package

  2. 在 dubbo-spring-boot-demo-interface/src/main/java 下创建 org.apache.dubbo.springboot.demo package

  3. 在 dubbo-spring-boot-demo-provider/src/main/java 下创建 org.apache.dubbo.springboot.demo.provider package

添加 Maven 依赖

在初始化完项目以后,我们需要先添加 Dubbo 相关的 maven 依赖。

对于多模块项目,首先需要在父项目的 pom.xml 里面配置依赖信息。

编辑 ./pom.xml 这个文件,添加下列配置。

 <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>dubbo-spring-boot-demo-interface</module>
        <module>dubbo-spring-boot-demo-provider</module>
        <module>dubbo-spring-boot-demo-consumer</module>
    </modules>

    <properties>
        <dubbo.version>3.2.0-beta.4</dubbo.version>
        <spring-boot.version>2.7.8</spring-boot.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- Spring Boot -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- Dubbo -->
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-bom</artifactId>
                <version>${dubbo.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
                <version>${dubbo.version}</version>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring-boot.version}</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

然后在 dubbo-spring-boot-consumer 和 dubbo-spring-boot-provider 两个模块 pom.xml 中进行具体依赖的配置。

编辑 ./dubbo-spring-boot-consumer/pom.xml 和 ./dubbo-spring-boot-provider/pom.xml 这两文件,都添加下列配置。 

 <dependencies>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-demo-interface</artifactId>
            <version>${project.parent.version}</version>
        </dependency>

        <!-- dubbo -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
            <type>pom</type>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-reload4j</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- spring boot starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

    </dependencies>

在这份配置中,定义了 dubbo 和 zookeeper(以及对应的连接器 curator)的依赖。

添加了上述的配置以后,可以通过 IDEA 的 Maven - Reload All Maven Projects 刷新依赖。

定义服务接口

服务接口 Dubbo 中沟通消费端和服务端的桥梁。

在 dubbo-spring-boot-demo-interface 模块的 org.apache.dubbo.samples.api 下建立 DemoService 接口,定义如下:

package org.apache.dubbo.springboot.demo;

public interface DemoService {

    String sayHello(String name);
}

在 DemoService 中,定义了 sayHello 这个方法。后续服务端发布的服务,消费端订阅的服务都是围绕着 DemoService 接口展开的。

定义服务端的实现

定义了服务接口之后,可以在服务端这一侧定义对应的实现,这部分的实现相对于消费端来说是远端的实现,本地没有相关的信息。

dubbo-spring-boot-demo-provider 模块的 org.apache.dubbo.samples.provider 下建立 DemoServiceImpl 类,定义如下:

package org.apache.dubbo.springboot.demo.provider;

import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.springboot.demo.DemoService;

@DubboService
public class DemoServiceImpl implements DemoService {

    @Override
    public String sayHello(String name) {
        return "Hello " + name;
    }
}

在 DemoServiceImpl 中,实现了 DemoService 接口,对于 sayHello 方法返回 Hello name

注:在DemoServiceImpl 类中添加了 @DubboService 注解,通过这个配置可以基于 Spring Boot 去发布 Dubbo 服务。

配置服务端 Yaml 配置文件

从本步骤开始至第 7 步,将会通过 Spring Boot 的方式配置 Dubbo 的一些基础信息。

首先,我们先创建服务端的配置文件。

在 dubbo-spring-boot-demo-provider 模块的 resources 资源文件夹下建立 application.yml 文件,定义如下: 

dubbo:
  application:
    name: dubbo-springboot-demo-provider
  protocol:
    name: dubbo
    port: -1
  registry:
    address: zookeeper://${zookeeper.address:127.0.0.1}:2181

在这个配置文件中,定义了 Dubbo 的应用名、Dubbo 协议信息、Dubbo 使用的注册中心地址。

配置消费端 YAML 配置文件

同样的,我们需要创建消费端的配置文件。

在 dubbo-spring-boot-demo-consumer 模块的 resources 资源文件夹下建立 application.yml 文件,定义如下:

dubbo:
  application:
    name: dubbo-springboot-demo-consumer
  protocol:
    name: dubbo
    port: -1
  registry:
    address: zookeeper://${zookeeper.address:127.0.0.1}:2181

在这个配置文件中,定义了 Dubbo 的应用名、Dubbo 协议信息、Dubbo 使用的注册中心地址。

基于 Spring 配置服务端启动类

除了配置 Yaml 配置文件之外,我们还需要创建基于 Spring Boot 的启动类。

首先,我们先创建服务端的启动类。

在 dubbo-spring-boot-demo-provider 模块的 org.apache.dubbo.springboot.demo.provider 下建立 Application 类,定义如下:

package org.apache.dubbo.springboot.demo.provider;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubbo
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

在这个启动类中,配置了一个 ProviderApplication 去读取我们前面第 6 步中定义的 application.yml 配置文件并启动应用。

基于 Spring 配置消费端启动类

同样的,我们需要创建消费端的启动类。

在 dubbo-spring-boot-demo-consumer 模块的 org.apache.dubbo.springboot.demo.consumer 下建立 Application 类,定义如下:

package org.apache.dubbo.springboot.demo.consumer;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubbo
public class ConsumerApplication {

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

在这个启动类中,配置了一个 ConsumerApplication 去读取我们前面第 7 步中定义的 application.yml 配置文件并启动应用。

配置消费端请求任务

除了配置消费端的启动类,我们在 Spring Boot 模式下还可以基于 CommandLineRunner去创建

在 dubbo-spring-boot-demo-consumer 模块的 org.apache.dubbo.springboot.demo.consumer 下建立 Task 类,定义如下:

package org.apache.dubbo.springboot.demo.consumer;

import java.util.Date;

import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.springboot.demo.DemoService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class Task implements CommandLineRunner {
    @DubboReference
    private DemoService demoService;

    @Override
    public void run(String... args) throws Exception {
        String result = demoService.sayHello("world");
        System.out.println("Receive result ======> " + result);

        new Thread(()-> {
            while (true) {
                try {
                    Thread.sleep(1000);
                    System.out.println(new Date() + " Receive result ======> " + demoService.sayHello("world"));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
            }
        }).start();
    }
}

在 Task 类中,通过@DubboReference 从 Dubbo 获取了一个 RPC 订阅,这个 demoService 可以像本地调用一样直接调用。在 run方法中创建了一个线程进行调用。

启动应用

截止第 10 步,代码就已经开发完成了,本小节将启动整个项目并进行验证。

首先是启动 org.apache.dubbo.samples.provider.Application ,等待一会出现如下图所示的日志(Current Spring Boot Application is await)即代表服务提供者启动完毕,标志着该服务提供者可以对外提供服务了。

[Dubbo] Current Spring Boot Application is await...

然后是启动org.apache.dubbo.samples.client.Application ,等待一会出现如下图所示的日志(Hello world )即代表服务消费端启动完毕并调用到服务端成功获取结果。

Receive result ======> Hello world 

直连提供者 

在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,所以,这种情况下,我们只需要直接连接服务端的地即可,其实,这种方法在前面的讲解已经使用到了,第一种讲解的方式就是这种方式,因为这种方式简单。

使用

<dubbo:reference id="providerService"
                     interface="com.sihai.dubbo.provider.service.ProviderService"
                     url="dubbo://192.168.234.1:20880/com.sihai.dubbo.provider.service.ProviderService"/>

说明:可以看到,只要在消费端在 dubbo:reference 节点使用 url 给出服务端的方法即可。

只订阅

只订阅就是只能够订阅服务端的服务,而不能够注册。

引用官方的使用场景如下:

为方便开发测试,经常会在线下共用一个所有服务可用的注册中心,这时,如果一个正在开发中的服务提供者注册,可能会影响消费者不能正常运行。
可以让服务提供者开发方,只订阅服务(开发的服务可能依赖其它服务),而不注册正在开发的服务,通过直连测试正在开发的服务。
<dubbo:registry register="false" protocol="zookeeper" address="localhost:2181,localhost:2182,localhost:2183" check="false"/>

使用只订阅方式

当在服务提供端使用 register="false" 的时候,我们使用下面的方式获取服务端的服务;

<dubbo:reference cluster="failover" retries="2" check="false" id="providerService"
                     interface="com.sihai.dubbo.provider.service.ProviderService"/>

启动信息 

发现,这时候并不是向注册中心 zookeeper 注册,而只是做了发布服务和启动netty

② 不使用只订阅方式

<dubbo:registry protocol="zookeeper" address="localhost:2181,localhost:2182,localhost:2183" check="false"/>

启动信息

可以发现,这里就向注册中心 zookeeper 注册了。

只注册

只注册正好跟前面的只订阅相反,这个时候可以向注册中心注册,但是,消费端却不能够读到服务。

应用场景

如果有两个镜像环境,两个注册中心,有一个服务只在其中一个注册中心有部署,另一个注册中心还没来得及部署,而两个注册中心的其它应用都需要依赖此服务。这个时候,可以让服务提供者方只注册服务到另一注册中心,而不从另一注册中心订阅服务。

使用说明

<dubbo:registry subscribe="false" address="localhost:2181"></dubbo:registry>

在服务端的 dubbo:registry 节点下使用 subscribe="false" 来声明这个服务是只注册的服务。

这个时候消费端调用的时候是不能调用的。

多协议机制 

在前面我们使用的协议都是 dubbo 协议,但是 dubbo 除了支持这种协议外还支持其他的协议,比如,rmi、hessian等,另外,而且还可以用多种协议同时暴露一种服务。

使用方法

① 一种接口使用一种协议

先声明多种协议

 <!--当前服务发布所依赖的协议;webserovice、Thrift、Hessain、http-->
    <dubbo:protocol name="dubbo" port="20880"/>
    <dubbo:protocol name="rmi" port="1099" />

然后在发布接口的时候使用具体协议

<!--服务发布的配置,需要暴露的服务接口-->
    <dubbo:service cluster="failover" retries="2"
            interface="com.sihai.dubbo.provider.service.ProviderService"
            ref="providerService"/>
    <dubbo:service cluster="failover" retries="2"
                   interface="com.sihai.dubbo.provider.service.ProviderService"
                   ref="providerService" protocol="rmi"/>

在输出日志中,就可以找到rmi发布的接口。

rmi://192.168.234.1:1099/com.sihai.dubbo.provider.service.ProviderService?anyhost=true&application=provider&bean.name=com.sihai.dubbo.provider.service.ProviderService&cluster=failover&dubbo=2.0.2&generic=false&interface=com.sihai.dubbo.provider.service.ProviderService&methods=SayHello&owner=sihai&pid=796&retries=2&side=provider&timestamp=1564281053185, dubbo version: 2.6.6, current host: 192.168.234.1

② 一种接口使用多种协议
声明协议和上面的方式一样,在发布接口的时候有一点不一样。

<dubbo:service cluster="failover" retries="2"
                   interface="com.sihai.dubbo.provider.service.ProviderService"
                   ref="providerService" protocol="rmi,dubbo"/>

说明:protocol属性,可以用,隔开,使用多种协议。

多注册中心

Dubbo 支持同一服务向多注册中心同时注册,或者不同服务分别注册到不同的注册中心上去,甚至可以同时引用注册在不同注册中心上的同名服务。

服务端多注册中心发布服务

一个服务可以在不同的注册中心注册,当一个注册中心出现问题时,可以用其他的注册中心。

注册

<!--多注册中心-->
    <dubbo:registry protocol="zookeeper" id="reg1" timeout="10000" address="localhost:2181"/>
    <dubbo:registry protocol="zookeeper" id="reg2" timeout="10000" address="localhost:2182"/>
    <dubbo:registry protocol="zookeeper" id="reg3" timeout="10000" address="localhost:2183"/>

发布服务

<!--服务发布的配置,需要暴露的服务接口-->
    <dubbo:service cluster="failover" retries="2"
            interface="com.sihai.dubbo.provider.service.ProviderService"
            ref="providerService" registry="reg1"/>
    <dubbo:service cluster="failover" retries="2"
                   interface="com.sihai.dubbo.provider.service.ProviderService"
                   ref="providerService" protocol="rmi" registry="reg2"/>

说明:使用registry="reg2"指定该接口使用的注册中心,同时也可以使用多个,用隔开,例如,registry="reg1,,reg2"

消费端多注册中心引用服务

首先,先向不同注册中心注册;

<!--多注册中心-->
    <dubbo:registry protocol="zookeeper" id="reg1" timeout="10000" address="localhost:2181"/>
    <dubbo:registry protocol="zookeeper" id="reg2" timeout="10000" address="localhost:2182"/>
    <dubbo:registry protocol="zookeeper" id="reg3" timeout="10000" address="localhost:2183"/>

其次,不同的消费端服务引用使用不同的注册中心;

!--不同的服务使用不同的注册中心-->
    <dubbo:reference cluster="failover" retries="2" check="false" id="providerService"
                     interface="com.sihai.dubbo.provider.service.ProviderService" registry="reg1"/>
    <dubbo:reference cluster="failover" retries="2" check="false" id="providerService2"
                     interface="com.sihai.dubbo.provider.service.ProviderService" registry="reg2"/>

说明:上面分别使用注册中心1和注册中心2。

多版本

不同的服务是有版本不同的,版本可以更新并且升级,同时,不同的版本之间是不可以调用的。

<!--服务发布的配置,需要暴露的服务接口-->
    <dubbo:service cluster="failover" retries="2"
            interface="com.sihai.dubbo.provider.service.ProviderService"
            ref="providerService" registry="reg1" version="1.0.0"/>
    <dubbo:service cluster="failover" retries="2"
                   interface="com.sihai.dubbo.provider.service.ProviderService"
                   ref="providerService" protocol="rmi" registry="reg2" version="1.0.0"/>

加入了版本控制。

日志管理

dubbo 也可以将日志信息记录或者保存到文件中的。

① 使用accesslog输出到log4j

<dubbo:protocol accesslog="true" name="dubbo" port="20880"/>
    <dubbo:protocol accesslog="true" name="rmi" port="1099" />

② 输出到文件

<dubbo:protocol accesslog="http://localhost/log.txt" name="dubbo" port="20880"/>
    <dubbo:protocol accesslog="http://localhost/log2.txt" name="rmi" port="1099" />
  • 23
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值