文章目录
一、 前言
其实我没在项目中使用过Dubbo,所以才想去看一看。这篇就是自己的入门教程,里面可能有些概念不对或者不清晰,如有错误,感谢指正。
二、简介
Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
三、项目搭建
1. 项目概述
项目搭建成如下三个项目模块, 见名知意,dubbo-consumer 是服务消费者,dubbo-provider1和2是服务提供者。dubbo-interface是RPC调用的接口。
- 首先需要启动Zookeeper。和可视化工具。准备工作到此为止
2. dubbo-interface
dubbo 根据引用类型的全路径类名 + 版本号 作为唯一服务id
这是提供给调用方的接口列表,就创建了一个provider接口。
1. ServerProvider 接口
/**
* @Data: 2019/12/10
* @Des: RPC提供的接口
*/
public interface ServerProvider {
String provider(String msg);
}
3. dubbo-provider-1、dubbo-provider-2
两个项目完全一样,只是端口不同,所以这里拿 dubbo-provider-1 模块讲解。
ServerProvierImpl 代码
import com.alibaba.dubbo.config.annotation.Service;
import com.kingfish.service.ServerProvider;
import org.springframework.beans.factory.annotation.Value;
/**
* @Data: 2019/12/10
* @Des:
*/
// 注意service注解是阿里的注解,不是spring的
// 配上版本号1.0.0说明向zookeeper注册的是版本为1.0.0的TestService接口,超时时长为3000ms等信息。
@Service(version = "1.0.0")
public class ServerProvierImpl implements ServerProvider {
@Value("${server.port}")
private int port;
@Override
public String provider(String msg) {
return "端口号 :" + port + " 提供了服务 : " + msg;
}
}
application.yml文件。 dubbo-provider-2 的端口号是8092和10002
server:
port: 8091
spring:
dubbo:
application:
name: dubbo-provider # 应用名
registry:
address: zookeeper://localhost #zookeeper地址
port: 2181
protocol:
name: dubbo
port: 10001 #dubbo服务暴露的端口
scan: com.kingfish.service #扫描的包
注意,这里引入的是 io.dubbo.springboot 的包,所以可以在yml中配置dubbo,但是引用这个包在使用Aop时会出现问题,这个后面再说。
4. dubbo-consumer
1. ServerConsumerController
import com.alibaba.dubbo.config.annotation.Reference;
import com.kingfish.service.ServerProvider;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("server")
public class ServerConsumerController {
// 引用dubbo中的注解。版本号1.0.0, 超时时间10s, 采用异步调用
@Reference(version = "1.0.0", timeout = 10000, async = true)
private ServerProvider serverProvider;
@RequestMapping("consumer")
public String consumer() {
String str = serverProvider.provider("哈哈哈哈");
System.out.println(str);
return str;
}
}
- application.yml
server:
port: 8090
spring:
dubbo:
application:
name: dubbo-provider # 应用名
registry:
address: zookeeper://localhost #zookeeper地址
port: 2181
protocol:
name: dubbo
port: 10000 #dubbo服务暴露的端口
scan: com.kingfish.controller #扫描的包名
5. 启动项目
千万不要把这个看做一个jar包间的调用!!!实际上,把这个三个服务剥离开,只需要改一下配置就可以继续访问了。
- 查看zk中的节点发现,服务提供者和服务消费者都已经注册进去
- 调用 http://localhost:8090/server/consumer 返回如下:
四、其它
1. dubbo 异步调用
这里写的比较简单,详细可以看 https://www.jianshu.com/p/3a706e544874
服务端在引用 @Reference注解时可以 async = true 参数通过开启异步调用,默认会返回null,如下。
1. 通过RpcContext获取Future对象,调用get方法时阻塞知道返回结果。
这种方式调用get方法会阻塞到返回
// 设置异步,超时10s
@Reference(version = "1.0.0", async = true, timeout = 10000)
private ServerProvider serverProvider;
@RequestMapping("consumer")
public String consumer() throws ExecutionException, InterruptedException {
serverProvider.provider("哈哈哈哈");
// 如果开启异步,默认会直接返回null。下面两种方式可以获取到结果
// 方式1 : 异步调用时使用
Future<String> future = RpcContext.getContext().getFuture();
// 会一直阻塞到异步调用返回结果
String str = future.get();
System.out.println(str);
return str;
}
2. 通过ResponseFuture设置回调,执行完成会回调done方法,抛异常则会回调caught方法:
这种方式会开启一个新线程来等待回调
// 设置异步,超时10s
@Reference(version = "1.0.0", async = true, timeout = 10000)
private ServerProvider serverProvider;
@RequestMapping("consumer")
public String consumer() throws ExecutionException, InterruptedException {
serverProvider.provider("哈哈哈哈");
// 如果开启异步,默认会直接返回null。下面两种方式可以获取到结果
// 方式1 : 异步调用时使用
ResponseFuture responseFuture = ((FutureAdapter)RpcContext.getContext().getFuture()).getFuture();
responseFuture.setCallback(new ResponseCallback() {
@Override
public void done(Object response) {
// RPC结果在这里获取
System.out.println("回调成功 : " + response);
}
@Override
public void caught(Throwable exception) {
System.out.println("回调成功 : " + exception.getMessage());
}
});
// System.out.println(str);
// 因为结果在回调中返回,所以这里随便返回
return "111";
}
2. io.dubbo.springboot 和 AOP 服务注册异常
在实际搭建这个项目过程中,加入Aop后会导致dubbo服务无法注册,网上搜索说是因为io.dubbo.springboot 所依赖的dubbo版本问题,但修改dubbo版本后会出现注册后节点加了一层代理对象节点的问题。下面提出上面两个问题的解决方案。
解决方案:
- 使用 io.dubbo.springboot 包,这时候duboo的配置就不能使用配置类方式,直接使用xml配置方式,xml 配置方式不会出现问题
- 不使用 io.dubbo.springboot 包,直接导入dubbo包,使用xml配置或者配置类方式配置都可。如下
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.7</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<!-- zookeeper客户端 -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.7</version>
</dependency>
3. dubbo 配置类方式配置
@Configuration
@EnableDubbo(scanBasePackages = {"com.kingfish.business.service"})
public class DubboConfig {
//<dubbo:application name="boot-user-service-provider"></dubbo:application>
@Bean
public ApplicationConfig applicationConfig() {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("dubbo-consumer");
return applicationConfig;
}
//<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry>
@Bean
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setProtocol("zookeeper");
registryConfig.setAddress("127.0.0.1:2181");
return registryConfig;
}
//<dubbo:protocol name="dubbo" port="20882"></dubbo:protocol>
@Bean
public ProtocolConfig protocolConfig() {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setName("dubbo");
protocolConfig.setPort(9999);
return protocolConfig;
}
}
4. dubbo xml 方式配置
<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="springboot-dubbo-provider"/>
<!-- 注册中心配置,使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" timeout="60000" />
<!--关闭服务消费方所有服务的启动检查。dubbo缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止Spring初始化完成。-->
<dubbo:consumer check="false" />
<!-- 用dubbo协议在29014端口暴露服务 -->
<dubbo:protocol name="dubbo" port="29014" />
<!-- 使用注解方式暴露接口,会自动扫描package下所有包中dubbo相关的注解,这样就不用在xml中再针对每个服务接口配置dubbo:service interface-->
<dubbo:annotation package="com.kingfish.business.service"/>
</beans>
以上:内容部分参考网络
https://www.jianshu.com/p/3a706e544874
如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正