两小时学会使用dubbo(直接API、spring、注解、springboot)
最近上新的项目中需要用到dubbo,于是我决定温故知新,决定分享一下Dubbo在各种环境下的使用方式,本篇文章让你两小时就能学会使用dubbo
什么是Dubbo
Dubbo是一个分布式、高性能、透明化的RPC服务框架,提供服务自动注册、自动发现等高效服务治理方案,可以和Spring框架无缝集成。Dubbo最常用的应用就是远程调用。
Dubbo中服务端最核心的对象有四个:
- ApplicationConfig:配置当前应用信息
- ProtocolConfig:配置提供服务的协议信息
- RegistryConfig:配置注册相关信息
- ServiceConfig:配置暴露的服务信息
Dubbo客户端中核心的对象有两个:
- ApplicationConfig:配置当前应用信息
- ReferenceConfig:配置引用的服务信息
Dubbo的主要应用场景
透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。
软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。(F5负载均衡器我也是百度来的)。
服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。
Dubbo的使用
接下来通过四种方式入门Dubbo。首先会通过原生API直接展示dubbo的直连和注册中心实现方式,接着使用Spring、注解和SpringBoot的方式分别展示如何使用Dubbo。
案例源码点击这里
在写dubbo相关代码前,首先要定义一个公共的api服务,这个服务里存放的是service接口。服务提供者引入这个工程,写实现类,提供dubbo接口;服务消费者引入这个工程,通过这个工程的service接口调用。
User类:
@Data //RPC调用一般不建议使用lombok注解,容易出很多bug,这里使用是为了方便
public class User implements Serializable {
private static final long serialVersionUID = -9206514891359830486L;
private Long id;
private String name;
private String sex;
}
UserService:
public interface UserService {
User getUser(Long id);
}
原生API
通过原生API的方式生成一个dubbo服务,并且用另外一个类去调用这个dubbo服务:
- 引入依赖
核心依赖就两个,一个dubbo的依赖,另外一个上面的公共接口方法,服务提供方和消费者都需要引入这两个依赖
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.4.1</version>
</dependency>
<dependency>
<artifactId>dubbo-api</artifactId>
<groupId>com.seven.direct-dubbo-demo.api</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
- 服务提供者
服务提供者主要配置以下几个属性:
- application:设置应用的名称等信息
- protocol :设置服务的协议
- register:设置服务的连接方式
- service:将需要暴露的服务注册出来
public class DubboProvider {
public static void main(String[] args) throws IOException {
//暴露UserService服务
//1、application
ApplicationConfig applicationConfig = new ApplicationConfig("sample-provider");
//2、protocol -dubbo协议
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setName("dubbo");
protocolConfig.setPort(20880);
//3、register
//直连的方式,不暴露到注册中心
RegistryConfig registryConfig = new RegistryConfig(RegistryConfig.NO_AVAILABLE);
//4、service
ServiceConfig serviceConfig = new ServiceConfig();
serviceConfig.setInterface(UserService.class);
serviceConfig.setRef(new UserServiceImpl());
//5、将application、protocol、register注册到service
serviceConfig.setRegistry(registryConfig);
serviceConfig.setProtocol(protocolConfig);
serviceConfig.setApplication(applicationConfig);
serviceConfig.export();
System.out.println("服务已经暴露");
System.in.read();
}
}
- 服务消费者
消费者的实现主要就三步:
- 配置application:设置应用的名称等信息
- 配置reference:主要配置要引用的信息
- 获取到接口,调用服务。
public class DubboConsumer {
public static void main(String[] args) {
//1、application
ApplicationConfig applicationConfig =new ApplicationConfig("sample-consumer");
//2、配置reference
ReferenceConfig referenceConfig = new ReferenceConfig();
referenceConfig.setApplication(applicationConfig);
referenceConfig.setInterface(UserService.class);
referenceConfig.setUrl("dubbo://127.0.0.1:20880/com.seven.directdubbodemo.api.service.UserService?anyhost=true&application=sample&bind.ip=127.0.0.1&bind.port=20880&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=com.seven.directdubbodemo.api.service.UserService&methods=getUser&pid=5936&release=2.7.4.1&side=provider×tamp=1728390413736");
UserService userService = (UserService) referenceConfig.get();
User user = userService.getUser(1L);
System.out.println(user);
}
}
先启动提供者,再启动消费者,如果user信息打印出来了就说明调用成功。
- 使用zookeeper作为注册中心
上面的Register使用的是直连的方式,也可以使用注册中心,这里以zookeeper为例。首先在项目中引入zookeeper相关依赖:
<!-- zk客户端依赖:curator -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.13.0</version>
</dependency>
服务提供者修改一处地方,将RegistryConfig修改为zookeeper的连接方式
//register
//直连的方式,不暴露到注册中心
//RegistryConfig registryConfig=new RegistryConfig(RegistryConfig.NO_AVAILABLE);
//通过注册中心暴露dubbo
RegistryConfig registryConfig = new RegistryConfig("zookeeper://127.0.0.1:2181");
消费者同样修改一处位置,将referenceConfig中的setUrl方法替换为zookeeper:
RegistryConfig registryConfig = new RegistryConfig("zookeeper://127.0.0.1:2181");
ReferenceConfig referenceConfig = new ReferenceConfig();
referenceConfig.setRegistry(registryConfig);
referenceConfig.setApplication(applicationConfig);
referenceConfig.setInterface(UserService.class);
//referenceConfig.setUrl("dubbo://127.0.0.1:20880/com.seven.directdubbodemo.api.service.UserService?anyhost=true&application=sample&bind.ip=127.0.0.1&bind.port=20880&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=com.seven.directdubbodemo.api.service.UserService&methods=getUser&pid=5936&release=2.7.4.1&side=provider×tamp=1728390413736");
Spring集成dubbo
通过Spring的方式只不过是把上面写在Java中的代码拿到配置文件中去,并把接口注入到Bean容器中
- 引入spring相关依赖
在provider和consumer的模块下额外引入spring相关依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.37</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.37</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.37</version>
</dependency>
- 在resource文件夹下新建两个配置文件
provider.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://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="spring-provider"/>
<!-- 使用zookeeper广播注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.seven.springdubbodemo.springdubboapi.service.UserService" ref="userService" loadbalance="roundrobin"/>
<!-- 和本地bean一样实现服务 -->
<bean id="userService" class="com.seven.springdubbodemo.springdubboprovider.impl.UserServiceImpl"/>
</beans>
consumer.xml
<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="spring-consumer" />
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<dubbo:reference id="userService" interface="com.seven.springdubbodemo.springdubboapi.service.UserService" loadbalance="roundrobin"/>
</beans>
- 启动类
这里的配置文件和上方的代码均一一对应。服务的提供者和消费者:
SpringDubboProvider:
public class SpringDubboProvider {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("provider.xml");
System.out.println("服务已经暴露");
System.in.read();
}
}
SpringDubboConsumer
public class SpringDubboConsumer {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("consumer.xml");
UserService bean = context.getBean(UserService.class);
System.out.println(bean.getUser(1L));
}
}
纯注解版
注解的方式就是不在xml文件中注入bean,xml文件中只需要写包名即可
- provider修改
provider.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://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="anno-provider"/>
<!-- 使用zookeeper广播注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 注解版 -->
<dubbo:annotation package="com.seven.annotationdubbodemo.annodubboprovider.impl"/>
</beans>
UserService实现类
import org.apache.dubbo.config.annotation.Service;
@Service //dubbo的@Service注解
public class UserServiceImpl implements UserService {
@Override
public User getUser(Long id) {
User user = new User();
user.setId(id);
user.setName("Seven");
user.setSex("男");
return user;
}
}
- consumer修改
consumer.xml
<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"
xmlns:context="http://www.springframework.org/schema/context"
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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<dubbo:application name="anno-consumer" />
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- 注解版 -->
<dubbo:annotation package="com.seven.annotationdubbodemo.annodubboapi.service"/>
<context:component-scan base-package="com.seven.annotationdubbodemo.annodubboconsumer.controller"/>
</beans>
controller类
@Controller
public class UserController {
@Reference //import org.apache.dubbo.config.annotation.Reference;
private UserService userService;
public User getUser(long id){
return userService.getUser(id);
}
}
SpringBoot集成dubo
引入dubbo和springboot的核心依赖
<!-- 引入spring-boot-starter以及dubbo和curator的依赖 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.5</version>
</dependency>
<!-- Spring Boot相关依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.7.5</version>
</dependency>
- 服务提供者provider
这里的配置都写在application.properties中:
#当前服务/应用的名字
dubbo:
application:
name: springboot-provider
#注册中心的协议和地址
registry:
protocol: zookeeper
address: 127.0.0.1:2181
#通信规则(通信协议和接口)
protocol:
name: dubbo
port: 20880
# 负载均衡算法
provider:
loadbalance: roundrobin
服务提供者需要写服务的实现类,这里需要注意@Service注解采用的是dubbo包下:
import com.seven.springbootdubbodemo.api.entity.User;
import com.seven.springbootdubbodemo.api.service.UserService;
import org.apache.dubbo.config.annotation.Service;
@Service
public class UserServiceImpl implements UserService {
@Override
public User getUser(Long id) {
User user = new User();
user.setId(id);
user.setName("Seven");
user.setSex("男");
return user;
}
}
接着在启动类上添加一个@EnableDubbo注解即可。
@EnableDubbo
@SpringBootApplication
public class App{
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
- 服务的消费者consumer
配置文件:
#避免和provider端口冲突,设为8081端口访问
server:
port: 8081
#当前服务/应用的名字
dubbo:
application:
name: springboot-consumer
#注册中心的协议和地址
registry:
protocol: zookeeper
address: 127.0.0.1:2181
#通信规则(通信协议和接口)
protocol:
name: dubbo
port: 20880
# 负载均衡算法
consumer:
loadbalance: roundrobin
接着通过@Reference注解将service对象引进来
@SpringBootApplication
public class App{
@Reference
UserService userService;
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@Bean
public ApplicationRunner getBean(){
return args -> {
System.out.println(userService.getUser(1L));
};
}
}
dubbo的常用配置
- xml配置
<dubbo:application/> 用于配置当前应用信息
<dubbo:register/> 用于配置连接注册相关信息
<dubbo:protocol/> 用于配置提供服务的协议信息,提供者指定协议,消费者被动接受
<dubbo:service/> 用于暴露一个服务,一个服务可以用多个协议暴露,一个服务也可以注册到多个注册中心。provider端配置
<dubbo:reference/> 用于创建一个远程服务代理。consumer端配置
- springboot配置
dubbo:
application:
name: dubbo-springboot-demo-provider
protocol:
name: dubbo
port: 50052
registry:
address: zookeeper://127.0.0.1:2181
更加具体的配置信息可以参考:配置项参考手册 | Apache Dubbo
企业中如何通过dubbo实现分布式调用
在企业中,如果消费者直接通过RPC去调用提供者,理论上需要把提供者的整个Jar包引入到项目中。但是这样的话服务提供这种的其他无关代码也会被引入其中,导致代码污染。
因此实际开发过程中,服务提供者和调用者之间会增加一层API模块。这个API中主要写的是Service的接口定义,接口的返回实例对象以及接口的请求实例对象。简单来讲,所有的定义都在API中完成。
使用时,服务提供者引入这个API,然后写实现方法,服务消费者引入这个API,然后通过dubbo直接调用即可。
另外企业开发中,可能会出现多个接口实现,这种情况下可以给Service设定group、version等进行区分。
关于作者
来自一线程序员Seven的探索与实践,持续学习迭代中~
本文已收录于我的个人博客:https://www.seven97.top
公众号:seven97,欢迎关注~
两小时学会使用dubbo(直接API、spring、注解、springboot)的更多相关文章
- 三小时学会Kubernetes:容器编排详细指南
三小时学会Kubernetes:容器编排详细指南 如果谁都可以在三个小时内学会Kubernetes,银行为何要为这么简单的东西付一大笔钱? 如果你心存疑虑,我建议你不妨跟着我试一试!在完成本文的学习后 ...
- 【转载】一个小时学会MySQL数据库
一个小时学会MySQL数据库 目录 一.数据库概要 1.1.发展历史 1.1.1.人工处理阶段 1.1.2.文件系统 1.1.3.数据库管理系统 1.2.常见数据库技术品牌.服务与架构 1.3.数 ...
- Apache Dubbo 官方正式发布 Spring 6 & Spring Boot 3 支持
Dubbo 简介 Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提供了 Java.Golang 等多语言 SDK 实现.使用 Dubbo 开发的 ...
- 一小时学会微信小程序
一小时学会微信小程序 目录 一.小程序概要 1.1.发展历史 1.2.小程序的诞生 二.微信小程序介绍 三.开发微信小程序的软件下载与初步配置 3.1.获取微信小程序的AppID 3.2.下载安装微 ...
- Python入门教程 超详细1小时学会Python(转)
假设我们有这么一项任务:简单测试局域网中的电脑是否连通.这些电脑的ip范围从192.168.0.101到192.168.0.200. 思路:用shell编程.(Linux通常是bash而Windows ...
- Android开发工程师文集-1 小时学会各种Drawable
前言 大家好,给大家带来Android开发工程师文集-1 小时学会各种Drawable的概述,希望你们喜欢 Drawable介绍 Drawable为抽象类,drawable与view有区别的地方,主要 ...
- Python入门教程 超详细1小时学会Python
Python入门教程 超详细1小时学会Python 作者: 字体:[增加 减小] 类型:转载 时间:2006-09-08我要评论 本文适合有经验的程序员尽快进入Python世界.特别地,如果你掌握Ja ...
- 实例教程:1小时学会Python(转)
1 序言 面向读者 本文适合有经验的程序员尽快进入Python2.x世界.特别地,如果你掌握Java和Javascript,不用1小时你就可以用Python快速流畅地写有用的Python程序. Pyt ...
- 半小时学会V语言
半小时学会V语言 1. V语言简介 V是一个静态类型.编译型的编程语言,目标是构建可维护软件.与Go语言相似,并受Oberon,Rust和Swift语言影响.V语言非常简单,只需要半小时就能学会这门语 ...
- Dubbo -- 关于 api接口调用不使用强依赖
首先,我们都知道 Dubbo 调用api 需要提供暴露 接口, 消费端才通过 ZK 可以调用 通常我们都会使用 提供 api jar包 的方式 使用 这样既方便又快捷 简单 只需要在spr ...
随机推荐
- 【ECharts】01 快速上手
简单介绍: ECharts 是一个使用 JavaScript 实现的开源可视化库,涵盖各行业图表,满足各种需求. ECharts 遵循 Apache-2.0 开源协议,免费商用. ECharts 兼容 ...
- 【FastDFS】06 SpringBoot实现上传
创建SpringBoot工程: 再导入所需要的依赖: <dependency> <groupId>net.oschina.zcx7878</groupId> < ...
- Google的TPU的逐元素操作特性 —— TPU数据操作时最基本的操作原语(primitive)
地址: https://jax.readthedocs.io/en/latest/pallas/tpu.html TPU是原来进行矩阵计算加速的一个科学计算的设备,功能大致等同于NVIDIA的GPU的 ...
- 代码随想录Day10
232.用栈实现队列 请你仅使用两个栈实现先入先出队列.队列应当支持一般队列支持的所有操作(push.pop.peek.empty): 实现 MyQueue 类: void push(int x) 将 ...
- C# ?. 判斷Null值
有一句代碼: @Html.DisplayFor(modelItem => item.SellDate, "RegularDate") RegularDate.cshtml 內 ...
- 通过 C# 将数据写入到Excel表格
Excel 是一款广泛应用于数据处理.分析和报告制作的电子表格软件.在商业.学术和日常生活中,Excel 的使用极为普遍.本文将详细介绍如何使用免费.NET库将数据写入到 Excel 中,包括文本.数 ...
- 一次生产环境mysql迁移操作(一)数据归档
一次生产环境mysql迁移操作(一)数据归档 一次生产环境mysql迁移操作(二)mysql空间释放(碎片整理) 背景 在项目过程中我们经常要对数据库进行迁移.归档.拆分等等操作,现在描述下几种方案 ...
- CSS2基础(part-1)
CSS2基础 基础 简介 [全称]Cascading Style Sheets,又名层叠样式表 层叠:一层一层涂上去 表:列表 样式:如文字大小,颜色,元素宽高等. CSS 描述了在屏幕.纸质.音频等 ...
- P7706 文文的摄影布置 题解
P7706 文文的摄影布置 题解 原题 读完题,发现是线段树.单点修改+区间查询. 不过查询的值有些奇怪,就是了,我们考虑用线段树维护这个 ψ 值(下称待求值). 对于一个区间的待求值,大概有四种情况 ...
- Oracle——navicat连接Oracle数据库报错(12514)
2024/07/22 1.问题描述 2.解决办法 3.参考材料 1.问题描述 与其他厂商做数据对接时,对方提供相关视图,我navicat连接Oracle数据库时报错,其报错代码如下: ORA-1251 ...