1. Dubbo介绍
1. 开篇
介绍主要介绍Dubbo框架、Dubbo的基本应用以及Dubbo的基本原理。
2. Dubbo介绍
官网:dubbo.apache.org/zh/index.ht…
Apache Dubbo 是一款微服务框架,为大规模微服务实践提供高性能 RPC 通信、流量治理、可观测性等解决方案,并提供了Java、Golang、Erlang、Rust等多种语言的SDK实现。
如果经常关注Dubbo的话可以注意到,官网对Dubbo的介绍经历了几个版本。
刚开始的时候是这么介绍的:
Apache Dubbo 是一款高性能、轻量级的开源 Java RPC 框架。
经过了一段时间介绍更改为:
Apache Dubbo 是一款高性能、轻量级的开源 Java 服务 框架。
可以看到对于Dubbo的定位已经发生了几次变化,从RPC框架->服务框架->微服务框架
。
Dubbo一开始把自己定位为一个RPC框架,专注于服务之间的调用。随着微服务的概念越来越火爆,Dubbo开始重新思考自己的定位,提升自己的格局,除了服务调用,开始逐渐向服务治理、服务监控、服务网关等方向扩展,随着Dubbo生态圈的逐渐完善,Dubbo慢慢的演变为一个成熟的微服务框架。
RPC
RPC是远程过程调用
(Remote Procedure Call)的缩写形式,也就是我们常说的远程方法调用
。
与远程方法调用的是本地方法调用
。
本地方法调用
指的是进程内部的方法调用,简单理解就是一个类中的方法调用本类或其他类的方法。
远程方法调用
指的是两个进程内的方法相互调用,调用方式基本上都是通过网络传输数据来进行调用。例如,进程A的一个方法在调用进程B的一个方法时,通过网络把要调用的类
、方法名
、参数类型
、参数
、版本
等等信息传给进程B,进程B执行完后再通过网络把执行结果传递给进程A。
其中类
、方法名
、参数类型
、参数
、版本
这些信息,在两个进行之间传输需要达成一致才能进行调用。
3. Dubbo架构
Dubbo的总体架构图如上,图中各个节点的角色说明如下:
Container
:服务运行的容器
Provider
: 服务提供者
Registry
:注册中心
Consumer
:服务消费者
Monitor
:监控中心
Registry
注册中心这个角色非常重要,他的职责主要为服务注册
和服务发现
。Dubbo支持接口级别
和应用级别
的服务发现和服务注册。
简单讲就是,我可以把自己的服务暴露在注册中心上,供其他服务来调用。或者我可以从注册中心上查找我可以调用哪些服务。
注册中心不是必选的,如果是本地直连的话是不需要部署注册中心的。
Dubbo支持的注册中心有:Zookeeper
、Nacos
、Redis
、Multicast
,其中Zookeeper
和Nacos
是最常用的注册中心。
Monitor
监控中心可以用来统计服务的调⽤次数和调⽤时间,这些统计数据会先在内存中汇总,然后发送到监控中心服务器。
另外监控中心可以为服务的运维监控提供数据。
监控中心支持自定义扩展,满足个性化运维需求。比如:服务健康检测、服务压力以及性能统计、服务告警等。
Monitor
也不是必须的,监控中心宕机后也不会影响Provider
和Consumer
之间的服务调用。
4. Dubbo工作原理
Dubbo大致请求流程如下:
- 容器启动、加载、运行服务提供者。
- 服务提供者启动,提供自己的服务。提供服务的过程主要包括:提供服务的接口、注册服务(本地注册、注册中心注册)、暴露服务、启动Tomcat、Netty接受处理请求。把自己的主机地址、端口等信息注册到注册中心。
- 注册中心接受注册请求,保存服务名与服务器的地址映射关系,或感知服务地址变动通知消费者。
- 服务消费者启动时,从注册中心获取服务提供者的地址信息并缓存起来,根据负载均衡算法,从服务提供者地址列表里选择一个服务进行服务调用。
- 服务提供者和消费者在产生调用时,在内存中统计调用次数和时间,定时发送到监控中心。
5. 基本应用
了解了Dubbo的基本概念和工作原理,写个代码试下吧。
本示例采用版本如下:
dubbo:2.7.15
gradle:6.7
代码整体结构如下,一个简单的demo,不复杂。
dubbo-api
api模块为公共模块,定义一个简单的接口,作为项目依赖供服务者和消费者使用。
public interface HelloService {
String sayHello(String name);
default String sayGoodbye(String name) {
return "Goodbye, " + name;
}
}
dubbo-provider
服务提供者,定义接口的实现,提供服务。
引入依赖build.gradle
dependencies {
implementation project(':dubbo-api')
implementation 'org.apache.dubbo:dubbo:2.7.15'
implementation 'org.apache.dubbo:dubbo-dependencies-zookeeper:2.7.15'
}
服务提供者的配置文件provider.properties
# 应用名
dubbo.application.name=dubbo-provider
# 注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
# 使用的协议
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
服务提供者启动类ProviderApplication.java
@Configuration
@EnableDubbo
@PropertySource("classpath:provider.properties")
public class ProviderApplication {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderApplication.class);
context.start();
System.out.println("dubbo service started.");
new CountDownLatch(1).await();
}
}
对接口的实现HelloServiceImpl.java
@DubboService
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
System.out.println("provider received invoke of sayHello: " + name);
return "Hello, " + name;
}
public String sayGoodbye(String name) {
System.out.println("provider received invoke of sayGoodbye: " + name);
return "Goodbye, " + name;
}
}
dubbo-consumer
服务消费者
同样的先引入依赖build.gradle
dependencies {
implementation project(':dubbo-api')
implementation 'org.apache.dubbo:dubbo:2.7.15'
implementation 'org.apache.dubbo:dubbo-dependencies-zookeeper:2.7.15'
}
服务消费者的配置文件provider.properties
# 应用名
dubbo.application.name=dubbo-consumer
# 注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
服务消费者启动类ConsumerApplication.java
@Configuration
@EnableDubbo
@ComponentScan
@PropertySource("classpath:consumer.properties")
public class ConsumerApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerApplication.class);
context.start();
ConsumerService consumerService = (ConsumerService) context.getBean("consumerService");
consumerService.sayHello();
consumerService.sayGoodbye();
}
}
定义一个service,用来调用dubbo服务。
@Service
public class ConsumerService {
@DubboReference
private HelloService helloService;
public void sayHello() {
String result = helloService.sayHello("world");
System.out.println(result);
}
public void sayGoodbye() {
String result = helloService.sayGoodbye("world");
System.out.println(result);
}
}
6. 结束
到此,一个简单的dubbo小项目就实现了。