- 作者简介:☕️大家好,我是Aomsir,一个爱折腾的开发者!
- 个人主页:Aomsir_Spring5应用专栏,Netty应用专栏,RPC应用专栏
- 当前专栏:Dubbo3应用专栏_Aomsir的博客
结构术语
在深入学习 Dubbo 开发之前,我们首先需要对其结构和相关的专业术语有所了解。Dubbo 主要在微服务领域得到广泛应用,所以了解它的结构尤为关键。请参考下面的描述:
如图所示,commons-api模块
作为一个基础模块,其主要负责定义实体类、服务接口等核心元素。这些定义不仅为服务提供者所使用,也为服务消费者所依赖。而 provider 模块
,如其名字所示,是服务的提供者。它实现了 commons-api模块中的服务接口,并对外发布这些服务。相对地,consumer模块
作为服务的消费者,负责对 provider 发起远程服务调用。
这里还有一个可选组件,即 register。如果没有这个组件,consumer 会直接与 provider 通讯进行服务调用。但如果引入了 register
,事情就变得更加有趣:consumer 不再直接与 provider 交互,而是首先查询 register 以获取 provider 的集群地址,然后基于这些地址发起服务调用。
总的来说,这整个结构为微服务的开发和交互提供了一个灵活而高效的框架,使得服务的提供和消费变得既简单又高效
版本选择
此教程的版本搭配主要使用JDK8+Dubbo3.2.0,部分章节使用JDK17与Dubbo2.x
注意事项
- JDK8+Dubbo3.1.x及之前版本使用Zookeeper做注册中心,消费者会出现节点已存在异常
- JDK17与Dubbo3.2.0-beta4版本不兼容
- 原因:Dubbo-3.2.0-beta4及之前版本都是使用的Spring5.2.x,但是Spring5.2.x只支持JDK8-JDK15
- 解决方案:升级为Dubbo-3.2.0-beta5,beta5版本使用的是Spring5.3.x,Spring5.3.x支持JDK8-JDK21
- JDK9+出现的深反射问题,项目启动会有异常
- 解决方案:添加下面的JVM参数即可
-Dio.netty.tryReflectionSetAccessible=true
--add-opens
java.base/jdk.internal.misc=ALL-UNNAMED
--add-opens
java.base/java.nio=ALL-UNNAMED
--add-opens
java.base/java.lang=ALL-UNNAMED
--add-opens
java.base/java.math=ALL-UNNAMED
直连开发
直连开发是一种不通过注册中心,让消费者(consumer)与提供者(provider)直接进行通信的方法。为了便于更深入地理解Dubbo与SpringBoot的整合以及注解的使用,本章节将采用Spring配置文件的方式进行说明和处理
项目结构
如下图所示的项目结构包括api模块、consumer模块和provider模块。所有的依赖管理均交由父级pom统一处理。在这种结构中,api模块负责提供实体类并定义服务接口;provider模块实现了api模块中定义的服务接口,并发布这些服务;consumer模块则负责远程调用这些已发布的服务
父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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.aomsir</groupId>
<artifactId>dubbo-lession</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>dubbo-01-api</module>
<module>dubbo-02-provider</module>
<module>dubbo-03-consumer</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>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.9</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
</project>
模块代码与演示
API模块
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User implements Serializable {
private String name;
private String password;
}
服务接口
public interface UserService {
public boolean login(String username, String password);
}
Provider模块
服务实现
public class UserServiceImpl implements UserService{
@Override
public boolean login(String username, String password) {
System.out.println("UserServiceImpl.login,name:" + username + "password:" + password);
return false;
}
}
spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!--全局唯一的应用名-->
<dubbo:application name="dubbo-02-provider">
<!--关闭qos启动-->
<dubbo:parameter key="qos.enable" value="false" />
</dubbo:application>
<!--网络通信协议与端口-->
<dubbo:protocol name="dubbo" port="-1" serialization="hessian2"/>
<!--将UserService服务实现类注册到容器-->
<bean id="userService" class="com.aomsir.service.UserServiceImpl" />
<!--Dubbo发布服务-->
<dubbo:service interface="com.aomsir.service.UserService" ref="userService" />
</beans>
启动类
public class ProviderMain {
public static void main(String[] args) throws InterruptedException {
// 创建工厂并启动
ClassPathXmlApplicationContext applicationContext
= new ClassPathXmlApplicationContext("applicationContext-provider.xml");
applicationContext.start();
// 阻塞
new CountDownLatch(1).await();
}
}
启动输出
下图展示了启动日志,从中我们可以看到Provider已经对外发布了我们的UserService服务,发布地址为dubbo://198.18.0.1:20880/com.aomsir.service.UserService?anyhost=true&application=dubbo-02-provider&background=false&bind.ip=198.18.0.1&bind.port=20880&deprecated=false&dubbo=2.0.2&dynamic=true&executor-management-mode=isolation&file-cache=true&generic=false&interface=com.aomsir.service.UserService&methods=login,login&pid=80310&prefer.serialization=hessian2&qos.enable=false&release=3.2.0&serialization=hessian2&side=provider×tamp=1691391591286
。
从这个地址我们可以提取出以下信息:IP地址是198.18.0.1,端口号是20880,服务的全类名为com.aomsir.service.UserService。此外,我们还看到了采用的序列化方案为hessian2,这是一种由Dubbo团队优化过的序列化方案,旨在提高序列化的效率和性能。
这个日志的输出对我们理解服务是如何发布,以及如何配置服务发布的参数都非常有帮助。通过这个日志,我们可以了解到服务发布的一些关键信息,包括服务地址、服务名、使用的序列化方案等,这都是我们在进行服务开发和调试时需要关注的重要信息
Consumer模块
spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="dubbo-03-consumer" />
<!--远端服务接口,id,地址-->
<dubbo:reference interface="com.aomsir.service.UserService" id="userService" url="dubbo://198.18.0.1:20880/com.aomsir.service.UserService?serialization=hessian2" />
</beans>
启动类
public class ClientApplication {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext applicationContext
= new ClassPathXmlApplicationContext("applicationContext-consumer.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
boolean ret = userService.login("Aomsir", "123456");
System.out.println("ret = " + ret);
System.in.read();
}
}
发起调用
细节分析
Provider模块配置文件
在Provider模块的配置文件中,我们为Dubbo设置了应用名称并选择关闭了QoS功能。此配置还明确了整体通信的协议、所使用的序列化方法和端口号。默认情况下,端口号被设置为20880。若将其设置为-1,系统将从20880开始逐一增加,直至找到一个可用的端口。此外,配置确保服务被注入到容器中,并从容器中发布该服务,使其对外可用
Consumer模块配置文件
在Consumer模块的配置文件中,我们为Dubbo指定了应用名称。此外,我们详细配置了远程服务的诸如id、接口的全类名和地址等关键信息。这样的配置确保了程序能够从IoC容器中准确而轻松地获取和调用所需的远程服务的地址进而发起调用
注意
在Spring的配置文件中,我们必须引入Dubbo的命名空间以确保正确的配置和功能性。若Consumer的地址或端口发生任何变化,Provider的配置文件必须被立即更新。否则,Provider将无法与Consumer建立正确的通信,从而导致远程调用失败
注意观察两个配置文件的标签嗷,这些标签在整个SpringBoot的时候都会变成注解配置嗷