Dubbo框架浅谈
Dubbo 是一款高性能、轻量级的开源 Java RPC(Remote Procedure Call,远程过程调用)框架。
一、Dubbo分层:
·业务层
·RPC层
·Remoting层
二、Dubbo调用工作流:
1.提供者读取配置将服务实例化,Proxy封装服务调用接口
2.Proxy封装时,调用Protocol定义协议格式,如:Dubbo Protocol
3.将Proxy封装成Invoker(真实服务调用的实例)
4.Invoker封装到Exporter
5.将Exporter注册到注册中心
6.消费者服务实例化,从注册中心订阅提供者元数据(IP、端口以及调用方式)
7.获取到Proxy,拿到Invoker实体,使用Invoker进行调用
8.在Invoker调用之前,通过Directory获取提供者的Invoker列表
9.通过路由规则知道服务需要从哪些节点获取
10.Invoker调用过程中,通过Cluster进行容错
11.调用过程中,通过LoadBalance来实现负载均衡
12.在调用之前还需要经过Filter过滤链,用来处理上下文,限流和计数的工作
13.生成过滤后的Invoker
14.用Client进行数据传输
15.Codec会根据Protocol定义的协议,进行协议构造
16.构造完成的数据,通过序列化Serialization传输给服务提供者
17.Request到达提供者,被分配到线程池中进行处理
18.Server拿到请求后查找对应的Exporter
19.Exporter通过Filter的层层解析获得Invoker
20最后对服务提供者实体进行调用
上述步骤中出现的Proxy、Invoker、Exporter、Filter时调用实体在不同阶段的不同表现形式,本质是一样的。
三、服务暴露实现原理
- 服务提供者初始化,注册到注册中心,暴露给其他服务调用。提供者暴露服务整体机制:
- 服务消费者初始化,注册到注册中心,消费其他服务。消费者消费服务整体机制:
四、集群容错
1.生成Invoker对象。根据Cluster实现不同,生成不同类型的ClusterInvoker对象,并通过Invoker方法启动调用流程。
2.获取可调用的服务列表,通过Directory的List方法获取,有两类服务列表的获取方式:
·RegistryDirectory:动态Directory实现,自动从注册中心更新Invoker列表,配置信息,路由列表。
·StaticDirectory:静态列表实现,将传入的Invoker列表封装成静态的Directory对象。
3.Directory获取所有的Invoker列表后,会调用路由接口(Router),根据用户配置的不同策略对Invoker列表进行过滤,返回符合规则的Invoker。
4.前面三步生成的Invoker需要调用最终服务,但服务分布在不同节点上,所以需要经过LoadBalance,负载均衡策略有四种:
·Random LoadBalance 随机,按照权重设置随机概率做负载均衡。
·RoundRobin LoadBalance 轮询,按照公约后的权重设置轮询比例。
·LeastActive LoadBalance 按照活跃数调用,活跃差的被调用次数多,活跃度相同的进行随机调用。
·ConsistentHash LoadBalance 一致性Hash,相同参数的请求总是发到同一个提供者
5.最后进行RPC调用,如果出现异常,提供9种不同的容错策略:
Failover、Failfast、Failsafe、Failback、Forking、Broadcast、Mock、Available、Mergable
五、远程调用
- 服务消费者经过容错,Invoker列表,路由和负载均衡后,会对Invoker进行过滤,之后通过Client编码,序列化发送给服务提供者。
- 服务消费者调用提供者的前后,都会调用Filter。
- Dubbo系统有自带的系统过滤器,提供者有11个,消费者有5个,用户可以自定义过滤器。
- 调用请求经过过滤以后,会以Invoker的形式对Client进行调用。Client会交由底层I/O线程池处理,其包括处理消息读写、序列化、反序列化等逻辑,同时会对Dubbo协议进行编码和解码操作。
- Dubbo协议基于TCP/IP协议,包括协议头和协议体。协议体包含传输的主要内容,由16字节长的报文组成,每个字节包含8个二进制位。 具体内容如下:
- 消费者在调用之前会将上述消息体,根据Dubbo协议打包好,框架内部会调用DefaultFuture对象的get方法进行等待,在准备发送请求时,才创建Request对象,这个对象会保存在一个静态的HashMap中,当提供者处理完Request后,将返回的Response放回到Futures的HashMap中,在HashMap中会找到对应的Request对象,并且返回给服务消费者。
- 协议打包好之后就需要给协议编码和序列化,用到Dubbo的编码器,过程是将信息转化成字节流。Dubbo协议编码请求对象分为使用ExchangeCodec中的两个方法,encodeRequest负责编码协议头和encodeRequestData编码协议体,同样通过encodeResponse 编码协议头,encodeResponseData 编码协议体。
- 消费者和提供者都通过decode和decodeBody两个方法进行解码,不同的是解码有可能在IO线程或者Dubbo线程池中完成。当服务提供者收到请求协议包以后,先将其放到 ThreadPool 中,然后依次处理。
- 由于服务提供者在注册中心是通过 Exporter 的方式暴露服务的,服务消费者也是通过 Exporter 作为接口进行调用的。Exporter 是将 Invoker 进行了包装,将拆开的 Invoker 进行 Filter 过滤链条进行过滤以后,再去调用服务实体。最后,将信息返回给服务消费者。