Dubbo依赖关系
由dubbo可以看到一个基本的RPC框架设计和依赖。
- Provider向注册中心注册服务(pub)
- Consumer订阅注册中心消息(sub)
- Provider向注册中心注册服务时会被注册中心推送至Consumer
- Consumer通过注册中心获取到服务的注册信息,比如调用地址等。Consumer通过调用地址列表做负载均衡(客户端负载均衡),然后调用Provider。数据之间需要序列化后通过网络传输
- 监控
注册中心(服务注册与发现)
序列化协议
协议 | 优点 | 缺点 | 数据格式 | 可读性 |
---|---|---|---|---|
Kyro | ||||
Avro | ||||
Xstream | ||||
Hessian | ||||
Jackson | ||||
JDK |
网络传输
框架 | JDK底层 | 传输协议 | 连接方式 | 优点 | 缺点 |
---|---|---|---|---|---|
Netty | NIO | ||||
Mina | NIO | ||||
Grizzly | NIO | ||||
Twisted | |||||
REST类 |
负载均衡
服务端负载均衡(nginx/zuul)
由网关统一管理应用请求的分发,好处是服务请求入口统一管理,方便做限流、权限控制等;缺点是所有负载均衡的分发压力(CPU和IO)全部归于网关。
客户端负载均衡(dubbo loadbalance/ribbon)
有客户端从配置中心获取服务实例列表,然后客户端根据服务列表做负载均衡的处理。好处是负载均衡的分发压力分摊给客户端,缺点是不方便做请求的统一管理。
负载均衡策略
一般来说,负载均衡的算法有3大类:轮询、哈希以及随机。
监控
Dubbo支持协议(序列化以及网络传输)
dubbo将对象序列化,包括header(codec)(序列化编码方式,可选)和body(serialization)(对象序列化后的内容,二进制或者字符串)。
Client通过网络传输,将序列化内容发送给服务端。
协议 | 访问地址 |
---|---|
dubbo协议 | dubbo协议 |
rmi协议 | rmi协议 |
hessian协议 | hessian协议 |
http协议 | http协议 |
webservice协议 | webservice协议 |
thrift协议 | thrift协议 |
memcached协议 | memcached协议 |
redis协议 | redis协议 |
Dubbo服务集群容错
Failover 失败转移
失败转移,当出现失败,重试其它服务器,通常用于读操作,但重试会带来更长延迟。
以下是源码,只保留关键部分。com.alibaba.dubbo.rpc.cluster.support.FailoverClusterInvoker
Failfast 快速失败
快速失败,只发起一次调用,失败立即报错,通常用于非幂等性的写操作。
以下是源码,只保留关键部分。com.alibaba.dubbo.rpc.cluster.support.FailfastClusterInvoker
Failsafe 失败安全
失败安全,出现异常时,直接忽略,通常用于写入审计日志等操作。
以下是源码,只保留关键部分。com.alibaba.dubbo.rpc.cluster.support.FailfastClusterInvoker
Failback 失败自动恢复
失败自动恢复,后台记录失败请求,定时重发,通常用于消息通知操作。
以下是源码,只保留关键部分。com.alibaba.dubbo.rpc.cluster.support.FailbackClusterInvoker
Forking 并行调用
并行调用,只要一个成功即返回,全部异常则返回最后一个异常。通常用于实时性要求较高的操作,但需要浪费更多服务资源。
以下是源码,只保留关键部分。com.alibaba.dubbo.rpc.cluster.support.ForkingClusterInvoker
Broadcast 广播调用
轮询所有提供者实例,只返回最后一个提供者实例的结果。任意一个实例抛出异常则整个RPC过程异常。
通常用于通知所有提供者更新缓存或日志等本地资源信息。
以下是源码,只保留关键部分。com.alibaba.dubbo.rpc.cluster.support.BroadcastClusterInvoker
Mergeable 合并调用
调用多个实例,并调用合并器Merger合并所有的返回结果
这个代码比较长,略。com.alibaba.dubbo.rpc.cluster.support.MergeableClusterInvoker
Dubbo负载均衡算法
Random LoadBalance(随机均衡算法)
com.alibaba.dubbo.rpc.cluster.loadbalance.RandomLoadBalance
根据权重进行实例的随机选择,即每个实例的随机选中的概率是根据权重的决定的。
RoundRobin LoadBalance(权重轮循均衡算法)
com.alibaba.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance
LeastAction LoadBalance(最少活跃调用数均衡算法)
com.alibaba.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance
如果一个实例被调用的次数较少,则会优先调用该实例。
ConsistentHash LoadBalance(一致性Hash均衡算法)
com.alibaba.dubbo.rpc.cluster.loadbalance.ConsistentHashLoadBalance
根据一致性哈希算法,
一致性哈希选择器依赖的参数是:
- virtualInvokers:每个哈希槽对应的Invoker
- replicaNumber:理解为哈希槽的数量,由hash.nodes指定,默认值是160
- identityHashCode:哈希码,根据invokers生成
- argumentIndex:参数索引数组,int[]类型。由hash.arguments指定,默认值是0。会根据该参数来确定选择那些输入参数作为key生成的依据。然后MD5之后做Hash。
综上,可以认为,同一个方法的调用中,如果参数的哈希值相同则会调用同一个实例。
源码解析12345678910protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();int identityHashCode = System.identityHashCode(invokers);ConsistentHashSelector<T> selector = (ConsistentHashSelector<T>) selectors.get(key);if (selector == null || selector.getIdentityHashCode() != identityHashCode) {selectors.put(key, new ConsistentHashSelector<T>(invokers, invocation.getMethodName(), identityHashCode));selector = (ConsistentHashSelector<T>) selectors.get(key); //ConsistentHashSelector 一致性哈希选择器}return selector.select(invocation);}