分布式服务之Dubbo

一、Dubbo介绍

Dubbo是一款高性能、轻量级的开源 Java 服务框架。

提供了六大核心能力:面向接口代理的高性能RPC调用,智能容错和负载均衡,服务自动注册和发现,高度可扩展能力,运行期流量调度,可视化的服务治理与运维。

Dubbo的主要功能

  1. RPC调用
  • 支持多协议(序列化、传输)
  • 服务注册发现
  • 配置、元数据管理

  1. 集群、高可用、管控
  • 集群、负载均衡
  • 治理、路由
  • 控制台、管理与监控

二、Dubbo技术原理

整体架构图:

  1. Config配置层:对外配置接口,以ServiceConfig,ReferenceConfig为中心,可以直接初始化配置类,也可以通过Spring解析配置生成配置类
  2. Proxy 服务代理层:服务接口透明代理,生成服务的客户端Stub和服务器端Skeleton,以ServiceProxy为中心,扩展接口为ProxyFactory
  3. Registry 注册中心层:封装服务地址的注册与发现,以服务URL为中心,扩展接口为RegistryFactory,Registry,RegistryService
  4. Cluster 路由层:封装多个提供者的路由及负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为Cluster,Directory,Router,LoadBalace
  5. Monitor 监控层:RPC调用次数和调用时间的监控,以Statistics为中心,扩展接口为MonitorFactory,Monitor,MonitorService
  6. Protocol 远程调用层:封装RPC调用,以Invocation,Result为中心,扩展接口为Protocol,Invoker,Exporter
  7. Exchange 信息交换层:封装请求响应模式,同步转异步,以Request,Response为中心,扩展接口为Exchanger,ExchangeChannel,ExchangeClient,ExchangeServer
  8. Transport 网络传输层:抽象mina和netty为统一接口,以Message为中心,扩展接口为Channel,Transporter,Client,Server,Codec
  9. Serialize 数据序列化层:可复用的一些工具,扩展接口为Serialization,ObjectInput,ObjectOutput,ThreadPool

SPI的应用

SPI与API

ServiceLoader机制

META-INF/dubbo/接口全限定名,文件内容为实现类

其他两个类似的机制:Callback和EventBus

服务如何暴露

服务如何引用

集群与路由

  • Router :选取此次调用可以提供服务的Invoker集合
  • LoadBalance :从上述集合中选取一个作为最终调用者

泛化引用

GenericService
当我们知道接口、方法和参数时,可以使用反射调用服务。

方法1:

<dubbo:reference id="barService" interface="com.foo.BarService" generic="true" /> GenericService barService = (GenericService) applicationContext.getBean("barService"); Object result = barService.$invoke("sayHello", new String[] { "java.lang.String" }, new Object[] { "World" });

方法2:

ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
reference.setInterface("com.xxx.XxxService");
reference.setVersion("1.0.0"); 
reference.setGeneric(true);
GenericService genericService = reference.get();

隐式传参
Context模式

RpcContext.getContext().setAttachment("index","1");

此参数可以传播到RPC调用的整个过程

Mock

将mock设为true,在实现一个对应的Mock实现类即可。如HelloService的Mock类为HelloServiceMock

三、Dubbo最佳实践

开发分包

  1. 建议将服务接口、服务模型、服务异常等均放在API包中,因为服务模型和异常也是API的一部分,这样做也服务分包原则。

  2. 服务接口尽可能大粒度,每个服务方法代表一个功能,否则将面临分布式事务问题

  3. 服务接口建议以业务场景为单位划分

  4. 不建议使用过于抽象的通用接口,如Map query(Map map),没有明确的语义,会给后期维护带来不便

环境隔离与分组

如何做到多环境隔离呢?

  1. 隔离性的部署多套
  2. 多注册中心机制
  3. Dubbo提供的group机制
  4. Dubbo提供的版本机制

参数配置

通用参数以consumer端为准,如果consumer端没有设置,则用provider数值

建议在Provider端配置的Consumer端属性有:

  • timeout: 方法调用超时时间
  • retries:失败重试次数
  • loadbalance:负载均衡算法
  • actives:消费者端的最大并发调用限制。

建议在Provider端配置的Provider端属性有:

  • threads:服务线程池大小
  • executes:一个服务提供者并行执行请求上限。

容器化部署

注册的ip问题,解决方法:

  1. 方法1: docker使用宿主机网络
  2. docker参数指定注册的ip和端口

运维和监控

Admin里面功能比较简单,可以整合自己公司的监控系统:

  • Promethus + Grafana

重试和幂等

服务调用失败会默认重试,所以接口需要幂等性

设计幂等接口方法:

  • 去重。 可以通过redis、bitMap等
  • 类似乐观锁机制判断

四、源码解析

带着问题去看

  1. 如何代理服务的?
  2. 如何发送远程请求的?
  3. 配置如何生效的?
  4. 异常处理?
  5. 超时机制?
  6. 优雅停机?
书山有路勤为径,学海无涯苦作舟
原文地址:https://www.cnblogs.com/javammc/p/15141356.html