一、dubbo 概述
Apache Dubbo 是一款高性能、轻量级的开源 Java RPC 框架,它提 供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和 发现。Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案、服 务治理方案。
二、基本架构
服务提供者(Provider):暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。
服务消费者(Consumer): 调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
注册中心(Registry):注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
监控中心(Monitor):服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
调用关系说明:
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
三、dubbo 支持的协议
支持多种协议:dubbo , hessian , rmi , http, webservice , thrift , memcached , redis。 dubbo 官方推荐使用 dubbo 协议。dubbo 协议默认端口 20880
使用 dubbo 协议,spring 配置文件加入:
<dubbo:protocol name="dubbo" port="20880" />
四、dubbo 常用标签
Dubbo 中常用标签。分为三个类别:公用标签,服务提供者标签,服务消费者标签
1. 公用标签
<dubbo:application/> 和 <dubbo:registry/>
① 配置应用信息
<dubbo:application name=”服务的名称”/>
② 配置注册中心
<dubbo:registry address=”ip:port” protocol=”协议”/>
2. 服务提供者标签
① 配置暴露的服务
<dubbo:service interface=”服务接口名” ref=”服务实现对象 bean”>
3. 服务消费者
① 配置服务消费者引用远程服务
<dubbo:reference id=”服务引用 bean 的 id” interface=”服务接口名”/>
五、注册中心
对于服务提供方,它需要发布服务,而且由于应用系统的复杂性,服务的数量、类型也不断膨胀;对于服务消费方,它最关心如何获取到它所需要的服务,而面对复杂的应用系统,需要管理大量的服务调用。
而且,对于服务提供方和服务消费方来说,他们还有可能兼具这两种角色,即需要提供 服务,有需要消费服务。 通过将服务统一管理起来,可以有效地优化内部应用对服务发布/使用的流程和管理。服务注册中心可以通过特定协议来完成服务对外的统一。Dubbo 提供 的注册中心有如下几种类型可供选:
Multicast 注册中心:组播方式
Redis 注册中心:使用 Redis 作为注册中心
Simple 注册中心:就是一个 dubbo 服务。作为注册中心。提供查找服务的功能。
Zookeeper 注册中心:使用 Zookeeper 作为注册中心
推荐使用 Zookeeper 注册中心。
1. Zookeeper 注册中心
Zookeeper 是一个高性能的,分布式的,开放源码的分布式应用程序协调服务。简称 zk。Zookeeper 是翻译管理是动物管理员。可以理解为 windows 中的资源管理器或者注册表。他是一个树形结构。这种树形结构和标准文件系统相似。ZooKeeper 树中的每个节点被称为Znode。和文件系统的目录树一样,ZooKeeper 树中的每个节点可以拥有子节点。每个节点表示一个唯一服务资源。Zookeeper 运行需要 java 环境。
① 下载zookeeper,官网:https://zookeeper.apache.org/
② 修改配置 /conf/zoo_sample.cfg
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/tmp/zookeeper
# the port at which the clients will connect
clientPort=2181
admin.serverPort=8888
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
③ 导入依赖
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.1.0</version>
</dependency>
若启动报错:java.lang.NoClassDefFoundError:org/apache/curator/framework/recipes/cache/TreeCacheListener ,则导入依赖
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.1.0</version>
</dependency>
2. 注册中心的高可用
① 概念:
高可用性(High Availability):通常来描述一个系统经过专门的设计,从而减少不能提供服 务的时间,而保持其服务的高度可用性。Zookeeper 是高可用的,健壮的。Zookeeper 宕机,正在运行中的 dubbo 服务仍然可以正 常访问。
② 健壮性 :
监控中心宕掉不影响使用,只是丢失部分采样数据
注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
服务提供者无状态,任意一台宕掉后,不影响使用
服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复
六、dubbo 服务化
1. 分包
建议将服务接口、服务模型、服务异常等均放在公共包中。
2. 粒度
① 服务接口尽可能大粒度,每个服务方法应代表一个功能,而不是某功能的一个步骤,否则将面临分布式事务问题,Dubbo 暂未提供分布式事务支持。
② 服务接口建议以业务场景为单位划分,并对相近业务做抽象,防止接口数量爆炸。
③ 不建议使用过于抽象的通用接口,如:Map query(Map),这样的接口没有明确语义,会给后期维护带来不便。
3. 版本
1. 每个接口都应定义版本号,为后续不兼容升级提供可能。当一个接口有不同的实现,项目早期使用的一个实现类, 之后创建接口的新的实现类。区分不同的接口实现使用 version。特别是项目需要把早期接口的实现全部换位新的实现类,也需要使用 version.
2. 可以用版本号从早期的接口实现过渡到新的接口实现,版本号不同的服务相互间不引用。
3. 可以按照以下的步骤进行版本迁移:
① 在低压力时间段,先升级一半提供者为新版本
② 再将所有消费者升级为新版本
③ 然后将剩下的一半提供者升级为新版本
4. 每个接口都应定义版本号,为后续不兼容升级提供可能,如: <dubbo:service interface="com.xxx.XxxService" version="1.0" />。
5. 建议使用两位版本号,要变更服务版本。先升级一半提供者为新版本,再将消费者全部升为新版本,然后将剩下的一半提供者升为新版本
七、快速开始
dubbo依赖
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.1</version>
</dependency>
1. 服务提供者
① 定义服务接口
package org.apache.dubbo.demo;
public interface DemoService {
String sayHello(String name);
}
② 在服务提供方实现接口
package org.apache.dubbo.demo.provider;
import org.apache.dubbo.demo.DemoService;
public class DemoServiceImpl implements DemoService {
public String sayHello(String name) {
return "Hello " + name;
}
}
③ 用 Spring 配置声明暴露服务
<?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-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="hello-world-app" />
<!-- 使用zookeeper广播注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://localhost:2181" />
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService" />
<!-- 和本地bean一样实现服务 -->
<bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl" />
</beans>
④ 在web.xml中加载 Spring 配置
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:provider.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
2. 服务消费者
① 通过 Spring 配置引用远程服务
<?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-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="consumer-of-helloworld-app" />
<!-- 使用zookeeper广播注册中心暴露发现服务地址 -->
<dubbo:registry address="zookeeper://localhost:2181" />
<!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<dubbo:reference id="demoService" interface="org.apache.dubbo.demo.DemoService" />
</beans
② 加载Spring配置,并调用远程服务
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.apache.dubbo.demo.DemoService;
public class Consumer {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"META-INF/spring/dubbo-demo-consumer.xml"});
context.start();
DemoService demoService = (DemoService)context.getBean("demoService"); // 获取远程服务代理
String hello = demoService.sayHello("world"); // 执行远程方法
System.out.println( hello ); // 显示调用结果
}
}
更多可以访问Dubbo官网:https://dubbo.apache.org/zh/