前言:本文已经默认你已经会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 # 立即注册即可
测试结果如下,正常返回了模型
