Dubbo Provider Hello World之初体验
Dubbo 介绍
Dubbo 是一款 RPC 微服务框架,提供微服务架构下服务治理、服务通讯的解决方案。Dubbo底层定义了自己RPC的通信协议与编码方式,屏蔽了TCP底层通讯的复杂性和细节。让用户在使用Dubbo时像调用本地方法一样,让程序员用起来“真香”。
Dubbo的架构图如下:
Registry : 注册中心,用以管理服务提供者、服务消费者的元数据。对提供者、消费者,它分别承担服务注册、服务发现的职责;从物理上将接口的调用进行远程隔离,通过rpc的方式实现数据通信。因此这种项目的组织方式,特别适合大军团作战。需要特别注意的是: 注册中心可以实时感知提供者/消费者的状态,从而提供服务下线的能力。
Provider : 服务提供者。服务启动时根据指定配置向注册中心注册自身的IP、端口。表明服务已经处于就绪状态,可以向外部提供正常调用能力。
Consumer: 服务消费者。根据指定配置读取服务提供者列表(集群存在多个服务),并在接口调用时,选择合适的Provider进行通讯,返回结果,完成调用。
相对于本地调用,Dubbo在一次完整的接口调用中代码更为复杂,至少需要提供以上三种角色。回归主题,下面将演示Hello World的三种姿势。
版本声明:
Dubbo 2.7.5、zookeeper-3.4.13、apache-maven-3.6.0、apache-jmeter-5.2.1
Provider 代码
项目结构
说明:
dubbo-api : dubbo 接口定义
provider : dubbo接口实现,dubbo服务的提供者
consumer : dubbo 接口消费者
pom文件
parent pom.xml
<?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>dubbo-example</groupId>
<artifactId>dubbo-example-case</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>provider</module>
<module>consumer</module>
<module>dubbo-api</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<dubbo.version>2.7.15</dubbo.version>
<junit.version>4.12</junit.version>
<spring-test.version>4.3.16.RELEASE</spring-test.version>
<maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
<maven-failsafe-plugin.version>2.21.0</maven-failsafe-plugin.version>
<spring-boot.version>1.5.13.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.78</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.14.0</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-test.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
dubbo-api pom.xml
<?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">
<parent>
<artifactId>dubbo-example-case</artifactId>
<groupId>dubbo-example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-api</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
provider pom.xml
<?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">
<parent>
<artifactId>dubbo-example-case</artifactId>
<groupId>dubbo-example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>provider</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>dubbo-example</groupId>
<artifactId>dubbo-api</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.25</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>${dubbo.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
consumer pom.xml
<?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">
<parent>
<artifactId>dubbo-example-case</artifactId>
<groupId>dubbo-example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>consumer</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>dubbo-example</groupId>
<artifactId>dubbo-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
代码实现
接口定义
package org.example.api.day01;
public interface IHello {
String sayHi(String name);
}
实现类
package org.example.provider.day01;
import org.apache.dubbo.config.annotation.DubboService;
import org.example.api.day01.IHello;
@DubboService(version = "1.0.0")
public class HelloProvider implements IHello {
@Override
public String sayHi(String name) {
return "sayHi to " + name;
}
}
启动类
package org.example.provider;
import org.apache.dubbo.config.spring.context.annotation.DubboComponentScan;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
@SpringBootApplication
@DubboComponentScan(basePackages = {"org.example.provider"})
public class ProviderApp {
public static void main(String[] args) {
/**
* 以非web项目启动
*/
new SpringApplicationBuilder(ProviderApp.class)
.web(WebApplicationType.NONE)
.run(args);
}
}
项目启动
-
启动zookeeper
./bin/zkServer.sh start conf/zoo.cfg -
启动 provider
# 直接在Idea 运行 ProviderApp main方法即可
控制台出现以上日志,则证明启动成功。
Provider 功能测试
到现在为止,dubbo中的服务提供者已经正常启动,我们需要测试一下provider是否能够正常提供服务,下面介绍两种测试方法:
Dubbo Admin
下载/安装
Github 下载地址 : https://github.com/apache/dubbo-admin
工具包下载地址 : https://github.com/apache/dubbo-admin/releases
本人是使用Github master 分支的代码进行编译的,附上工具包
# 第一步 clone 代码
git clone -b master https://github.com/apache/dubbo-admin.git
# 第二步 修改配置中心 (dubbo-admin-server/src/main/resources/application.properties)
admin.registry.address=zookeeper://127.0.0.1:2181
admin.config-center=zookeeper://127.0.0.1:2181
admin.metadata-report.address=zookeeper://127.0.0.1:2181
# 第三步 修改登录账号/密码 (dubbo-admin-server/src/main/resources/application.properties)
admin.root.user.name=root
admin.root.user.password=root
# 第四步 编译文件
mvn clean install -Dmaven.test.skip=true
# 第五步 找到 target/dubbo-admin-server-0.3.0.jar
启动
启动命令,默认占用 8080端口
java -jar dubbo-admin-server-0.3.0.jar
指定端口
java -Dserver.port=8081 -jar dubbo-admin-server-0.3.0.jar
登录
浏览器打开网址: http://localhost:8081/#/
输入账号/密码: root/root
Dubbo 接口测试
至此,使用Dubbo Admin工具进行dubbo接口测试的流程已经介绍完毕!
Jmeter 工具
下载/安装
Jmeter 官方下载地址 : https://jmeter.apache.org/download_jmeter.cgi
本人是很早之前下载的版本,因此比较旧。
dubbo 插件安装
Jmeter 默认是不支持dubbo 接口的,因此需要安装额外的插件。
插件下载地址 : https://github.com/thubbo/jmeter-plugins-for-apache-dubbo/releases
将下载下来的jar包放置到jmeter安装目录下 lib/ext/ 文件夹下,启动 jemter 即可
dubbo 接口测试
-
启动jmeter
进入jmeter安装目录的bin文件夹下,执行 ./jmeter
-
右键创建线程池
-
添加执行计划
-
输入相关参数
-
添加执行结果
-
运行,查看结果
可以看到 “Response data” 中正常输出dubbo接口的返回值,大功告成!
代码测试
下面介绍一种可以通过main函数 直接测试dubbo服务的方法,但是该方式仅仅只是针对开发/测试阶段。
旧版本代码
@Test
public void sayHi() {
// 当前应用配置
ApplicationConfig application = new ApplicationConfig();
application.setName("test-consumer");
application.setOwner("owner");
// 连接注册中心配置
RegistryConfig registry1 = new RegistryConfig();
registry1.setAddress("zookeeper://localhost:2181");
//InterfaceAPI 为dubbo接口定义
ReferenceConfig<IHello> reference = new ReferenceConfig();
reference.setApplication(application);
reference.setRegistries(Arrays.asList(registry1));
reference.setInterface(IHello.class);
//接口定义的版本号
reference.setVersion("1.0.0");
IHello interfaceAPI = reference.get();
String result = interfaceAPI.sayHi("kobe");
System.out.println("===== : " + result);
}
以上代码在Idea中可以明显的看到(如下图),setApplication方法超时,
原因是在2.7.15的版本中将该方法设置为@Deprecated。因此,新版本的测试代码如下
新版本代码
@Test
public void sayHi2Bootstrap(){
ReferenceConfig<IHello> reference = new ReferenceConfig<>();
reference.setInterface(IHello.class);
reference.setGeneric("true");
reference.setVersion("1.0.0");
DubboBootstrap bootstrap = DubboBootstrap.getInstance();
bootstrap.application(new ApplicationConfig("consumer"))
.registry(new RegistryConfig("zookeeper://localhost:2181"))
.reference(reference)
.start();
IHello iHello = ReferenceConfigCache.getCache().get(reference);
final String message = iHello.sayHi("Kobe");
System.out.println("===== : " + message);
GenericService generic = (GenericService) iHello;
Object msg = generic.$invoke("sayHi", new String[]{String.class.getName()},
new Object[]{"Kobe"});
System.out.println("===== : " + msg);
}
Dubbo 新特性
1 从使用2.7.7版本开始,使用 @DubboService 注解代替 旧版本 @Service 注解
2 同理 从使用2.7.7版本开始,使用 @DubboReference注解代替 旧版本 @Reference 注解
代码Git地址: https://gitee.com/whylxd/dubbo-example-case
参考: https://cloud.tencent.com/developer/article/1810648