• 周六. 10 月 12th, 2024

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

dubbo实战之一:准备和初体验

King Wang

1 月 3, 2022

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

《dubbo实战》系列导航

  1. 准备和初体验
  2. 与SpringBoot集成
  3. 使用Zookeeper注册中心
  4. 管理控制台dubbo-admin

关于dubbo

  1. Apache Dubbo (发音ˈdʌbəʊ) 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现;
  2. 以下是来自官方的架构图:
    在这里插入图片描述

版本简介和选定

  • 截止写此文时,Dubbo 社区主力维护的有 2.6.x 和 2.7.x 两大版本;
  • 2.6.x 主要以 bugfix 和少量 enhancements 为主,因此能完全保证稳定性;
  • 2.7.x 作为社区的主要开发版本,得到持续更新并增加了大量新 feature 和优化,同时也带来了一些稳定性挑战;
  • 综上所述,《dubbo实战》系列选择了社区推荐的2.7.6版本,这是2.7系列的稳定版;

环境信息

我这边用来编码的环境如下:

  1. 操作系统:macOS Catalina 10.15.5
  2. JDK:1.8.0_121
  3. Maven:33.3.9
  4. 开发工具:IntelliJ IDEA 2019.3.2 (Ultimate Edition)

注意事项

如果您是在windows环境运行代码,并且安装了VMWare,请您关闭对应的虚拟网卡,否则在广播模式(Multicast)时,consumer可能无法找到自己所需的服务;

本篇概览

  • 作为《dubbo实战》系列的开篇,本文的主要内容如下:
  1. 创建整个《dubbo实战》系列的父工程;
  2. 创建整个《dubbo实战》系列的公共二方库;
  3. 初步体验dubbo框架,为了简单,本篇的实战暂不使用注册中心,而是服务提供方启动时广播自己的地址,再由消费方启动时订阅,并随时远程调用,调用逻辑如下图所示:
    在这里插入图片描述
  4. 先创建一个提供远程服务的子工程,名为helloxmldirectprovider,并运行起来;
  5. 再创建名为helloxmldirectconsumer的子工程,运行起来后,会调用helloxmldirectprovider提供的远程服务,将远端返回的内容打印出来;
  • 接下来开始编码

源码下载

  1. 如果您不想编码,可以在GitHub下载所有源码,地址和链接信息如下表所示:
名称 链接 备注
项目主页 https://github.com/zq2599/blog_demos 该项目在GitHub上的主页
git仓库地址(https) https://github.com/zq2599/blog_demos.git 该项目源码的仓库地址,https协议
git仓库地址(ssh) [email protected]:zq2599/blog_demos.git 该项目源码的仓库地址,ssh协议
  1. 这个git项目中有多个文件夹,本章的应用在dubbopractice文件夹下,如下图红框所示:
    在这里插入图片描述
  2. dubbopractice是父子结构的工程,本篇的代码在helloxmldirectproviderhelloxmldirectconsumer这两个子工程中,如下图:
    在这里插入图片描述

《dubbo实战》系列的父工程

  1. 为了方便管理《dubbo实战》系列的代码和依赖库版本的管理,这里创建名为dubbopractice的父maven工程,整个系列的后续源码都会作为它的子工程;
  2. dubbopractice的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">
<modules>
<module>practiceinterface</module>
<module>helloxmldirectprovider</module>
<module>helloxmldirectconsumer</module>
<module>springbootzkprovider</module>
<module>springbootzkconsumer</module>
<module>springbootmulticastprovider</module>
<module>springbootmulticastconsumer</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<java.version>1.8</java.version>
<dubbo.version>2.7.6</dubbo.version>
<springboot.version>2.3.3.RELEASE</springboot.version>
</properties>
<modelVersion>4.0.0</modelVersion>
<groupId>com.bolingcavalry</groupId>
<artifactId>dubbopractice</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-bom</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.25.Final</version>
</dependency>
<!-- dubbo相关 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-multicast</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.7</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>2.11.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.7</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
<scope>compile</scope>
</dependency>
<!-- swagger依赖 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.5.0</version>
</dependency>
<!-- swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.5.0</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

《dubbo实战》系列的二方库

  1. 涉及到多个工程之间的服务调用,因此要有个工程保存公用的数据结构、接口定义等,因此新建名为practiceinterface的子工程;
  2. practiceinterface工程的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>dubbopractice</artifactId>
<groupId>com.bolingcavalry</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.bolingcavalry</groupId>
<artifactId>practiceinterface</artifactId>
<version>1.0-SNAPSHOT</version>
<name>practiceinterface</name>
<description>Beans of all app</description>
</project>
  1. 此工程目前只有一个接口定义,后面多个子工程都会用到:
package com.bolingcavalry.dubbopractice.service;
public interface DemoService {

String sayHello(String name);
}

编码(服务提供方)

  • 先创建提供服务的工程helloxmldirectprovider,一共要创建6个文件,创建顺序和功能如下表:
创建顺序 文件名 作用
1 pom.xml 工程的pom文件
2 src/main/java/com/bolingcavalry/helloxmldirectprovider/ProviderApplication.java 启动类
3 src/main/java/com/bolingcavalry/helloxmldirectprovider/service/impl/DemoServiceImpl.java 提供具体的服务
4 src/main/resources/log4j.properties 日志配置文件
5 src/main/resources/dubbo.properties dubbo配置文件
6 src/main/resources/spring/dubbo-provider.xml spring的bean配置
  • 完整的文件位置如下图:
    在这里插入图片描述
  • 接下来逐个创建上述内容;
  1. 创建名为helloxmldirectprovider的子工程,pom.xml内容如下,可见刚才新建的二方库practiceinterface也被依赖了:
<?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>dubbopractice</artifactId>
<groupId>com.bolingcavalry</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.bolingcavalry</groupId>
<artifactId>helloxmldirectprovider</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.bolingcavalry</groupId>
<artifactId>practiceinterface</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
</dependencies>
</project>
  1. 编写启动类ProviderApplication.java,可见就是个普通的后台程序,加载spring配置做初始化:
package com.bolingcavalry.helloxmldirectprovider;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ProviderApplication {

public static void main(String[] args) throws Exception {

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-provider.xml");
context.start();
System.in.read();
}
}
  1. 编写提供具体服务的业务实现类DemoServiceImpl.java,只是个简单的接口实现类而已:
package com.bolingcavalry.helloxmldirectprovider.service.impl;
import com.bolingcavalry.dubbopractice.service.DemoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.rpc.RpcContext;
@Slf4j
public class DemoServiceImpl implements DemoService {

@Override
public String sayHello(String name) {

log.info("Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
try {

Thread.sleep(1000);
} catch (InterruptedException e) {

e.printStackTrace();
}
return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
}
}
  1. 日志配置文件log4j.properties,内容如下:
###set log levels###
log4j.rootLogger=info, stdout
###output to the console###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n
  1. 在同样位置创建dubbo配置文件dubbo.properties,内容很简单只有qos的端口设置,用于支持telnet命令:
dubbo.application.qos.port=22222
  1. 在resources目录下新建文件夹spring,在此文件夹下创建文件dubbo-provider.xml,要重点关注的是dubbo:registry的配置,其address属性值为multicast://224.5.6.7:1234,代表当前服务通过广播让消费者获得自身信息:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="demo-provider"/>
<!--广播模式-->
<dubbo:registry address="multicast://224.5.6.7:1234" />
<bean id="demoService" class="com.bolingcavalry.helloxmldirectprovider.service.impl.DemoServiceImpl"/>
<dubbo:service interface="com.bolingcavalry.dubbopractice.service.DemoService" ref="demoService"/>
</beans>
  1. 至此,服务提供方编码完成,直接在IDEA上运行ProviderApplication类即可启动服务,启动成功后的日志输出如下图:
    在这里插入图片描述

编码(服务消费方)

  • 现在网络上已经有了服务,接下来创建一个消费该服务的工程helloxmldirectconsumer,一共要创建5个文件,创建顺序和功能如下表:
创建顺序 文件名 作用
1 pom.xml 工程的pom文件
2 src/main/java/com/bolingcavalry/helloxmldirectconsumer/ConsumerApplication.java 启动、调用远端服务、再结束自身进程
3 src/main/resources/log4j.properties 日志配置文件
4 src/main/resources/dubbo.properties dubbo配置文件
5 src/main/resources/spring/dubbo-consumer.xml spring的bean配置
  • 完整的文件位置如下图:
    在这里插入图片描述
  • 接下来逐个创建上述文件;
  1. 创建名为helloxmldirectconsumer的子工程,pom.xml内容如下,可见刚才新建的二方库practiceinterface也被依赖了:
<?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>dubbopractice</artifactId>
<groupId>com.bolingcavalry</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.bolingcavalry</groupId>
<artifactId>helloxmldirectconsumer</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.bolingcavalry</groupId>
<artifactId>practiceinterface</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
</dependencies>
</project>
  1. 编写唯一的java文件ConsumerApplication.java,里面用了最简单的方法初始化spring环境,然后取得服务实例,执行过方法后结束进程:
package com.bolingcavalry.helloxmldirectconsumer;
import com.bolingcavalry.dubbopractice.service.DemoService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ConsumerApplication {

public static void main(String[] args) throws Exception {

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-consumer.xml");
context.start();
DemoService demoService = context.getBean("demoService", DemoService.class);
String hello = demoService.sayHello("world1");
System.out.println("result: " + hello);
}
}
  1. 日志配置文件log4j.properties,内容如下:
###set log levels###
log4j.rootLogger=info, stdout
###output to console###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n
  1. 在同样位置创建dubbo配置文件dubbo.properties,内容很简单只有qos的端口设置,用于支持telnet命令,本例中是用不上的,因为远程调用后进程就会结束:
dubbo.application.qos.port=33333
  1. 在resources目录下新建文件夹spring,在此文件夹下创建文件dubbo-consumer.xml,要重点关注的是dubbo:registry的配置,其address属性值为multicast://224.5.6.7:1234?unicast=false,代表当前服务通过广播让消费者获得自身信息,unicast=false表示多个消费者都能收到广播:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="demo-consumer"/>
<dubbo:registry address="multicast://224.5.6.7:1234?unicast=false"/>
<dubbo:reference id="demoService" check="false" interface="com.bolingcavalry.dubbopractice.service.DemoService" timeout="2000"/>
</beans>
  1. 上面的dubbo-consumer.xml中还有一处要注意,就是dubbo:referencetimeout属性,这是远程调用的超时时间,此处设置为2秒,要注意的是前面helloxmldirectprovider提供的服务延时了1秒才返回,所以这里设置不能低于1秒;
  2. 至此,服务消费方编码完成,直接在IDEA上运行ConsumerApplication类即可启动,如下图,红框中就是远程调用helloxmldirectprovider服务返回的内容:
    在这里插入图片描述
  • 至此,《dubbo实战》系列的准备和初体验都完成了,接下来的章节,咱们会通过更多实战来学习这个优秀的框架;

欢迎关注公众号:程序员欣宸

微信搜索「程序员欣宸」,我是欣宸,期待与您一同畅游Java世界…

发表回复