Dubbo中invoker是provider和consumer实现RPC调用的关键,invoker的构建过程是Dubbo服务的init初始化过程。invoker#invoke的调用是Dubbo服务的call调用过程。因此,这里分析invoker模型,主要是provider和consumer端的初始化过程。
dubbo中常用的Invoker类,如下:
- AbstractProxyInvoker:本地执行类的Invoker,实际通过Java反射的方式执行原始对象的方法。一般通过接口ProxyFactory的扩展类StubProxyFactoryWrapper、JavassistProxyFactory先后执行完成目标接口的代理。
- AbstractInvoker:远程通信类的Invoker,实际通过通信协议发起远程调用请求,并接收响应。
- AbstractClusterInvoker:多个远程通信类的Invoker聚合成的集群Invoker,加入了集群容错和负载均衡策略。cluster集群下的Invoker实现,采用模板方法设计模式,abstract定义方法框架,具体方法实现由子类实现。
Invoker是Dubbo中实体类,rpc的server端服务提供和client端服务调用,都要由invoker实现。因此,其作为一个可执行体,在server端,用于调用provider的本地服务调用;在client端,其内包含远程通信的NettyClient,用于远程调用。provider端和consumer端,在Config配置类中,分别持有ProxyFactory和Protocol实例。
1.ProxyFactory
该接口的作用:利用目标接口以及目标接口的实现类生成Invoker【服务提供端Invoker】;利用Invoker生成其代理对象。
@SPI(value = "javassist", scope = FRAMEWORK)
public interface ProxyFactory {
@Adaptive({PROXY_KEY})
<T> T getProxy(Invoker<T> invoker) throws RpcException;
@Adaptive({PROXY_KEY})
<T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException;
/**
* create invoker.
* @param <T>
* @param proxy 目标接口的具体实现类之ChinaServiceImpl
* @param type 目标接口之CountryService
* @param url
* @return invoker
*/
@Adaptive({PROXY_KEY})
<T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;
}
当前接口涉及扩展类如下所示:
stub=org.apache.dubbo.rpc.proxy.wrapper.StubProxyFactoryWrapper
jdk=org.apache.dubbo.rpc.proxy.jdk.JdkProxyFactory
javassist=org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory
nativestub=org.apache.dubbo.rpc.stub.StubProxyFactory
其中,StubProxyFactory适用于生成非反射方式的invoker、proxy,主要依赖于Dubbo3 Triple协议。正常调用方向:StubProxyFactoryWrapper -> JavassistProxyFactory。
2.Protocol
@SPI(value = "dubbo", scope = ExtensionScope.FRAMEWORK)
public interface Protocol {
/**
* 提供端导出服务方便消费端远程调用:
* 1. 服务提供端接收到远程访问后需要记录消费端IP地址等信息:RpcContext.getServerAttachment().setRemoteAddress()。
* 2. 服务导出功能必须是idempotent幂等的,there's no difference between invoking once and invoking twice when export the same URL。
* 3. Invoker instance is passed in by the framework, protocol needs not to care。
*
* @param <T> Service type
* @param invoker Service invoker
* @return exporter reference for exported service, useful for unexport the service later
* @throws RpcException thrown when error occurs during export the service, for example: port is occupied
*/
@Adaptive
<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
/**
* 消费端引用远程服务:
* 1. 消费端通过Invoker#invoke调用refer指定的远程服务时,the protocol needs to correspondingly execute `invoke()` method of `Invoker` object。
* 2. It's protocol's responsibility to implement `Invoker` which's returned from `refer()`. Generally speaking,
* protocol sends remote request in the `Invoker` implementation. <br>
* 3. When there's check=false set in URL, the implementation must not throw exception but try to recover when connection fails.
* @param <T> Service type
* @param type Service class
* @param url URL address for the remote service
* @return invoker service's local proxy
* @throws RpcException when there's any error while connecting to the service provider
*/
@Adaptive
<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
}
当前接口涉及扩展类如下所示:
filter=org.apache.dubbo.rpc.cluster.filter.ProtocolFilterWrapper
listener=org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper
mock=org.apache.dubbo.rpc.support.MockProtocol
serializationwrapper=org.apache.dubbo.rpc.protocol.ProtocolSerializationWrapper
dubbo=org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol
injvm=org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol
rest=org.apache.dubbo.rpc.protocol.rest.RestProtocol
grpc=org.apache.dubbo.rpc.protocol.grpc.GrpcProtocol
tri=org.apache.dubbo.rpc.protocol.tri.TripleProtocol
registry=org.apache.dubbo.registry.integration.InterfaceCompatibleRegistryProtocol
service-discovery-registry=org.apache.dubbo.registry.integration.RegistryProtocol
qos=org.apache.dubbo.qos.protocol.QosProtocolWrapper
ProtocolSerializationWrapper->ProtocolFilterWrapper->ProtocolListenerWrapper->QosProtocolWrapper->RegistryProtocol
3.消费端Invoker
Consumer端之Invoker用于执行远程调用(所以consumer端invoker带有通信能力,内部传入NettyClient)。
public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
private T createProxy(Map<String, String> referenceParameters) {
...
createInvokerForRemote();
...
return (T) proxyFactory.getProxy(invoker, ProtocolUtils.isGeneric(generic));
}
}
- 制造一个远程reference,创造一个远程reference Invoker。
- 基于 Invoker 生成目标接口的代理。
3.1. reference & reference Invoker
由RegistryProtocol生成最初Invoker之MigrationInvoker,并通过RegistryProtocolListener控制Invoker的状态和行为。直观点其实就是属性invoker、serviceDiscoveryInvoker的赋值操作。
public class MigrationInvoker<T> implements MigrationClusterInvoker<T> {
private URL url;
private URL consumerUrl;
private Cluster cluster;
private Registry registry;
private Class<T> type;
private RegistryProtocol registryProtocol;
private MigrationRuleListener migrationRuleListener;
private volatile ClusterInvoker<T> invoker;
private volatile ClusterInvoker<T> serviceDiscoveryInvoker;
private volatile ClusterInvoker<T> currentAvailableInvoker;
}
此时MigrationInvoker内部相关属性如下所示:
RegistryProtocolListener内部通过MigrationRuleHandler基于MigrationRule规则Migrate改变Invoker的状态和行为。
public class MigrationRuleHandler<T> {
// MigrationInvoker
private MigrationClusterInvoker<T> migrationInvoker;
private URL consumerURL;
public MigrationRuleHandler(MigrationClusterInvoker<T> invoker, URL url) {
this.migrationInvoker = invoker;
this.consumerURL = url;
}
public synchronized void doMigrate(MigrationRule rule) {
....
if (refreshInvoker(step, threshold, rule)) {
setMigrationRule(rule);
}
}
private boolean refreshInvoker(MigrationStep step, Float threshold, MigrationRule newRule) {
MigrationStep originStep = currentStep;
if ((currentStep == null || currentStep != step) || !currentThreshold.equals(threshold)) {
boolean success = true;
switch (step) {
case APPLICATION_FIRST://默认执行策略
migrationInvoker.migrateToApplicationFirstInvoker(newRule);
break;
case FORCE_APPLICATION:
success = migrationInvoker.migrateToForceApplicationInvoker(newRule);
break;
case FORCE_INTERFACE:
default:
success = migrationInvoker.migrateToForceInterfaceInvoker(newRule);
}
...
return success;
}
return true;
}
}
public class MigrationInvoker<T> implements MigrationClusterInvoker<T> {
private RegistryProtocol registryProtocol;
private volatile ClusterInvoker<T> invoker;
private volatile ClusterInvoker<T> serviceDiscoveryInvoker;
public void migrateToApplicationFirstInvoker(MigrationRule newRule) {
CountDownLatch latch = new CountDownLatch(0);
//初始化参数invoker
refreshInterfaceInvoker(latch);
//初始化参数serviceDiscoveryInvoker
efreshServiceDiscoveryInvoker(latch);
calcPreferredInvoker(newRule);
}
protected void refreshServiceDiscoveryInvoker(CountDownLatch latch) {
serviceDiscoveryInvoker = registryProtocol.getServiceDiscoveryInvoker(cluster, registry, type, url);
}
protected void refreshInterfaceInvoker(CountDownLatch latch) {
invoker = registryProtocol.getInvoker(cluster, registry, type, url);
}
}
截止当前才真正开始初始化MigrationInvoker内部相关属性invoker、serviceDiscoveryInvoker。
3.2.MigrationInvoker之属性invoker
public class RegistryProtocol implements Protocol{
protected <T> ClusterInvoker<T> doCreateInvoker(DynamicDirectory<T> directory, Cluster cluster, Registry registry, Class<T> type) {
...
//directory类型:RegistryDirectory
if (directory.isShouldRegister()) {
// 1.通过zkClient注册当前消费端服务
directory.setRegisteredConsumerUrl(urlToRegistry);
registry.register(directory.getRegisteredConsumerUrl());
}
directory.buildRouterChain(urlToRegistry);
//2.当前消费端监听的节点
directory.subscribe(toSubscribeUrl(urlToRegistry));
//3.利用MockClusterWrapper创建Invoker
return (ClusterInvoker<T>) cluster.join(directory, true);
}
}
zk注册当前消费端服务:创建如下节点
/dubbo/common.service.CountryService/consumers/consumer%3A%2F%2F192.168.80.36%2Fcommon.service.CountryService%3Fapplication%3Ddubbo-consumer%26background%3Dfalse%26category%3Dconsumers%26check%3Dfalse%26dubbo%3D2.0.2%26interface%3Dcommon.service.CountryService%26lazy%3Dtrue%26methods%3DgetCountry%26pid%3D65342%26qos.enable%3Dfalse%26register-mode%3Dinstance%26release%3D3.0.7%26revision%3D2.0%26side%3Dconsumer%26sticky%3Dfalse%26timestamp%3D1712909849973%26version%3D2.0
在zk端创建以下节点,并添加相关zk监听器 :
/dubbo/common.service.CountryService/providers
/dubbo/common.service.CountryService/configurators
/dubbo/common.service.CountryService/routers
最终返回的Invoker:MockClusterInvoker -> AbstractCluster静态内部类AbstractClusterInvoker。当前在内部类AbstractClusterInvoker构造方法内部会初始化过滤器filter类型的ClusterInvoker。
3.2.MigrationInvoker之属性serviceDiscoveryInvoker
public class RegistryProtocol implements Protocol{
protected <T> ClusterInvoker<T> doCreateInvoker(DynamicDirectory<T> directory, Cluster cluster, Registry registry, Class<T> type) {
...
// directory:ServiceDiscoveryRegistryDirectory
if (directory.isShouldRegister()) {
// 1.zkClient注册当前消费端服务已经完成,此处不会重复执行
directory.setRegisteredConsumerUrl(urlToRegistry);
registry.register(directory.getRegisteredConsumerUrl());
}
directory.buildRouterChain(urlToRegistry);
//2.获取服务提供端对应的IP信息,提供消费端远程调用提供端接口
directory.subscribe(toSubscribeUrl(urlToRegistry));
//3.利用MockClusterWrapper创建Invoker
return (ClusterInvoker<T>) cluster.join(directory, true);
}
}
获取服务提供端地址信息后还涉及具有远程通信功能的DubboInvoker初始化。
public class ServiceDiscoveryRegistry{
protected void subscribeURLs(URL url, NotifyListener listener, Set<String> serviceNames) {
serviceNames = toTreeSet(serviceNames);
String serviceNamesKey = toStringKeys(serviceNames);
String protocolServiceKey = url.getProtocolServiceKey();
Lock appSubscriptionLock = getAppSubscription(serviceNamesKey);
appSubscriptionLock.lock();
ServiceInstancesChangedListener serviceInstancesChangedListener = serviceListeners.get(serviceNamesKey);
if (serviceInstancesChangedListener == null) {
serviceInstancesChangedListener = serviceDiscovery.createListener(serviceNames);
serviceInstancesChangedListener.setUrl(url);
for (String serviceName : serviceNames) {
// 获取到 服务提供端服务 所有地址列表
List<ServiceInstance> serviceInstances = serviceDiscovery.getInstances(serviceName);
if (CollectionUtils.isNotEmpty(serviceInstances)) {
serviceInstancesChangedListener.onEvent(new ServiceInstancesChangedEvent(serviceName, serviceInstances));
}
}
serviceListeners.put(serviceNamesKey, serviceInstancesChangedListener);
}
if (!serviceInstancesChangedListener.isDestroyed()) {
serviceInstancesChangedListener.setUrl(url);
listener.addServiceListener(serviceInstancesChangedListener);
// 基于提供端服务列表生成与之对应的DubboInvoker
serviceInstancesChangedListener.addListenerAndNotify(protocolServiceKey, listener);
serviceDiscovery.addServiceInstancesChangedListener(serviceInstancesChangedListener);
} else {
logger.info(String.format("Listener of %s has been destroyed by another thread.", serviceNamesKey));
serviceListeners.remove(serviceNamesKey);
}
}
}
返回的serviceDiscoveryInvoker属性:MockClusterInvoker -> AbstractCluster静态内部类AbstractClusterInvoker。此时AbstractClusterInvoker内部由ServiceDiscoveryRegistryDirectory加载的过滤器filter类型的ClusterInvoker区别于MigrationInvoker属性invoker。