02.Dubbo3应⽤开发第二章

Dubbo3应⽤开发第二章

1.Dubbo直连开发

所谓的Dubbo RPC直连应⽤,指的就是Consumer直接访问Provider,⽽⽆需注册中⼼的接⼊。Dubbo完成的仅仅是RPC最基本的功能。

dubbo的核心:rpc和服务治理

dubbo的方式 优于 openfeign,这个结论待证明

直连开发有三个核心概念:

  • 服务提供者
  • 服务消费者
  • 网络通信

服务提供者和服务消费者是跨虚拟机通信的,中间需要通过网络通信

网络通信有三个核心要素:

  • 协议:是调用者和被调用者共同遵守的,又分为应用层协议(一般是公共的,如http1.x http2.x)和传输层协议(一般都是私有协议:比如name=xxx;password=tttt)。
  • 通信方式
  • 序列化

image-20231123113833747

使用了不同的协议,则需要使用不同的通信方式

传输层协议:BIO,nio,netty,mina

应用层协议:tomcat jetty

dubbo切换协议和通信方式和序列化方式(基于spi)

<dubbo:protocol name=”dubbo” port=”20882” transporter=”mina” serialization=”json”/>

先确定协议,就知道使用哪个层次进行通信,然后就知道通信方式

2.序列化

序列化:解决数据的传输格式。好的序列化方案能使传输的体量变小。

image-20231123114240812

1
2
3
4
5
6
7
8
1. Hessian Dubbo 协议中默认的序列化实现⽅案 
3.2.0以前的默认方式(实质上是hessian2),3.2.0以后默认是fastjson2
2. Java Serialization JDK的序列化⽅式
3. Dubbo序列化 阿⾥尚未开发成熟的⾼效java序列化实现,阿⾥不建议在⽣产环境使⽤它。
4. Json序列化 ⽬前有两种实现,⼀种是采⽤的阿⾥的fastjson库,另⼀种是采⽤dubbo中⾃⼰实现的简单 json 库。
5. Kryo Java序列化⽅式,后续替换Hessian2,是⼀种⾮常成熟的序列化实现,已经在Twitter、 Groupon、Yahoo以及多个著名开源项⽬(如Hive、 Storm)中⼴泛的使⽤。 建议实战中使用这种方式
6. FST Java序列化⽅式,后续替换Hessian2,是⼀种较新的序列化实现,⽬前还缺乏⾜够多的成熟使⽤案例。
7. 跨语⾔序列化⽅式 ProtoBuf,Thrift,Avro, MsgPack(MessagePack是⼀种⾼效的⼆进制序列化格式。它允许您在多种语⾔(如JSON)之间交换数据。但它更快更⼩。短整型被编码成⼀个字节)

各种序列化都有一个类似dubbo-serialization-xxx的依赖

image-20231123114718989

protobuf的依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    <!-- 注意protoc 的版本,要和build中的plug版本保持一致 -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.22.2</version>
</dependency>

<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.22.2</version>
</dependency>

<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-serialization-protobuf</artifactId>
<version>2.7.23</version>
<exclusions>
<exclusion>
<artifactId>dubbo-common</artifactId>
<groupId>org.apache.dubbo</groupId>
</exclusion>
<exclusion>
<artifactId>dubbo-serialization-api</artifactId>
<groupId>org.apache.dubbo</groupId>
</exclusion>
<exclusion>
<artifactId>protobuf-java</artifactId>
<groupId>com.google.protobuf</groupId>
</exclusion>
<exclusion>
<artifactId>protobuf-java-util</artifactId>
<groupId>com.google.protobuf</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.7.1</version>
</extension>
</extensions>
<plugins>
<!-- https://github.com/grpc/grpc-java -->
<!-- protoc没有针对低版本的arm版本的mac进行适配,如果需要的话,可以参考这个
https://github.com/grpc/grpc-java/issues/7690
com.google.protobuf:protoc:3.14.0:exe:osx-x86_64
-->
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<!--将proto文件转换为java文件有两种转换方式:1.使用protoc工具转换 2 使用maven转换-->
<!--注意和jar报依赖的版本保持一致-->
<!--proto文件夹必须放在 src/main 包下-->
<protocArtifact>com.google.protobuf:protoc:3.22.2:exe:${os.detected.classifier}</protocArtifact>
<outputDirectory>${basedir}/src/main/java</outputDirectory>
<!-- 改为true的话,整个java下的目录都会删掉 -->
<clearOutputDirectory>false</clearOutputDirectory>
<protocPlugins>
<protocPlugin>
<id>dubbo</id>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-compiler</artifactId>
<version>0.0.2</version>
<mainClass>org.apache.dubbo.gen.dubbo.Dubbo3Generator</mainClass>
</protocPlugin>
</protocPlugins>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Dubbo3Generator;

3.协议

什么是协议

​ Client[Consumer]与Server[Provider]在传输数据时双⽅的约定。

协议与序列化的关系。

​ 序列化是协议数据的传输⼀种格式。⽬的是为了提⾼协议在⽹络传输的效率。

Dubbo协议

  1. Dubbo的默认协议,⾃⼰定义的私有协议,基于TCP层,默认的通信⽅式是Netty4
  2. Dubbo采⽤单⼀⻓连接和 NIO 异步通讯,适合于⼩数据量⼤并发的服务调⽤。反之,Dubbo 缺省协议不适合传送⼤数据量的服务,⽐如传⽂件,传视频等

image-20231123132806226

准备zookeeper,版本搭配说明

img

Rest协议

gRPC协议

Triple协议

总依赖文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
<?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>

<groupId>org.example</groupId>
<artifactId>me-triple</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>me-triple-api</module>
<module>me-triple-provider</module>
<module>me-triple-comsumer</module>
</modules>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<dubbo.version>3.2.0</dubbo.version>
<grpc.version>1.54.1</grpc.version>
<spring-boot.version>2.7.12</spring-boot.version>
<protoc.version>3.21.7</protoc.version>
<os.detected.classifier>windows-x86_64</os.detected.classifier>
</properties>


<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</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>
</dependency>

<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>

<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-all</artifactId>
<version>${grpc.version}</version>
<exclusions>
<exclusion>
<artifactId>grpc-netty</artifactId>
<groupId>io.grpc</groupId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${protoc.version}</version>
</dependency>


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

<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.8.1</version>
</dependency>

<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.8.2</version>
</dependency>
</dependencies>

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

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

<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-bom</artifactId>
<version>${grpc.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.7.1</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.21.7:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
</pluginArtifact>
<outputDirectory>${basedir}/src/main/java</outputDirectory>
<clearOutputDirectory>false</clearOutputDirectory>
<protocPlugins>
<protocPlugin>
<id>dubbo</id>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-compiler</artifactId>
<version>${dubbo.version}</version>
<!-- 注意这里的mainClass,不同的作用有不同的类-->
<mainClass>org.apache.dubbo.gen.tri.Dubbo3TripleGenerator</mainClass>
</protocPlugin>
</protocPlugins>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
<goal>compile-custom</goal>
<goal>test-compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

多协议

dubbo-compiler

原生

Dubbo3Generator

proto文件转换java文件

proto文件名称与service名称不一致时:

预置:proto文件HelloService.proto,其中service名:HelloService,请求参数:HelloRequest,响应参数:HelloResponse,outClassName:HelloServiceProto

1.点击protobuf:compile:

生成了:HelloRequest及其构建者,HelloResponse及其构建者,HelloServiceProto,HelloServiceDubbo,接口HelloService七个文件。

其中后面三个是有规律的。

点击protofub:compile-custome:报错

privider: HelloService的实现类

consumer: HelloService

gRPC协议

DubboGrpcGenerator:

proto文件转换java文件

proto文件名称与service名称不一致时:

预置:proto文件DemoService.proto,其中service名:DemoService,请求参数:RequestData,响应参数:ResponseData,outClassName:DemoProto

1.点击protobuf:compile:

生成了:RequestData及其构建者,ResponseData及其构建者,DemoProto,DubboDemoServiceGrpc六个文件。

其中后面三个是有规律的。

点击protofub:compile-custome:生成DemoServiceGrpc.java。生成的是接口+Grpc

privider:

1
public class DemoServiceImpl extends DubboDemoServiceGrpc.DemoServiceImplBase {}

consumer:

注入对象:

1
2
@DubboReference(protocol = "grpc")
private DubboDemoServiceGrpc.IDemoService iDemoService;

gRPC原生:

1
DemoServiceGrpc.DemoServiceBlockingStub s= DemoServiceGrpc.newBlockingStub(managedChannel);

triple协议:

Dubbo3TripleGenerator:

proto文件转换java文件

注意:

1.当proto的文件名和service名称不一致时,需要指定java_outer_classname。否则DubboxxxTriple这个类中,引用xxxOuterClass时名称会出错。

2.option java_multiple_files = true; 这个选项只能为true,为false时,protoc插件报错。估计和Dubbo3TripleGenerator这个生成类有关系

类的生成关系:

proto文件名称与service名称一致时:

预置:proto文件me.proto,其中service名:Me,请求参数:MeRequest,响应参数:MeResponse

1.点击protobuf:compile:

生成了:MeRequest及其构建者,MeResponse及其构建者,接口Me,MeOuterClass,DubboMeTriple七个文件。

其中后面三个是有规律的。

点击protofub:compile-custome:生成MeGrpc.java

proto文件名称与service名称不一致时:

预置:proto文件hello.proto,其中service名:HelloService,请求参数:HelloRequest,响应参数:HelloResponse,outClassName:HelloServiceOuterClass

1.点击protobuf:compile:

生成了:HelloRequest及其构建者,HelloResponse及其构建者,接口HelloService,HelloServiceOuterClass,DubboHelloServiceTriple七个文件。

其中后面三个是有规律的。

点击protofub:compile-custome:生成HelloServoceGrpc.java。生成的是接口+Grpc

使用maven插件进行编译之后,会产生什么类?

  • proto文件中 service 的接口类:比如 proto文件中定义了service Greeter,那么就会产生 interface Greeter 的java类。同时会产生 DubboGreeterTriple 的类,这个类中有 Greeter接口的一个抽象的实现类。

provider需要提供的类是:

提供一个类,extends DubboMeTriple.MeImplBase,并且实现对应的方法,标注@DubboService注解

consumer:

1
2
3
@DubboReference(protocol = "tri")
private Me me;
MeGrpc.MeStub meStub = MeGrpc.newStub(managedChannel);