1、Dubbo3入门
本文章使用2022年9月Dubbo3.1.1版本。如果时过迁境,本篇文章经供参考。
学习Dubbo需要部分微服务思想,nacos相关知识,以及可能需要docker-conpose将nacos跑起来。
1.1、什么是Dubbo
Apache Dubbo 是一款 RPC 微服务框架,提供了包括 Java、Golang 等在内的多种语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力, 利用 Dubbo 提供的丰富服务治理特性,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。Dubbo 被设计为高度可扩展,用户可以方便的实现流量拦截、选址的各种定制逻辑。
Dubbo和OpenFeign有什么区别?
Dubbo比OpenFeign更加的灵活,功能集成度更高,虽然后续OpenFeign增加了更多的远程调用协议和序列化协议。但Dubbo还拥有原生的服务发现,负载均衡,流量调度等功能。同时,他的架构复杂度比OpenFeign更高,因此对未来协议的适配程度更高,二次开发灵活度也更高。并且,Dubbo也在做云原生的一些事情。
1.2、体验Dubbo
我们以SpringBoot为例,简单去体验一下Dubbo3的使用。
强烈建议你使用jdk8,不然需要解决一个麻烦的反射报错。
如果你只想得到测试demo,那么可以访问:hy-dubbo-demo项目地址
1.2.1、先知
由于Dubbo的版本是强依赖性的,因此建议与我版本高度一致。
- jdk8
- nacos2.1.1
- dubbo3.1.1
明确Dubbo远程调用要做的事情
- 添加Dubbo核心依赖
- 添加要使用的注册中心与Dubbo整合的依赖
- 添加要使用的协议依赖
- 配置Dubbo基本信息
1.2.2、公用包准备
公用包一般来说是去包含远程调用过程中的接口和实体类。
1.服务提供方对接口进行实现后,我们服务调用方需要注入接口,才能知晓具体调用的是哪个服务。因此双方都必须明确接口。
有个小细节,服务提供者是对接口进行实现并注册到注册中心中的,而服务消费者是直接使用接口进行注入,这属于DI的内容,也可以理解为高级多态(父类的引用指向子类的实现)。
2.实体类在Dubbo远程调用国产中需要双方序列化,因此必须实现 Serializable
序列化接口 ,否则会报错
1.项目结构
2.pom依赖
我们只需要实体类的一些get和set方法即可,引入lombok就行
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
</dependencies>
3.pojo
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private Integer id;
private String username;
}
4.Service
public interface UserService {
User getUser(Integer id);
}
1.2.3、服务提供方
当然,在这个环节,我们就需要跑一个注册中心了,我使用的是nacos2.1.1。
1.项目结构
2.pom依赖
由于我们dubbo使用的是3.1.1版本,所以相关的spring-boot依赖,rpc协议依赖和Dubbo注册中心依赖均使用3.1.1版本。请你注意,一般Spring,SpringBoot,注册中心,Dubbo这一系列的中间件都是配套的,因此他们的版本号最好使用官方推荐的。spring-cloud-alibaba中文组件说明
当然,我这里使用的是最新版本,也只是测试环境下使用。通常来讲以Dubbo版本为例,其他依赖包均为此版本。
<dependencies>
<!-- 引入公用包 -->
<dependency>
<groupId>com.hy</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- springboot的一些依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Dubbo的相关依赖-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-dubbo</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<version>3.1.1</version>
</dependency>
</dependencies>
3.启动类
启动类需要使用 @EnableDubbo
注解来声明我们开启Dubbo。
@SpringBootApplication
@EnableDubbo
public class DubboProviderApplication {
public static void main(String[] args) {
SpringApplication.run(DubboProviderApplication.class, args);
}
}
4.Service
对于服务提供方而言,我们需要使用 @DubboService
注解,作用是将此Service作为一个服务在注册中心中注册。
@DubboService
public class UserServiceImpl implements UserService {
@Override
public User getUser(Integer id) {
return new User(id, "坏银");
}
}
5.配置文件
在配置文件中,我们主要是配置应用名,以及注册中心的一些相关配置。对于nacos而言,则是命名空间,分组,地址,用户名,密码等等。这里为了减少负担,大多都采用默认配置类。
server:
port: 9200
spring:
application:
name: dubbo-provider
dubbo:
application:
name: hy-dubbo-provider
registry:
address: nacos://localhost:8848
username: nacos
password: nacos
1.2.4、服务消费方
1.项目结构
2.pom依赖
与服务提供方一致
<dependencies>
<!-- 引入公用包 -->
<dependency>
<groupId>com.hy</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- springboot的一些依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Dubbo的相关依赖-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-dubbo</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<version>3.1.1</version>
</dependency>
</dependencies>
3.Serice
在服务消费方,我们需要调用服务提供方的接口,我们只需要使用 @DubboReference
装配接口即可。Dubbo会自己将远程调用,负载均衡,序列化等等过程解决的。不需要我们手动解决。这也是Dubbo的亮点,远程调用像本地调用一样简单。
@Service
public class OrderService {
@DubboReference
private UserService userService;
public String createOrder() {
User user = userService.getUser(6905);
System.out.println("成功创建订单");
return user.toString() + "已经成功为用户创建订单";
}
}
4.配置文件
此处的配置文件配置的内容与服务提供方无异。
server:
port: 9201
spring:
application:
name: dubbo-consumer
dubbo:
protocol:
host: 127.0.0.1
application:
name: hy-dubbo-consumer
registry:
address: nacos://localhost:8848
username: nacos
password: nacos
tips:
服务消费方主启动类上可以不使用@EnableDubbo注解
服务消费方默认是不在注册中心注册的
1.2.5、报错问题
1.反射报错
如果你使用的是jdk8以上,大概率会报反射错误,我们需要在java的运行环境上加上:
--illegal-access=deny
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/sun.net.util=ALL-UNNAMED
--add-opens java.base/java.math=ALL-UNNAMED
2.实体类未实现序列化接口
如果你的公用实体类没有实现 Serializable
接口,那么在远程调用过程中使用了该实体,必然报错。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private Integer id;
private String username;
}
1.3、Dubbo使用说明
实际上,Dubbo的使用是非常简单的。步骤如下:
- 定义服务接口
- 配置Dubbo配置文件,配置中心,序列化,网络协议等等
- 服务提供方暴露接口,可以使用
DubboService
- 服务提供方定义Spring Boot主函数,可以使用
@EnableDubbo
- 服务消费方调用远程服务即可,
DubboReference
Dubbo 抽象了一系列的结构化配置,对不同的用户而言,既可以以最小化配置快速启动服务,又可以在需要时通过复杂的配置精确的控制服务行为; 除了 API + Properties 的基本使用方式之外,通过与 Spring 的集成 Dubbo 在配置形式上还支持 SpringBoot、Annotation、XML、YAML 等。
因此,我们上述使用的流程是常用且便捷的流程,但并不代表非他不可。
1.4、Dubbo原理
1.5、Dubbo3新特性
Dubbo3有几个很重要的新特性
- 应用级服务发现
- Triple,自研通信协议
- 跨语言调用
- Dubbo Mesh
1.5.1、应用级服务发现
应用级的服务发现,实际上是注册模型的改变。在服务注册领域中,市面上有两种常见的模型,一种是应用级注册,一种是接口级注册。在Spring Cloud中,一个应用就是一个微服务。而在Dubbo2中,一个接口就会被注册成为一个微服务。Dubbo3优化了注册模型,将Dubbo2的接口级注册转变成为Dubbo3的应用级注册。
官方文档:Dubbo2和Dubbo3在Nacos中的注册数据
我们以官方文档的图,来对比一下
1.Dubbo2
下面是nacos1中的注册实例,如果你点开观察注册元数据,就会发现他是一个接口,也就是一个方法就注册一个数据。
使用@DubboService注解下的每个方法都注册一个应用
2.Dubbo3
而对于Dubbo3和Nacos2中,他是以应用名来进行注册的。并且同时也会注册这个应用的实例。
Dubbo3 默认采用 “应用级服务发现 + 接口级服务发现” 的双注册模式,因此会发现应用级服务(应用名)和接口级服务(接口名)同时出现在 Nacos 控制台,可以通过配置
dubbo.registry.register-mode=instance/interface/all
来改变注册行为。笼统的来说就是,将@DubboService注解下的Service注册成一个应用,并且还会将此jar包运行包注册成为一个应用。
Dubbo3 服务发现模型更适合构建可伸缩的服务体系,这点要如何理解? 这里先举个简单的例子,来直观的对比 Dubbo2 与 Dubbo3 在地址发现流程上的数据流量变化:假设一个微服务应用定义了 100 个接口(Dubbo 中的服务), 则需要往注册中心中注册 100 个服务,如果这个应用被部署在了 100 台机器上,那这 100 个服务总共会产生 100 * 100 = 10000 个虚拟节点;而同样的应用, 对于 Dubbo3 来说,新的注册发现模型只需要 1 个服务(只和应用有关和接口无关), 只注册和机器实例数相等的 1 * 100 = 100 个虚拟节点到注册中心。 在这个简单的示例中,Dubbo 所注册的地址数量下降到了原来的 1 / 100,对于注册中心、订阅方的存储压力都是一个极大的释放。更重要的是, 地址发现容量彻底与业务 RPC 定义解耦开来,整个集群的容量评估对运维来说将变得更加透明:部署多少台机器就会有多大负载,不会像 Dubbo2 一样, 因为业务 RPC 重构就会影响到整个集群服务发现的稳定性。
1.5.2、Triple(新一代RPC通信协议)
Triple 是 Dubbo3 提出的基于 HTTP2 的开放协议,旨在解决 Dubbo2 私有协议带来的互通性问题。他完全兼容gRPC协议(实现差不多,可以认为是两兄弟),并在此基础上拓展出更丰富的语义。相比于原有 Dubbo2 协议,Triple 有以下优势:
- 原生和 gRPC 协议互通。打通 gRPC 生态,降低从 gRPC 至 Dubbo 的迁移成本。
- 增强多语言生态。避免因 CPP/C#/RUST 等语言的 Dubbo SDK 能力不足导致业务难以选型适配的问题。
- 网关友好。网关无需参与序列化,方便用户从传统的 HTTP 转泛化 Dubbo 调用网关升级至开源或云厂商的 Ingress 方案。
- 完善的异步和流式支持。带来从底层协议到上层业务的性能提升,易于构建全链路异步以及严格保证消息顺序的流式服务。
我们可以具体了解一下为啥叫网关友好。
在传统微服务中,用户一般是使用http请求调用服务的,http请求网关后,由网关进行转发请求,实际上转发的过程是网关进行gRPC调用微服务接口的过程。那么网关需要将http请求体,转化成为gRPC请求进行调用的,这个过程性能损耗比较大。
而使用Triple协议,网关依然是需要转化的,他是Http2.0实现的,并且也兼容gRPC协议,因此网关转化的代价很小,性能也就更高的。
网关转化的代价主要是什么?主要是做了一个无用的序列化和反序列化操作。由于gRPC与http不互通,因此网关需要将Http请求反序列化,然后再序列化为gRPC识别的序列化方式。而Triple由于同时兼容Http和gRPC,因此不需要网关进行中间过程的序列化。
1、体验Triple
我们可以来体验一下使用Triple的新特性,依然使用之前的项目
对于模块而言,我们需要两个步骤。
- 引入Triple协议包
- 配置文件声明使用Triple协议
1.引入Triple协议包,注意与你Dubbo版本一致
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-triple</artifactId>
<version>3.1.1</version>
</dependency>
2.配置文件声明使用Triple协议
dubbo.protocol.name = "tri" # tri就代表使用Triple,约定大于配置
我们可以只需要在服务提供方配置,因为注册的时候注册中心元数据会声明请求类型的,服务消费方只需要引入了Triple协议包就可以自己去调用。
事实上,通过修改上述配置,服务提供方已经将元数据请求协议修改为Triple协议,而服务调用方拿到服务提供元数据,发现调用方法为Triple协议时,就会自己使用对于的协议进行调用。我们只需要引入该协议相关的maven包即可。
nacos中的注册元数据
2、流式调用
Stream 是 Dubbo3 新提供的一种调用类型,简单来说就是一个方法体内可以多次请求与响应,在以下场景时建议使用流的方式:
- 接口需要发送大量数据,这些数据无法被放在一个 RPC 的请求或响应中,需要分批发送,但应用层如果按照传统的多次 RPC 方式无法解决顺序和性能的问题,如果需要保证有序,则只能串行发送
- 流式场景,数据需要按照发送顺序处理, 数据本身是没有确定边界的
- 推送类场景,多个消息在同一个调用的上下文中被发送和处理
他的主要原理就是依赖于使用了http2.0的Triple协议,其特点为长连接,全双工。
流的语义保证
- 提供消息边界,可以方便地对消息单独处理
- 严格有序,发送端的顺序和接收端顺序一致
- 全双工,发送不需要等待
- 支持取消和超时
流的调用有三种
- SERVER_STREAM(服务端流)
- CLIENT_STREAM(客户端流)
- BIDIRECTIONAL_STREAM(双向流)
在使用之前,我们再次提醒这是Triple协议的内容,因此需要我们在配置文件中声明使用Triple协议,因为Dubbo3.1.1版本默认使用的并不是Triple协议
2.1、unary(正常模式)
unary就是正常Dubbo调用的模式,不包括在流式调用里面
公用common接口
public interface UserService {
User getUser(Integer id);
}
服务提供方实现接口并注入
@DubboService
public class UserServiceImpl implements UserService {
@Override
public User getUser(Integer id) {
return new User(id, "坏银");
}
}
服务消费方,注入接口并调用对应方法即可
@Service
public class OrderService {
@DubboReference
private UserService userService;
public String createOrder() {
User user = userService.getUser(6905);
System.out.println("成功创建订单");
return user.toString() + "已经成功为用户创建订单";
}
}
2.2、server-stream(服务端流)
服务端流的意思就是服务端(生产者)能够不停的向请求端(消费者)响应数据,而不是单纯的调用一次。
1.common包引入依赖
服务端流也就是我们服务提供方,由于服务提供和消费都以common公用包的接口为媒介,所以我们在common包需要引入 dubbo-common
包才能使对应的实体。
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-common</artifactId>
<version>3.1.1</version>
</dependency>
2.接口实现服务端流方法,common包下的共用接口
public interface UserService {
//server-stream 服务端流,返回类型和参数校验不能出错
void sayHelloServerStream(String name, StreamObserver<String> response);
}
3.服务提供方(生产者)重写该方法,进行多次响应
@DubboService
@Override
public void sayHelloServerStream(String name, StreamObserver<String> response) {
// 循环响应信息,建立长连接,而不是调用一次
for (int i = 0; i < 10; i++) {
response.onNext("hello," + name);
}
// 响应完成,结束方法
response.onCompleted();
}
4.服务消费方,实现序列化接口,注入对应的接口,进行对应方法的调用即可。
@Service
public class OrderService implements Serializable{
@DubboReference
private UserService userService;
//进行服务端流的消费
public String getResponse(){
//服务端流,消费方不停的接收响应
userService.sayHelloServerStream("hello", new StreamObserver<String>() {
//接收响应处理程序
@Override
public void onNext(String data) {
System.out.println("接受到结果:"+data);
}
//接收错误处理程序
@Override
public void onError(Throwable throwable) {
System.out.println("服务提供方报错了");
}
//接收完成处理参数
@Override
public void onCompleted() {
System.out.println("服务端响应结束,现在是我接收端");
}
});
return "";
}
}
tips:
我们一定要注意的细节是消费方的Service实现了
Serializable
接口,也就是说这个接口需要序列化。实际上,服务端流接收消息是需要序列化消费端接口的远程调用的,调用的是匿名内部类的三个方法,而三个方法是匿名的,因此我们只能对外部的Service实现序列化接口,进而内部匿名内部类能够序列化。
2.3、client-stream(客户端流)、bi-stream(双向流)
我们的客户端流和双向流实际上是一个实现方式,这是由于 java 语言的限制。
那么客户端流也就是服务消费者不停的请求服务提供者,当然由于他和双向流共同实现,因此也是支持双工消费的。
具体流程如下
1.引入common包,之前我们已经引入过来
2.接口实现客户端流方法,common包下的共用接口
不难发现,这个方法多了返回值,那么这个返回值就是response,通过他就能够实现互相通行
public interface UserService {
//client-stream 客户端流 / bidirectional-stream 双向流
StreamObserver<String> sayHelloStream(StreamObserver<String> response);
}
3.服务提供方(生产者)重写该方法,进行多次响应和请求
@DubboService
public class UserServiceImpl implements UserService {
@Override
public StreamObserver<String> sayHelloStream(StreamObserver<String> response) {
return new StreamObserver<String>() {
//想要流接收消息方法
@Override
public void onNext(String data) {
System.out.println(data);
response.onNext("hello,"+data);
}
// 响应流错误执行方法
@Override
public void onError(Throwable throwable) {
throwable.printStackTrace();
}
// 响应流完成方法
@Override
public void onCompleted() {
System.out.println("onCompleted");
response.onCompleted();
}
};
}
}
4.服务消费方(消费者)注入这个Dubbo接口,调用方法
@Service
public class OrderService implements Serializable {
@DubboReference
private UserService userService;
public StreamObserver<String> getStreamData() {
//接收流式响应
StreamObserver<String> request = userService.sayHelloStream(new StreamObserver<String>() {
@Override
public void onNext(String data) {
System.out.println(data);
}
@Override
public void onError(Throwable throwable) {
throwable.printStackTrace();
}
@Override
public void onCompleted() {
System.out.println("终止请求");
}
});
//再次请求
for (int i = 0; i < 10; i++) {
request.onNext("消费方请求" + i);
}
//终止连接
request.onCompleted();
return request;
}
}
1.5.3、跨语言调用
在使用Dubbo的微服务开发中,服务生产者与服务消费者使用common(公共包)下的接口和实体来实现。他们在远程调用的过程中一个提供方法名,一个提供序列化与反序列化实体媒介。实际上他们在网络上传输的都是二进制文件,因此理论上来说是能够实现跨语言调用的。
当然,如果我们需要使用跨语言调用,那么common包的接口和实体,必须二者语言都能够序列化并实现。而不是单方的实现。
假如消费者不是用java语言写的,那至少满足一下条件才能够调用java实现的Dubbo服务
- Dubbo一开始是用Java语言实现的,那现在就需要一个go语言实现的Dubbo框架,也就是现在的dubbo-go,然后在go项目中引入dubbo-go,从而可以在go项目中使用dubbo,比如使用go语言去暴露和使用Dubbo服务。
- 我们在使用Java语言开发一个Dubbo服务时,会把服务接口和相关类,单独抽象成为一个Maven项目,实际上就相当于一个单独的jar包,这个jar能被Java项目所使用,但不能被go项目所使用,所以go项目中该如何使用Java语言所定义的接口呢?直接用是不太可能的,只能通过间接的方式来解决这个问题,除开Java语言之外,那有没有其他技术也能定义接口呢?并且该技术也是Java和go都支持,这就是protobuf。
因此,protobuf是多种语言的媒介,通过protobuf编译器,能够将接口和实体编译为特定语言的接口和实体。以此来实现不同语言common包的所需的接口和实体。
1.使用protobuf
使用 IDL 定义服务具有更好的跨语言友好性,对于 Dubbo3 新用户而言,我们推荐使用这种方式。 然而 Triple 协议并不是和 IDL 强绑定的,也可以使用 Java Interface + Pojo 的方式定义服务并启用 Triple 协议。Dubbo 使用 Protobuf 作为 IDL。
1.创建一个dubbo-IDL-common的普通maven项目,我们可以使用这个项目直接当作common包
请千万注意,我们需要使用maven的complie将porto文件编译成java,因此需要读取路径文件,请务必保证路径下没有中文
2.在项目中定义proto文件,可以叫做 userservice.proto
,路径为 src/main/proto/uservice.porto
,这里要注意proto文件一定要放在该路径下才能够读取到。
那么这个文件就是我们定义接口和实体的细节了。相当于定义了一个HelloService服务,并且定义了一个getUser方法,接收UserRequest类型的参数,返回User类型的对象。
syntax = "proto3";
package api;
// go包前缀
option go_package = "./;api";
option java_multiple_files = true;
// java包前缀
option java_package = "com.hy";
// java外部类名
option java_outer_classname = "UserServiceProto";
// 定义接口
service UserService {
// 调用方法,方法名,返回
rpc GetUser (UserRequest) returns (User) {}
}
// 定义实体
message UserRequest {
string uid = 1;
}
message User {
string uid = 1;
string username = 2;
}
3.编译成java
在项目的pom文件中添加相关的依赖以及构建插件
<dependencies>
<!-- protobuf java对应包 -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.21.6</version>
</dependency>
<!-- dubbo包 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>3.1.1</version>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.1</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier}</protocArtifact>
<!-- 最后输出路径,还会加上proto配置的包名,我的就是com/hy -->
<outputDirectory>src/main/java</outputDirectory>
<clearOutputDirectory>false</clearOutputDirectory>
<protocPlugins>
<protocPlugin>
<id>dubbo</id>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-compiler</artifactId>
<version>0.0.3</version>
<mainClass>org.apache.dubbo.gen.dubbo.Dubbo3Generator</mainClass>
</protocPlugin>
</protocPlugins>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
然后运行provider中lifecycle的compile,就会进行编译了
并且会编译出对应的接口等信息,编译完成后,会生成一些类:
其中就包括了一个UserService接口,所以我们的UserServiceImpl就可以实现这个接口了:
@DubboService
public class UserServiceImpl implements UserService {
public User getUser(UserRequest userRequest) {
User user = User.newBuilder().setUid(userRequest.getUid()).setUsername("hy").build();
return user;
}
}
而对于想要调用UserService服务的消费者而言,其实也是一样的改造,只需要使用同一份userservice.proto进行编译就可以了,比如现在有一个go语言的消费者。
2.go语言编译
go语言暂时我们就不做展示了