前言
Dubbo 整体架构分为10层,从宏观上把握这10层架构,并了解各层的功能和扩展点,可以帮助我们更好的了解 Dubbo。
代理层—Proxy
Proxy 层的功能就是使用动态代理的方式为接口创建代理类,Proxy 层最主要的接口就是 ProxyFactory。其默认的扩展点有:stub、jdk、javassist。jdk 使用反射的方式创建代理类,javassist 通过拼接字符串然后编译的方式创建代理类。
- 对于服务提供者,代理的对象是接口的真实实现。
- 对于服务消费者,代理的对象是远程服务的 invoker 对象。
注册层—Registry
注册层主要负责的就是服务的注册发现。这层的主要接口就是 RegistryFactory,其接口方法有 @Adaptive 注解,会根据参数 protocol 来选择实现,默认的扩展实现有:
- zookeeper
- redis
- multicast(广播模式)
- 内存
集群层—Cluster
集群层主要是对多提供者调用场景的抽象,是 Dubbo 整个集群容错的抽象层。主要的扩展点有:容错(Cluster)、路由(RouterFactory)、负载均衡(LoadBalance)。这层的这些扩展点参考之前的博客。
容错
| 机制名 | 简介 |
|---|---|
| Failover 默认 | 失败重试。默认失败后在重试1次,重试其他服务器。通常使用在读/幂等写的场景。会对下游服务造成较大压力。 |
| Failfast | 快速失败。失败就返回异常。使用在非幂等写的场景。但受网络影响大。 |
| Failsafe | 失败不做处理,直接忽略异常。使用在不关心调用结果,且成功与否不重要的场景。 |
| Failback | 失败后放入队列,并定时重试。使用在要保持最终一致或异步处理的场景。 |
| Forking | 并行调用多个服务,只要一个成功就可以。使用在实时性要求高的场景,但会造成消费者资源浪费。 |
| Broadcast | 广播给所有提供者,有一个失败就失败。 |
| Mock | 出现异常就会使用默认的返回内容,使用在服务降级的场景。 |
| Available | 不用负载均衡,找到第一个可用提供者就调用。 |
| Mergeable | 把多个节点的返回结果合并。 |
路由
- 条件路由;
- 文件路由;
- 脚本路由。
负载均衡
- 权重随机负载均衡(默认);
- 权重轮询负载均衡;
- 一致性 hash 负载均衡;
- 最小活跃数负载均衡。
协议层—Protocol
协议层是 Dubbo RPC 的核心,在这一层发起服务暴露(protocol.export)和服务引用(protocol.refer)。
Dubbo 提供的协议有:
- Dubbo (默认);
- injvm;
- rmi;
- http;
- hessian;
- thrift。
信息交换层—Exchange
信息交换层的作用就是封装 Request/Response 对象。
传输层—Transport
数据传输就是在传输层发生的,所以这层包含 Transport(传输)、Dispatcher(分派)、Codec2(编解码)、ThreadPool(线程池),这几个接口。这也很好理解,数据传输发生在传输层,所以传输层一定需要具备数据传输的能力,也就是 Transport 和 Codec2,其中 Transport 就是 Netty 等网络传输的接口,编解码不必说了,传输肯定需要;除了传输能力,数据接收之后的处理,Dispatcher 和 ThreadPool,也就是分派任务和任务提交给线程池处理,也是必不可少的。
Transport
- Netty;
- Mina;
- Grizzly。
Dispatcher
| 策略 | 用途 |
|---|---|
| all | 所有消息都派发到线程池,包括请求,响应,连接事件,断开事件等,默认 |
| direct | 所有消息都不派发到线程池,全部在 IO 线程上直接执行 |
| message | 只有请求和响应消息派发到线程池,其它消息均在 IO 线程上执行 |
| execution | 只有请求消息派发到线程池,不含响应。其它消息均在 IO 线程上执行 |
| connection | 在 IO 线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池 |
ThreadPool
| 线程池类型 | 说明 |
|---|---|
| fixed | 固定大小线程池,默认线程数200,启动时建立,不会关闭,一直存在 |
| cached | 缓存线程池,空闲一分钟自动删除,需要时重建 |
| limited | 可伸缩线程池,但只会扩大不会缩小。这么做的目的是避免收缩的时候来大流量带来性能问题 |
| eager | 优先创建 worker 线程池。任务数大于 corePoolSize 小于 maxPoolSize,创建 worker 处理,线程数大于 maxPoolSize ,任务放入阻塞队列,阻塞队列满了走拒绝策略。 |
序列化层—Serialize
序列化的作用是把对象转化为二进制流,然后在网络中传输。Dubbo 提供的序列化方式有:
- Hessian2(默认);
- Fastjson;
- fst;
- Java;
- Kayo;
- protobuff。