看过dubbo源码?
1、服务调用过程
- 最外层是Mock逻辑,调用前,调用后进行Mock
- 从服务目录中,根据当前调用的方法和路由链,筛选出部分服务Invoker(DubboInvoker)
- 对服务Invoker进行负载均衡,选出一个服务Invoker
- 执行Filter链
- AsyncToSyncInvoker完成异步转同步,因为DubboInvoker的执行是异步非阻塞的,所以如果是同步调用,则会在此处阻塞,知道拿到响应结果
- DubboInvoker开始异步非阻塞的调用
- HeaderExchangeChannel中会阻塞timeout的时间来等待结果,该timeout就是用户在消费端所配置的timeout
2、限流算法
1、一般的限制每秒多少请求量 ,用信号量来做,相当于线程池
2、TPS ,Dubbo默认使用令牌桶算法实现限流。某段时间内,桶里面只能放进n个令牌,然后来一个请求就减少一个令牌,如果桶里面的令牌没有了,则不能继续执行请求。限流通过com.alibaba.dubbo.rpc.filter.TpsLimitFilter实现。
3、负载均衡算法
1、随机
a、根据权重加总计算出总权重10
b、随机一个10以内的数字
c、轮询所有的invokers,然后拿随机值offset-每一个invoker的权重
d、当结果小于0时,直接返回这个invoker即可
2、轮询(权重一样,就取余的方式获取到invoker,权重不同按照按公约后的权重设置轮循比率)
3、一致性hash(利用缓存的hash思想 每个privoder 有一个hash值存在一个圆环上,范围是0-2的32次方,然后key的hash)
4、最少活跃数(每个provider维护了一个active,调用+1 调用完成-1,轮询所有的invokers,取最小的active,如果active相同,就看权重,权重相同,就随机)
Dubbo动态代理:
1、javassist(默认)
2、jdk动态代理
JavassistProxyFactory 来创建引用服务的代理,JavassistProxyFactory 源码如下:
public class JavassistProxyFactory extends AbstractProxyFactory {
// 获取代理
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
return (T) Proxy.getProx
y(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
return new AbstractProxyInvoker<T>(proxy, type, url) {
@Override
protected Object doInvoke(T proxy, String methodName, Class<?>[] parameterTypes,
Object[] arguments) throws Throwable {
return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
}
};
}
}
JavassistProxyFactory的getProxy方法看似跟jdk生成动态代理一样, 但这里的Proxy类不是jdk的类,而是dubbo自写的Proxy类(com.alibaba.dubbo.common.bytecode.Proxy),该类可利用javassist工具对接口生成代理代码(dubbo是不能对非接口类进行代理的)
Cglib和jdk动态代理的区别?
1、Jdk动态代理:利用拦截器(必须实现InvocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理
2、 Cglib动态代理:利用ASM框架,对代理对象类生成的class文