环境配置
1. 由于选择使用 Zookeeper 注册中心来实现 dubbo 中生产者与消费者之间的通讯,首先要把 Zookeeper 配置好并启动,Zookeeper 的配置与启动在另一篇文章(Zookeeper 安装与使用)已经介绍过。
2. 分别创建 Provider 与 Consumer 项目,此处是通过 Maven 构建项目的,接着我们需要在两个项目中配置好 dubbo 所需要的 dependency。
<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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.awang.dubbo</groupId>
<artifactId>dubbo_demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<dubbo.version>3.0.0</dubbo.version>
</properties>
<dependencies>
<!-- 该依赖为 dubbo 必需依赖 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<!-- 该依赖为调用 dubbo API 所需依赖 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
</dependency>
<!-- 该依赖为 XML、注解方式配置 dubbo 的必需依赖 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<version>${dubbo.version}</version>
</dependency>
</dependencies>
</project>
通过多种方式运行 dubbo
注意运行前需要先启动好 Zookeeper,否则会报连接不到 Zookeeper 的错误。
一、需要创建好接口
1. 首先在 Provider 项目中创建接口,用来暴露给 Consumer。
package com.awang.dubbo.service;
/**
* @author: awang
* @version: 1.0
* @date: 2021年6月24日
*/
public interface HelloService {
void sayHello();
}
2. 接着实现接口,来定义当 Consumer 调用接口时需要执行什么。
package com.awang.dubbo.serviceImpl;
import com.awang.dubbo.service.HelloService;
/**
* @author: awang
* @version: 1.0
* @date: 2021年6月24日
*/
public class HelloServiceImpl implements HelloService {
@Override
public void sayHello() {
System.out.println("Hello dubbo!");
}
}
3. 然后 Consumer 项目同样需要创建与 Provider 一样的接口,用于在调用时作为调用对象。
package com.awang.dubbo.service;
/**
* @author: awang
* @version: 1.0
* @date: 2021年6月24日
*/
public interface HelloService {
void sayHello();
}
二、通过 API 暴露与调用
1. 启动 dubbo 的 Provider,把所需要暴露的接口挂到 Zookeeper 上。
package com.awang.dubbo;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import com.awang.dubbo.service.HelloService;
import com.awang.dubbo.serviceImpl.HelloServiceImpl;
/**
* @author: awang
* @version: 1.0
* @date: 2021年7月3日
*/
public class StartByAPI {
private static String zookeeperHost = System.getProperty("zookeeper.address", "127.0.0.1");
public static void main(String[] args) throws Exception {
//dubbo provider 对象实例
ServiceConfig<HelloService> service = new ServiceConfig<>();
//Application 配置
service.setApplication(new ApplicationConfig("provider"));
//Registry 集群,此处配置了三个 Zookeeper
List<RegistryConfig> registries = new ArrayList<RegistryConfig>();
registries.add(new RegistryConfig("zookeeper://" + zookeeperHost + ":2181"));
registries.add(new RegistryConfig("zookeeper://" + zookeeperHost + ":2182"));
registries.add(new RegistryConfig("zookeeper://" + zookeeperHost + ":2183"));
service.setRegistries(registries);
//所暴露接口配置
service.setInterface(HelloService.class);
//接口所指向实现类
service.setRef(new HelloServiceImpl());
//dubbo 启动
service.export();
System.out.println("dubbo service started");
//执行后防止自动关闭 dubbo
new CountDownLatch(1).await();
}
}
2. 启动后我们能看到控制台输出信息。
3. Provider 启动完后,我们可以启动 Consumer 来去调用所暴露接口。
package com.awang.dubbo;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import com.awang.dubbo.service.HelloService;
/**
* @author: awang
* @version: 1.0
* @date: 2021年7月3日
*/
public class StartByAPI {
private static String zookeeperHost = System.getProperty("zookeeper.address", "127.0.0.1");
public static void main(String[] args) {
//dubbo consumer 对象实例
ReferenceConfig<HelloService> reference = new ReferenceConfig<>();
//Application 配置
reference.setApplication(new ApplicationConfig("consumer"));
//Registry 配置
reference.setRegistry(new RegistryConfig("zookeeper://" + zookeeperHost + ":2181"));
reference.setInterface(HelloService.class);
//调用 provider 接口
HelloService service = reference.get();
service.sayHello();
}
}
4. 运行后我们能看到调用接口成功,控制台输出 Hello dubbo!。
5. 启动后我们可能会看到控制台中并没有输出信息就停止了,这并不是调用失败,其实只是 System.out 对象被先前的控制台占用了,把 “Hello dubbo!”输出到了先前启动 Provider 的控制台中去了,我们可以点击右上角的切换控制台按钮来切换到之前的控制台,然后就能看到了。
三、通过 XML 配置 dubbo
1. 先在 Provider 项目的 src/main/resources 下创建 Provider 配置文件 dubbo_provider.xml(文件名可以自取)。
<?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="provider" />
<!-- 使用multicast广播注册中心暴露服务地址
<dubbo:registry address="multicast://127.0.0.1:1234" />-->
<!-- 使用zookeeper注册中心暴露服务地址,此处配置 Zookeeper 集群 -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183" />
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.awang.dubbo.service.HelloService" ref="helloService" />
<!-- 接口具体的实现bean -->
<bean id="helloService" class="com.awang.dubbo.serviceImpl.HelloServiceImpl" />
</beans>
2. 配置过程中有个比较重要的点需要提一下,配置完上面的 XML 后可能会报错,说找不到 dubbo.xsd。此处提供解决方法,先从网上下载现成的 dubbo.xsd 文件或者在电脑上创建一个 dubbo.xsd 文件,然后浏览器访问 http://dubbo.apache.org/schema/dubbo/dubbo.xsd,把页面上横线以下的所有配置内容复制到所创建的 dubbo.xsd 文件里面。
3. 接着我们在 eclipse 中进行操作 Window --> Preferences --> XML --> XML Catalog --> Add。
4. 在打开的新建窗口中,我们先点击 File System... 选择我们刚刚所下载或者创建的 dubbo.xsd 文件,然后 Key type 选择为 Schema location,在 Key 后面添加 /dubbo.xsd,然后点击 OK 关闭。返回到刚刚的窗口,点击 Apply and Close 保存好。
5. 最后我们在 XML 中打开右键菜单,然后选择 validate,验证完后就会发现错误解决了。
6. 配置好后我们就可以通过该 XML 配置文件启动 Provider 来暴露接口了。
package com.awang.dubbo;
import java.util.concurrent.CountDownLatch;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author: awang
* @version: 1.0
* @date: 2021年6月25日
*/
public class StartByXML {
public static void main(String[] args) throws InterruptedException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo_provider.xml");
context.start();
System.out.println("dubbo service started");
//执行后防止自动关闭 dubbo
new CountDownLatch(1).await();
}
}
7. 启动后我们能看到控制台输出信息。
8. 接着在 Consumer 项目的 src/main/resources 下创建 Consumer 配置文件 dubbo_consumer.xml(文件名同样可以自取)。
<?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://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="consumer" />
<!-- 使用 zookeeper 注册中心暴露服务地址 -->
<!-- <dubbo:registry address="multicast://127.0.0.1:1234" /> -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- 生成远程服务代理,可以像使用本地 bean 一样使用 HelloService -->
<dubbo:reference id="helloService"
interface="com.awang.dubbo.service.HelloService" />
</beans>
9. 配置完后我们启动 Consumer 来获取接口。
package com.awang.dubbo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.awang.dubbo.service.HelloService;
/**
* @author: awang
* @version: 1.0
* @date: 2021年6月25日
*/
public class StartByXML {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo_consumer.xml");
context.start();
HelloService helloService = (HelloService) context.getBean("helloService");
helloService.sayHello();
}
}
10. 运行后我们能看到调用接口成功,控制台输出 Hello dubbo!。
三、通过注解配置 dubbo
1. 由于该种方式接口实现也需要进行注解配置,所以我们不使用上面的接口,重新创建一个接口。首先是创建 Provider 项目的接口。
package com.awang.dubbo.service;
/**
* @author: awang
* @version: 1.0
* @date: 2021年7月4日
*/
public interface HelloAnnotationService {
void sayHello();
}
2. 接着实现所创建的接口,并在类上面添加 DubboService 注解。
package com.awang.dubbo.serviceImpl;
import org.apache.dubbo.config.annotation.DubboService;
import com.awang.dubbo.service.HelloAnnotationService;
/**
* @author: awang
* @version: 1.0
* @date: 2021年7月4日
*/
@DubboService
public class HelloAnnotationServiceImpl implements HelloAnnotationService{
@Override
public void sayHello() {
System.out.println("Hello dubbo!");
}
}
3. 接着创建一个 dubbo 配置类。Configuration 注解说明该类是一个配置类。EnableDubbo 注解用于配置扫描路径,即为刚刚 DubboService 注解的类所在的包。接着其它配置有两种方式可以选择:一种就是使用 PropertySource 注解指向 properties 文件,然后在文件里面配置各个配置参数的键与值;另一种就是分别配置好 registryConfig、applicationConfig、consumerConfig 三个 bean,分别对应着注册中心配置对象、应用配置对象、消费者配置对象。创建好方法并在方法上使用 Spring 的 Bean 注解,然后在方法内通过调用三个配置类的各个 Set 方法配置好各个 bean 的参数。此处同时使用了两种方式进行配置。
package com.awang.dubbo.annotation;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConsumerConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* @author: awang
* @version: 1.0
* @date: 2021年7月4日
*/
@Configuration
@EnableDubbo(scanBasePackages = "com.awang.dubbo.serviceImpl")
@PropertySource("dubbo_provider.properties")
public class ProviderConfiguration {
// 注册中心配置
@Bean
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setProtocol("zookeeper");
registryConfig.setAddress("127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183");
return registryConfig;
}
// 应用配置
@Bean
public ApplicationConfig applicationConfig() {
ApplicationConfig applicationConfig = new ApplicationConfig();
//applicationConfig.setName("provider");
return applicationConfig;
}
// 消费者配置
@Bean
public ConsumerConfig consumerConfig() {
ConsumerConfig consumerConfig = new ConsumerConfig();
return consumerConfig;
}
}
dubbo_provider.properties:
dubbo.application.name=provider
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
4. 配置好后,就可以创建运行类来启动 Provider 了。其中 AnnotationConfigApplicationContext 的构造方法参数为刚刚创建的配置类。
package com.awang.dubbo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.awang.dubbo.annotation.ProviderConfiguration;
/**
* @author: awang
* @version: 1.0
* @date: 2021年7月3日
*/
public class StartByAnnotation {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
context.start();
System.out.println("dubbo service started");
//防止 dubbo 服务自动关闭
System.in.read();
}
}
5. 运行后能在控制台看到输出信息。
6. 接着轮到 Consumer 项目,同样先创建一个与 Provider 项目一样的接口。
package com.awang.dubbo.service;
/**
* @author: awang
* @version: 1.0
* @date: 2021年7月4日
*/
public interface HelloAnnotationService {
void sayHello();
}
7. 然后创建一个需要调用接口的类。在类上使用 Component 注解,也就是 Spring 注解,启动 dubbo 时就会在环境中创建该类实例,我们可以从环境中调用该类的实例。接着在类中创建一个接口对象,并对该对象使用 DubboReference 注解,然后我们就可以使用该接口对象了,启动 dubbo 时会把该对象指向从注册中心上所获取到的接口实例。
package com.awang.dubbo.annotation.comp;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;
import com.awang.dubbo.service.HelloAnnotationService;
/**
* @author: awang
* @version: 1.0
* @date: 2021年7月4日
*/
@Component("helloAnnotationServiceComponent")
public class HelloAnnotationServiceComponent {
@DubboReference
private HelloAnnotationService helloAnnotationService;
public void sayHello() {
helloAnnotationService.sayHello();
}
}
8. 接着同样创建一个配置类。类的注解比 Provider 的配置类多了个 ComponentScan 注解,这同样是 Spring 注解,是为了扫描 Component 注解类,因为 EnableDubbo 注解配置路径后只会扫描 dubbo 相关注解。
package com.awang.dubbo.annotation;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* @author: awang
* @version: 1.0
* @date: 2021年7月4日
*/
@Configuration
@EnableDubbo(scanBasePackages = "com.awang.dubbo.annotation.comp")
@PropertySource("dubbo_consumer.properties")
@ComponentScan(value = {"com.awang.dubbo.annotation.comp"})
public class ConsumerConfiguration {
}
dubbo_consumer.properties:
dubbo.application.name=consumer
dubbo.registry.address=zookeeper://127.0.0.1:2181
9. 配置好后,就可以创建运行类了。启动 dubbo 后,我们从环境中获取刚刚的 Component 实例,然后调用它里面的 sayHello 方法,就能发现 HelloAnnotationServiceComponent 实例里面的接口参数已经获取到了 Provider 所提供的接口服务。
package com.awang.dubbo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.awang.dubbo.annotation.ConsumerConfiguration;
import com.awang.dubbo.annotation.comp.HelloAnnotationServiceComponent;
import com.awang.dubbo.service.HelloAnnotationService;
/**
* @author: awang
* @version: 1.0
* @date: 2021年7月3日
*/
public class StartByAnnotation {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
context.start();
HelloAnnotationServiceComponent service = context.getBean("helloAnnotationServiceComponent", HelloAnnotationServiceComponent.class);
service.sayHello();
}
}
10. 运行结果为:
11. 此时我们也可以通过 zkCli -server 127.0.0.1:2181 访问 Zookeeper 的客户端来查看 Zookeeper 中存放了什么数据信息。我们能够看到已经存放了我们所发布的服务信息,包括服务暴露 IP 端口等,有兴趣可以自行去研究。
最后指个路:dubbo 源码
dubbo-admin 后台管理
1. 为了方便管理 dubbo 服务,开发了服务后台管理项目 dubbo-admin。接着我们来部署访问一下管理后台,首先到 GitHub 上下载项目源码,可以通过 git clone [url] 把项目克隆到本地,或者点击 Download ZIP 下载压缩包。
2. 下载到电脑后,先到 dubbo-admin\dubbo-admin-server\src\main\resources 路径下打开 application.properties 文件,然后配置好 Zookeeper 集群的 IP 端口信息。默认是配置了单个 Zookeeper,我们改成集群。然后也可以在下面配置管理后台的登录用户名和密码。
3. 由于 dubbo-admin 的项目和前端分别是通过 Maven 和 npm 工具构建的,所以启动项目前电脑需要先安装配置好 Maven 和 nodejs,没有安装的可以到网上自行搜索安装配置教程。安装配置好后就可以启动项目了。
4. 此时若直接启动项目,会报端口被占用的错误。因为 Zookeeper 启动后管理默认会占用 8080 端口,而我们启动的 dubbo-admin 同样默认部署到 8080 端口上。所以我们需要改变其中一方的端口配置。要么在每个 Zookeeper 的 zoo.cfg 配置文件中都加上 admin.serverPort=8081 然后重启一下 Zookeeper,要么在 dubbo-admin 项目中上面提到的 application.properties 中加上 server.port=8081 再启动。
5. 接着就可以构建启动项目了。由于 npm 需要管理员权限,所以我们要运行管理员命令窗口。然后先在 dubbo-admin 的项目根目录下执行 mvn clean package -Dmaven.test.skip=true 构建好项目,然后再在根目录执行 mvn --projects dubbo-admin-server spring-boot:run 启动 Tomcat。启动完我们就可以访问 http://localhost:8080 (若 application.properties 中配置了其它 server 端口,就访问其它端口)来进入 dubbo 管理后台了。登录后就能进入主界面,如果我们暴露了服务,我们就能看到我们所暴露的服务了。