什么是Dubbo
Dubbo是一个分布式的服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是SOA服务化治理方案的核心框架。
RPC(Remote Procedure Call Protocol):远程过程调用:
两台服务器A、B,分别部署不同的应用a,b。当A服务器想要调用B服务器上应用b提供的函数或方法的时候,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义传达调用的数据:
RPC是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。
RPC需要解决的问题:
通讯问题 :
主要是通过在客户端和服务器之间建立TCP连接,远程过程调用的所有交换的数据都在这个连接里传输。连接可以是按需连接,调用结束后就断掉,也可以是长连接,多个远程过程调用共享同一个连接。
寻址问题 :
A服务器上的应用怎么告诉底层的RPC框架,如何连接到B服务器(如主机或IP地址)以及特定的端口,方法的名称名称是什么,这样才能完成调用。比如基于Web服务协议栈的RPC,就要提供一个endpointURI,或者是从UDDI服务上查找。如果是RMI调用的话,还需要一个RMI Registry来注册服务的地址。
序列化 与 反序列化 :
当A服务器上的应用发起远程过程调用时,方法的参数需要通过底层的网络协议如TCP传递到B服务器,由于网络协议是基于二进制的,内存中的参数的值要序列化成二进制的形式,也就是序列化(Serialize)或编组(marshal),通过寻址和传输将序列化的二进制发送给B服务器。 同理,B服务器接收参数要将参数反序列化。B服务器应用调用自己的方法处理后返回的结果也要序列化给A服务器,A服务器接收也要经过反序列化的过程。
Dubbo优缺点
优点:
- 透明化的远程方法调用
像调用本地方法一样调用远程方法;只需简单配置,没有任何API侵入。- 软负载均衡及容错机制
可在内网替代nginx lvs等硬件负载均衡器。- 服务注册中心自动注册 & 配置管理
不需要写死服务提供者地址,注册中心基于接口名自动查询提供者ip。 使用类似zookeeper等分布式协调服务作为服务注册中心,可以将绝大部分项目配置移入zookeeper集群。- 服务接口监控与治理
Dubbo-admin与Dubbo-monitor提供了完善的服务接口管理与监控功能,针对不同应用的不同接口,可以进行 多版本,多协议,多注册中心管理。
缺点:
只支持java语言
Dubbo原理
- client一个线程调用远程接口,生成一个唯一的ID(比如一段随机字符串,UUID等),Dubbo是使用AtomicLong从0开始累计数字的。
- 将打包的方法调用信息(如调用的接口名称,方法名称,参数值列表等),和处理结果的回调对象callback,全部封装在一起,组成一个对象object。
- 向专门存放调用信息的全局ConcurrentHashMap里面put(ID, object)。
- 将ID和打包的方法调用信息封装成一对象connRequest,使用IoSession.write(connRequest)异步发送出去。
- 当前线程再使用callback的get()方法试图获取远程返回的结果,在get()内部,则使用synchronized获取回调对象callback的锁,
再先检测是否已经获取到结果,如果没有,然后调用callback的wait()方法,释放callback上的锁,让当前线程处于等待状态。- 服务端接收到请求并处理后,将结果(此结果中包含了前面的ID,即回传)发送给客户端,客户端socket连接上专门监听消息的线程收到消息,分析结果,取到ID,再从前面的ConcurrentHashMap里面get(ID),从而找到callback,将方法调用结果设置到callback对象里。
- 监听线程接着使用synchronized获取回调对象callback的锁(因为前面调用过wait(),那个线程已释放callback的锁了),再notifyAll(),唤醒前面处于等待状态的线程继续执行(callback的get()方法继续执行就能拿到调用结果了),至此,整个过程结束。
Dubbo负载均衡策略
Dubbo提供了4种均衡策略,如:
Random LoadBalance(随机均衡算法)、
RoundRobin LoadBalance(权重轮循均衡算法)、
LeastAction LoadBalance(最少活跃调用数均衡算法)、
ConsistentHash LoadBalance(一致性Hash均衡算法)。缺省时为Random随机调用
Dubbo机制
dubbo启动时默认有重试机制和超时机制。
超时机制的规则是如果在一定的时间内,provider没有返回,则认为本次调用失败,
重试机制在出现调用失败时,会再次调用。如果在配置的调用次数内都失败,则认为此次请求异常,抛出异常。
如果出现超时,通常是业务处理太慢,可在服务提供方执行:jstack PID > jstack.log,分析线程都卡在哪个方法调用上,这里就是慢的原因。 如果不能调优性能,请将timeout设大。
某些业务场景下,如果不注意配置超时和重试,可能会引起一些异常。
超时设置
DUBBO消费端设置超时时间需要根据业务实际情况来设定,
如果设置的时间太短,一些复杂业务需要很长时间完成,导致在设定的超时时间内无法完成正常的业务处理。
这样消费端达到超时时间,那么dubbo会进行重试机制,不合理的重试在一些特殊的业务场景下可能会引发很多问题,需要合理设置接口超时时间。
比如发送邮件,可能就会发出多份重复邮件,执行注册请求时,就会插入多条重复的注册数据。
重连机制
dubbo在调用服务不成功时,默认会重试2次。 Dubbo的路由机制,会把超时的请求路由到其他机器上,而不是本机尝试,所以dubbo的重试机器也能一定程度的保证服务的质量。
但是如果不合理的配置重试次数,当失败时会进行重试多次,这样在某个时间点出现性能问题,调用方再连续重复调用, 系统请求变为正常值的retries倍,系统压力会大增,容易引起服务雪崩,需要根据业务情况规划好如何进行异常处理,何时进行重试。
Dubbo容错机制
1.默认失败自动去重试其他服务器,默认重试2次
2.只发起一次调用,失败就是失败
3.失败安全,忽略异常
4.请求失败后,设置一个定时任务,多少秒后再次进行请求(可能到时该服务器处理的业务就比较少了)
5.请求同时发送给多个服务器,只要有一个成功就返回
6.广播调用所有提供者,逐个调用,任意一台报错则报错