高级JAVA开发 Dubbo部分

Dubbo

参考和摘自:
中华石杉 《Java工程师面试突击第1季》
Dubbo 官网文档

Dubbo架构&框架设计

架构
在这里插入图片描述
Dubbo 架构具有以下几个特点,分别是连通性、健壮性、伸缩性、以及向未来架构的升级性。参考:架构

重点摘抄:

  1. 注册中心和监控中心全部宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表
  2. 注册中心和监控中心都是可选的,服务消费者可以直连服务提供者
  3. 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复

框架设计

加上用户实现的业务service,一共10层:

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

Dubbo的网络通信协议&序列化

网络通信协议不同,在各场景下性能不同。dubbo协议采用单链接长链接,适合频繁小数据包传输,不适合大数据包传输(会一直占用IO通道)。单链接的好处就是减少了频繁创建链接时不得不做出的额外消耗(握手验证 等)。并使用异步 IO,复用线程池,防止 C10K 问题。以下介绍不同协议适合的场景。

协议参考手册

协议 连接个数 连接方式 传输协议 传输方式 序列化 适用范围 适用场景
dubbo(缺省 单连接 长连接 TCP NIO 异步传输 Hessian 二进制序列化 - 传入传出参数数据包较小(建议小于100K)
- 消费者比提供者个数多,单一消费者无法压满提供者
- 尽量不要用 dubbo 协议传输大文件或超大字符串
常规远程服务方法调用
rmi 多连接 短连接 TCP 同步传输 Java 标准二进制序列化 - 传入传出参数数据包大小混合
- 消费者与提供者个数差不多
- 可传文件
常规远程服务方法调用,与原生RMI服务互操作
hessian 多连接 短连接 HTTP 同步传输 Hessian二进制序列化 - 传入传出参数数据包较大
- 提供者比消费者个数多,提供者压力较大
- 可传文件
页面传输,文件传输,或与原生hessian服务互操作
http 多连接 短连接 HTTP 同步传输 表单序列化 - 传入传出参数数据包大小混合
- 提供者比消费者个数多
- 可用浏览器查看,可用表单或URL传入参数
- 暂不支持传文件
需同时给应用程序和浏览器 JS 使用的服务。
webservice 多连接 短连接 HTTP 同步传输 SOAP 文本序列化 系统集成,跨语言调用
thrift
memcached
redis
rest

序列化框架优缺点:

优点 缺点
Kryo 速度快,序列化后体积小 跨语言支持较复杂
Hessian 默认支持跨语言 较慢
Protostuff 速度快,基于protobuf 需静态编译
Protostuff-Runtime 无需静态编译,但序列化前需预先传入schema 不支持无默认构造函数的类,反序列化时需用户自己初始化序列化后的对象,其只负责将该对象进行赋值
Java 使用方便,可序列化所有类 速度慢,占空间

引自:序列化框架性能对比(kryo、hessian、java、protostuff)

负载均衡策略

缺省为 random 随机调用。

  • Random LoadBalance
    随机,按权重设置随机概率。
    在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
  • RoundRobin LoadBalance
    轮询,按公约后的权重设置轮询比率。
    存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
  • LeastActive LoadBalance
    最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
    使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
  • ConsistentHash LoadBalance
    一致性 Hash,相同参数的请求总是发到同一提供者。
    当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
    算法参见:http://en.wikipedia.org/wiki/Consistent_hashing
    缺省只对第一个参数 Hash,如果要修改,请配置 <dubbo:parameter key=“hash.arguments” value=“0,1” />
    缺省用 160 份虚拟节点,如果要修改,请配置 <dubbo:parameter key=“hash.nodes” value=“320” />

参见官方 负载均衡

集群容错

缺省为 failover 重试

  • Failover Cluster
    失败自动切换,当出现失败,重试其它服务器 。通常用于读操作,但重试会带来更长延迟。可通过 retries=“2” 来设置重试次数(不含第一次)。
  • Failfast Cluster
    快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
  • Failsafe Cluster
    失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
  • Failback Cluster
    失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
  • Forking Cluster
    并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=“2” 来设置最大并行数。
  • Broadcast Cluster
    广播调用所有提供者,逐个调用,任意一台报错则报错 [2]。通常用于通知所有提供者更新缓存或日志等本地资源信息。

参见官方 集群容错

Dubbo SPI(Service Provider Interface)& Dubbo的Filter

官方:DubboSPI
总结:Dubbo 并未使用 Java SPI,而是重新实现了一套功能更强的 SPI 机制。
两者在使用上最大的区别是Java SPI配置多实现出来的是个列表,Dubbo SPI配置出来的是个字典(键值对)。在框架中使用:在接口上注解@SPI(“keyName”),keyName即为实现类key,dubbo自己的jar包的/META-INF/dubbo/internal/下寻找实现类配置后加载实现类。

替换动态代理示例:

# 添加如下JavassistProxyFactory 实现类:
 public class MyselfJavassistProxyFactory extends JavassistProxyFactory {
    public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
        return (T) Proxy.getProxy(interfaces).newInstance(new SevenMinInvokerInvocationHandler(invoker));
    }
    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        return super.getInvoker(proxy, type, url);
    }
 }
# /META-INF/dubbo/com.alibaba.dubbo.rpc.ProxyFactory 配置如下:
 myselfJavassistProxyFactory=com.example.dubbo.rpc.proxy.javassist.MyselfJavassistProxyFactory
# dubbo.xml 配置如下:
 <dubbo:consumer timeout="8000" proxy="myselfJavassistProxyFactory"/>

利用Dubbo SPI取得实现类实例:在这里插入图片描述
另外,(服务提供方和服务消费方)Protocol层设置了调用过程拦截(Filter),Dubbo 本身的大多功能均基于此扩展点实现,每次远程方法执行,该拦截都会被执行,扩展时请注意对性能的影响。
在这里插入图片描述
可用SPI机制配置com.alibaba.dubbo.rpc.Filter实现类,并配置到框架Filter中去。
参见:
调用拦截扩展
Dubbo的Filter链梳理

这里有一个利用Filter在Dubbo集成hystrix的例子可以参考:
dubbo-hystrix-support

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章