springboot整合dubbo

1.什么是rpc

要知道什么是rpc,就要了解rpc产生的背景,这就涉及到进程通信问题。

在单体时代,系统所有功能都集中一起,本地方法直接调用接口,简单方便。而在微服务时代,原本单独系统被分割为多份,一个系统中的方法不可能直接被另外一个系统调用。为解决这个问题,就引入所谓的远程调用,像socket、tcp/udp、http等都属于远程调用。

tcp和http底层也是基于socket实现,再调用时候,需要做很多工作,像tcp的报文设置、黏包处理,http的请求头设置、返回解析等。虽然能实现远程调用,但使用起来肯定没有本地方法调用那么简单。那有没有这种技术,能把远程调用简单到像本地调用一样呢?有,这就是rpc(远程过程调用)。

rpc强调面向过程调用,把远程调用的很多底层细节都给你做好,整个调用过程对你是透明的。你只需像调用本地方法一样简单。

2.rpc调用过程

以server、client举例。server提供接口方法,client负责调用。过程如下:

client:

client-》本地调用-》方法名、参数类型、参数值打包序列化-》网络传输-》server-》

server:

server-》接收数据-》反序列化-》-》拿到方法名,参数等-》本地方法调用-》将结果和类型序列化-》网络传输-》client-》

client:

client-》拿到结果-》反序列化-》得到数据

更详细的流程,可参考:https://blog.csdn.net/w372426096/article/details/88352833

3.什么是dubbo

从rpc调用过程可知,其中涉及到序列化和反序列化、网络传输、调用策略(负载均衡、熔断等)等。此外,一个完善的rpc框架,还会有服务治理等功能。而这些,都有业内大牛已经给你做好了,直接使用即可。(当然,能力强,自己实现也行)。目前,比较知名的rpc框架有,Dubbo、Motan、Tars、Thrift、gRPC。对,没错,dubbo就是一个rpc框架,这就是dubbo。

4.dubbo原理

这是dubbo官网的图片。整个dubbo调用过程,可以概括为:

1.当服务生产者启动后,会将服务信息(ip、port、接口)等信息注册到注册中心上。

2.服务消费者启动后,会监听注册中心,拿到服务生产者的列表,缓存在本地。

3.后续生产者如果下线,会立刻通知消费者。消费者重新拉取生产者列表。

4.消费者轮询或随机从本地缓存列表中拿出一个,进行接口调用。

5.生产者和消费者将调用数据发送监控中心,做监控使用。

5.springboot集成dubbo 

 5.1项目结构

项目采用maven父子结构,子模块共四个,分别为:api、consumer、provide、provide1。其中,api是公共接口模块,consumer是消费者模块,provide为生成者模块。截图如下:

子模块结构展开如下:

5.2 api模块代码

5.2.1 公共接口类

package com.qxmz.service;

public interface DemoDubboService {
    String showMsg(String str);
}

 5.2.2 pom文件内容

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!--    <parent>-->
<!--        <artifactId>maven</artifactId>-->
<!--        <groupId>com.qxmz.maven</groupId>-->
<!--        <version>1.0-SNAPSHOT</version>-->
<!--    </parent>-->
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.qxmz.maven</groupId>
    <artifactId>api</artifactId>
    <version>1.0-SNAPSHOT</version>

</project>

5.2.3 配置文件

5.3 provide模块代码

5.3.1 公共接口实现类

package com.qxmz.service;

import org.apache.dubbo.config.annotation.Service;

/**
 * @description:
 * @author: junzhang
 * @time: 2021/7/21 14:55
 */
@Service
public class DemoDubboServiceImpl implements DemoDubboService {
    @Override
    public String showMsg(String str) {
        return "Hello Dubbo--8030 " + str;
    }
}

注意:此处的@Service不是springboot的注解,而是dubbo的注解。

5.3.2 pom文件内容

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>maven</artifactId>
        <groupId>com.qxmz.maven</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>


    <modelVersion>4.0.0</modelVersion>

    <artifactId>provide</artifactId>

</project>

5.3.2 配置文件:application.yml

dubbo:
  application:
    name: myProvider
  registry:
    address: zookeeper://192.168.88.204:2181?backup=192.168.88.205:2182,192.168.88.206:2183
    timeout: 15000

  protocol:
    name: dubbo
    port: 20880
  scan:
    base-packages: com.qxmz.service
server:
  port: 8030

provied1和provide的内容一样,不再单独展示。

5.4 consumer模块代码

5.4.1 公共接口调用类

package com.qxmz.service;

import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;

/**
 * @description:
 * @author: junzhang
 * @time: 2021/7/21 16:39
 */
@Service
public class TestService {
    @Reference
    DemoDubboService demoDubboService;

    public String getMsg(String str) {
        return demoDubboService.showMsg(str);
    }
}

注意:此处的@Service是springboot的注解,不要与provide中的搞混淆。

5.4.2 controller类

package com.qxmz.controller;

import com.qxmz.service.TestService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @description:
 * @author: junzhang
 * @time: 2021/7/21 16:38
 */
@RestController
public class TestController {
    @Resource
    TestService testService;

    @RequestMapping("/getMsg")
    public String getMsg(String str) {
        return testService.getMsg(str);
    }
}

5.4.3 pom文件内容

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>maven</artifactId>
        <groupId>com.qxmz.maven</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>consumer</artifactId>


</project>

5.4.4 配置文件:application.yml

dubbo:
  application:
    name: myConsumer
  registry:
    address: zookeeper://192.168.88.204:2181?backup=192.168.88.205:2182,192.168.88.206:2183
    timeout: 10000

  protocol:
    name: dubbo
server:
  port: 8032

5.5 父模块中的pom文件内容

子模块中所有的依赖,我都放在父pom文件中了,主要的依赖都是consumer和provide需要的。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.qxmz.maven</groupId>
    <artifactId>maven</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>api</module>
        <module>provide</module>
        <module>consumer</module>
        <module>provide1</module>
    </modules>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-zookeeper</artifactId>
            <version>2.7.4</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.curator</groupId>
                    <artifactId>curator-recipes</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.qxmz.maven</groupId>
            <artifactId>api</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

5.6 注册中心说明

项目中dubbo的注册中心,我使用的是zookeeper,且是集群模式。你也可以使用单机模式,或者使用其他注册中心。

5.7 调用演示

依次重启两个provide和一个consumer,然后在浏览器上直接访问http://localhost:8032/getMsg。多次访问后,可以看到返回值是有变化的。在多个provide存在情况下,dubbo默认是随机调用的。其实,这里就体现了负载均衡的功能。

5.8 zookeeper中的注册信息

生产者和消费者启动后,会向注册中心注册自身信息。如下两个节点中对应的就是消费者和生产者的接口信息。

5.9 问题记录

如果是其他项目要实现公共接口,只需要在他的项目中引入公共接口的依赖就行。针对该项目,依赖如下:

        <dependency>
            <groupId>com.qxmz.maven</groupId>
            <artifactId>api</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>

不过,我在本地测试时候遇到一个问题。就是添加依赖后,更新maven也没有报错。但在实现类中,就是导入不了包。

后来排查发现,是在创建api子模块时候,使用的模板是springboot模板。打包时候,就变成了可以运行的jar包,这个时候,就引入不了对应的包名。

后面基于maven,重新建了一个空项目作为api模块,重新构建后就没有这个问题。

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值