1.架构
dubbo架构涉及的角色:
节点
角色说明
Provider
暴露服务的服务提供方
Consumer
调用远程服务的服务消费方
Registry
服务注册与发现的注册中心
Monitor
统计服务的调用次数和调用时间的监控中心
Container
服务运行容器
2.配置加载流程
Dubbo配置方式有XML配置、注解配置、API配置。支持多层级配置,按照优先级配置覆盖。
3.dubbo相关重要点
3.1 负载均衡
负载均衡策略有:
- 按权随机
- 按权轮询
- 最少活跃调用数:活跃数指调用前后技术差
- 一直性hash:缺省,对第一个参数做hash,缺省用160分虚拟节点
3.2 线程模型
3.3 服务分组
一个接口有多种实现时,使用group区分。
3.4 接口测试注意点
(1) 直连提供者
在开发测试环境下,可能存在绕过注册中心的情况下,测试某个服务提供者,这时需要点对点直连。可以有如下方式:
- xml 配置:<dubbo:reference id="xxxService" interface="com.alibaba.xxx.XxxService"
url="dubbo://localhost:8080" />
- 指定-D参数:java -Dcom.alibaba.xxx.XxxService=dubbo://localhost:8080
- 文件映射:用 -Ddubbo.resolve.file 指定映射文件路径
(2) 只订阅
方便开发测试,可能存在共用注册中心的情况,避免正开发的服务提供者影响服务消费者,可以让服务提供这只订阅服务(开发的服务可能依赖其他的服务),通过直连方式测试。
3.5 异步调用
v2.7.0起,dubbo的异步编程接口以CompletableFuture为基础,基于NIO的非阻塞实现,不需要启动多线程,相对多线程开销小。
3.6 多协议
dubbo支持在不同服务上支持多个协议或者同一个服务上同时支持多个协议。
支持的协议有dubbo、rmi、hessian、http、webservice、thrift、memcached、redis、rest
3.7 本地存根
远程服务调用后,客户端一般是接口,实现在服务端,提供方想在客户端提供部分执行逻辑如ThreadLocal缓存,提前验证参数,嗲用失败后伪造容错数据,需要在api带上stub。
3.8 并发控制
可以限制每个方法服务端并发执行的个数,设置executes属性
3.9 连接控制
限制服务端的连接个数,设置accepts属性值
3.10 延迟连接
延迟连接用户减少长连接数。有调用的时候才创建,设置lazy属性。
3.11 粘滞连接
一般用户有状态的服务,使客户端总是向调用同一个服务提供者,设置sticky属性。
3.12 令牌验证
令牌验证注册中心授权权限,可防止消费者绕过注册中心访问提供者,设置token属性。
3.13 集群容错
在集群调用失败时,Dubbo 提供了多种容错机制,缺省为 failover 重试。容错机制有:
- failover: 失败自动切换,重试其他服务器,通过设置retries属性(不包含第一次)
- failfast: 快速失败,只发起一次调用。
- failsafe:失败安全,出现异常直接忽略。
- failback:失败自动恢复,后台记录失败请求,定时重发。
- forking:并行调用多服务器,一个成功即返回,通过设置forks属性。
4.dubbo项目搭建
4.1 使用idea创建一个spring boot kotlin项目
(1) 点击菜单File->new Project->Spring Initializr->next
(2) 选择kotlin按照提示流程创建个人项目
(3) 按照上面流程创建一个父项目,保留pom文件、.idea 文件,删除无关文件,然后new module 添加模块
以上步骤就创建一个基于dubbo的spring boot kotlin多模块项目。
4.4 代码实现
基于接口开发,基于注解形式,不适用xml,spring boot 提倡约定大于配置
- 对于接口的提供方,使用注解@Service
- 对于接口的调用发使用@Reference
- 暴露的接口统一放在一个管理api的子模块
- 需要用到接口时,在pom文件引入模块
如下面例子所示:
<dependency>
<groupId>com.xhh</groupId>
<artifactId>xhh-practice-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
4.5 可能会遇到的问题
(1) @Reference 空引用问题
- 个人一开始未使用zookeeper注册中心,采用接口直连方式,需要在注解中设置好url属性,注意使用dubbo协议开头如:dubbo://。没有启动时不报错,接口调用发现失败,最终发现时配置不全导致的空引用问题
- 使用zookeeper注册中心时,本地已经搭建好zookeeper,需要配置的子模块也配置了zookeeper地址,启动项目时,时间间隔打印连接zookeeper信息,调用接口时,提示接口未注入实例。起初以为@Reference和@Service的注解缺少相关属性,例如版本,check、接口对象等,最后发现不是这个问题,发现子模块都还未成功注册到zookeeper,依赖配置还缺少一个zookeeper包,所以无法获得另外一个服务的接口代理对象,引入下面配置即可:
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>以上这些依赖包主要是实现在zookeeper原生API的基础上进行封装、实现一些开发细节,包括接连重连、注册等。
5.dubbo框架原理
5.1 SPI机制
服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,运行时加载实现类,动态为接口替换实现类。原生JDK标准SPI只能通过遍历查找拓展点和实例化,存在一次性加载所有拓展点的情况导致资源浪费,dubbo SPI机制解决了这个问题。
(1) 注解@SPI
表示该接口为可拓展接口。以下面说明为例子:
@SPI("netty")
public interface Transporter {
@Adaptive({"server", "transporter"})
Server bind(URL var1, ChannelHandler var2) throws RemotingException;
@Adaptive({"client", "transporter"})
Client connect(URL var1, ChannelHandler var2) throws RemotingException;
}
@SPI中的属性值,表示获取配置中key,会获取这个key对应的值,对应的值就是对应的实现类。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。