dubbo3使用grpc开发分布式服务

前言:本文已经默认你已经会dubbo基本的操作,本文将从入门项目配置到最后测试grpc接口,一步步的解决其中的问题,我的业务模型是电商项目,当然只提供个参考 我的github地址

1.建立项目骨架

采用聚合项目工程,默认读者已经会了,最后结构大致如下 |root |---serviceInterface----| | pom.xml |----OrderService---| | pom.xml | |-------| | pom.xml pom.xml

1.1首先在父工程里面做好相关的版本管理

xml 复制代码
先定义版本属性
<!-- Dubbo 相关 -->
<dubbo.version>3.3.5</dubbo.version>
<protoc-gen-dubbo.version>3.3.5</protoc-gen-dubbo.version>
<dubbo-nacos.version>3.3.5</dubbo-nacos.version>

<!-- Protobuf -->
<protobuf.version>3.24.4</protobuf.version>

下面做好dipendencyManangment,这样子项目就不用带版本了
```
<dependencyManagement>
    <dependencies>
        <!--dubbo依赖-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
        <!--2.dubbo-nacos注册中心-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-nacos</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
<dependencyManagement>

然后子项目分别导入这两个依赖,因为业务项目需要用到生成的stub代码,所以业务项目导入接口项目即serviceInterface项目,注意serviceInterface项目需要在业务项目之前就编译好,要不然会造成不同步问题,即修改了proto文件后,业务项目找不到新加的proto生成的代码,陷入到编译报错循环中,解决办法是接口模块需要排在最全面,这样接口模块就可以先编译,子项目就能及时同步

接下来聚焦于ServiceIntervace模块

xml 复制代码
        首先导入依赖
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-rpc-triple</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>${protobuf.version}</version>
        </dependency>
        导入编译插件
        ```
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-maven-plugin</artifactId>
            <version>${protoc-gen-dubbo.version}</version>
            <configuration>
                <outputDir>${project.build.directory}/generated-sources/protobuf/java</outputDir>
                <protoSourceDir>${basedir}/src/main/proto</protoSourceDir>
                <protocVersion>${protobuf.version}</protocVersion>
                <dubboGenerateType>tri</dubboGenerateType>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                    <phase>generate-sources</phase>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>kr.motd.maven</groupId>
                    <artifactId>os-maven-plugin</artifactId>
                    <version>1.7.0</version>
                </dependency>
            </dependencies>
        </plugin>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <version>3.5.0</version>
            <executions>
                <execution>
                    <id>add-source</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>add-source</goal>
                    </goals>
                    <configuration>
                        <sources>
                            <!-- 与 dubbo-maven-plugin 的 outputDir 保持一致 -->
                            <source>${project.build.directory}/generated-sources/protobuf/java</source>
                        </sources>
                    </configuration>
                </execution>
            </executions>
        </plugin>

    </plugins>

</build>

随后就开始编写proto文件了,插件里面可以配置proto文件的目录,当然我们选择默认的在src.main目录下新建立一个proto目录,我的结构如下

分别定义好模型和rpc接口,下面讲一下proto文件的写法

2如何编写proto文件

2.1定义业务模型

ini 复制代码
syntax = "proto3";
package item;
option java_package = "top.minkun.itemService.model";
option java_multiple_files = true;
import "google/protobuf/timestamp.proto";

message Items{
  repeated Item items = 1;
}
message Item {
  // 商品id
  int64  id = 1;
  // SKU名称
  string name = 2;
  // 价格(分)
  int32  price = 3;
  // 库存数量
  int32  stock = 4;
  // 商品图片
  string image = 5;
  // 类目名称
  string category = 6;
  // 品牌名称
  string brand = 7;
  // 规格
  string spec = 8;
  // 销量
  int32  sold = 9;
  // 评论数
  int32  comment_count = 10;
  // 是否是推广广告
  bool   is_ad = 11;
  // 商品状态:1-正常,2-下架,3-删除
  int32  status = 12;
}
// -----------------------item page query---------------------------------------------------
message ItemPageQueryReq {
  int32 page_no   = 1;   // 当前页
  int32 page_size = 2;   // 每页条数
  bool is_Asc = 3;
  string sort_by = 4;
}
message ItemPageQueryResp {
  int64 total = 1;
  int64 pages = 2;
  repeated Item item_list = 3;
}

// -----------------------------item query by id / ids --------------------------------------
// 批量查询
message QueryItemsByIdsReq {
  repeated int64 ids = 1;
}
// 单个查询
message QueryItemByIdReq {
  int64 id = 1;
}

// --------------------------add new Item ------------------------------------------------------
// 新增
message ItemSaveReq {
  Item item = 1;
}

// ----------------------------update------------------------------------------------------
//更新商品状态
message UpdateItemStatusReq{
  // 商品id
  int64  id = 1;
  //  商品状态
  int32 status = 2;
}
// 更新商品
message UpdateItemReq {
  Item item = 1;
}
// 更新状态
message UpdateStatusReq {
  int64 id     = 1;
  int32 status = 2;
}
// ---------------------------------------delete---------------------------------------
message DeleteItemByIdReq{
  int64 id = 1;
}
message DeleteItemsByIdsReq{
  repeated int64 id = 1;
}
// 批量扣减库存
message StockDeductReq {
  repeated OrderDetailDTO items = 1;
}
message OrderDetailDTO {
  // 商品Id
  int64 item_id = 1;
  // 下单数量
   int32 num = 2;
}
// 商品状态枚举
enum ItemStatus {
  // 未指定
  ITEM_STATUS_UNSPECIFIED = 0;
  // 正常
  NORMAL       = 1;
  // 下架
  OFF_SHELF    = 2;
  // 删除
  DELETED      = 3;
}

定义rpc接口

scss 复制代码
syntax = "proto3";
package item;
option java_package = "top.minkun.itemService.rpc";
option java_multiple_files = true;
import "item-service/model.proto";
import "common/common.proto";

//商品管理相关服务
service ItemGRPCService{

    //分页查询商品
  rpc queryItemByPage(ItemPageQueryReq) returns (ItemPageQueryResp);

  // 根据id批量查询商品
  rpc queryItemByIds(QueryItemsByIdsReq) returns (Items);

  // 根据id查询单个商品
  rpc queryItemById(QueryItemByIdReq) returns (Item);

  // 新增商品
  rpc saveItem(Item) returns (top.minkun.Empty);

  // 更新商品状态
  rpc updateItemStatus(UpdateItemStatusReq) returns (top.minkun.Empty);

  // 更新商品信息
  rpc updateItem(Item) returns (top.minkun.Empty);


  // 根据id删除商品
  rpc deleteItemById(DeleteItemByIdReq) returns (top.minkun.Empty);

  // 批量扣减库存
  rpc deductStock(StockDeductReq) returns (top.minkun.Empty);
}

然后另外的服务也是如此 最后编写完成后我们可以maven clean install 就能推送到本地仓库了,推荐直接从root项目目录那里install,这样全部的项目都能同步了

3.使用代码

3.1作为服务提供者 按照前面的,已经把ServiceInterface里面的接口编译并推送到本地仓库,现在只需要导入改模块依赖,然后继承生成的这个DubboOrderGRPCServiceTriple.OrderGRPCServiceImplBase类,然后重写里面定义的业务方法即可

作为服务消费者,只需加入DubboReference注解即可注入目标类

如何测试

由于dubbo的grpc并未提供服务器反射即server reflection功能,导致不能通过grpcurl查看有哪些方法,测试起来比较麻烦,接下来介绍如何使用apifox进行grpc测试, 首先建立grpc项目即可,然后导入我们编写的proto文件,然后添加依赖目录,即该proto文件import了什么文件,apifox会递归拆解目录查看是否有文件,我们导入proto目录和下面两个google提供的官方依赖的目录即可

最后导入后如下

这里我之前在user服务下写了一个hello的rpc方法方便进行测试,当然这些rpc接口,并且重新了对应方法的都可进行测试,然后我启动了user服务,记得把enable注解打开,并在yaml文件里面配置,注册中心可根据自己的目标自行配置,注册中心这块,dubbo默认会注册双服务,以为了版本兼容,我们可以把register-mode: instance # 立即注册即可

测试结果如下,正常返回了模型

相关推荐
一只韩非子3 小时前
Spring AI Alibaba 快速上手教程:10 分钟接入大模型
java·后端·ai编程
起风了___4 小时前
20 分钟搞定:Jenkins + Docker 一键流水线,自动构建镜像并部署到远程服务器
后端
用户4099322502124 小时前
如何在 FastAPI 中巧妙覆盖依赖注入并拦截第三方服务调用?
后端·ai编程·trae
泉城老铁4 小时前
Spring Boot中实现多线程分片下载
java·spring boot·后端
泉城老铁4 小时前
Spring Boot中实现多文件打包下载
spring boot·后端·架构
泉城老铁4 小时前
Spring Boot中实现大文件分片下载和断点续传功能
java·spring boot·后端
码事漫谈5 小时前
C++中虚函数与构造/析构函数的深度解析
后端
百思可瑞教育5 小时前
Spring Boot 参数校验全攻略:从基础到进阶
运维·服务器·spring boot·后端·百思可瑞教育·北京百思教育
武子康5 小时前
大数据-89 Spark应用必备:进程通信、序列化机制与RDD执行原理
大数据·后端·spark