接上一篇 dubbo-server 之后,再来看一下 dubbo-client 是如何工作的。
dubbo提供者服务示例, 其结构是这样的!
dubbo://192.168.11.6:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.0.2&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=12720&side=provider×tamp=1534902103892
dubbo消费者示例,其结构是这样的!
dubbo://192.168.11.6:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-consumer&check=false&dubbo=2.0.2&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=17400&qos.port=33333®ister.ip=192.168.11.6&remote.timestamp=1537448440181&side=consumer×tamp=1537871015998
官网可以运行起来的实例:
1// 提供者: 2public class Provider { 3 public static void main(String[] args) throws Exception { 4 //Prevent to get IPV6 address,this way only work in debug mode 5 //But you can pass use -Djava.net.preferIPv4Stack=true,then it work well whether in debug mode or not 6 System.setProperty("java.net.preferIPv4Stack", "true"); 7 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"}); 8 context.start(); 9 10 // 这个比较巧妙, 只需停留在当前点,不按下enter键,服务就会一直存在,等待消费者连接,而且无需真正提供一个监听服务 11 System.in.read(); // press any key to exit 12 } 13 14} 15 16// 消费者: 17public class Consumer { 18 public static void main(String[] args) { 19 //Prevent to get IPV6 address,this way only work in debug mode 20 //But you can pass use -Djava.net.preferIPv4Stack=true,then it work well whether in debug mode or not 21 System.setProperty("java.net.preferIPv4Stack", "true"); 22 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"}); 23 context.start(); 24 DemoService demoService = (DemoService) context.getBean("demoService"); // get remote service proxy 25 String hello = demoService.sayHello("world"); // call remote method, 调用远程服务和本地服务一样,这是其优势所在 26 System.out.println(hello); // get result 27 } 28 } 29}
以上代码可以直接运行起来,但是建议还是个搭建一个Zookeeper来用用,因为线上基本都是Zk的,搭建也很简单,可参考:ZooKeeper 搭建笔记
初始化Context,如上一篇server过程! Rpc框架dubbo-server(v2.6.3) 源码阅读(一)
1// DubboNamespaceHandler, provider与consumer主要的差别在于xml标签的获取不一致, 2public class DubboNamespaceHandler extends NamespaceHandlerSupport { 3 4 static { 5 Version.checkDuplicate(DubboNamespaceHandler.class); 6 } 7 8 @Override 9 public void init() { 10 registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true)); 11 registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true)); 12 registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true)); 13 registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true)); 14 // provider解析 15 registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true)); 16 // consumer解析 17 registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true)); 18 registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true)); 19 registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true)); 20 registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false)); 21 registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser()); 22 } 23 24}
// 主要看获取bean的过程
DemoService demoService = (DemoService) context.getBean("demoService"); // get remote service proxy

1// spring, 获取bean, 通过 org.springframework.beans.factory.support.DefaultListableBeanFactory, 获取 2 @Override 3 public Object getBean(String name) throws BeansException { 4 assertBeanFactoryActive(); 5 return getBeanFactory().getBean(name); 6 } 7 8 protected <T> T doGetBean( 9 final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) 10 throws BeansException { 11 12 final String beanName = transformedBeanName(name); 13 Object bean; 14 15 // Eagerly check singleton cache for manually registered singletons. 16 // 通过该方法获取bean代理实例,com.alibaba.dubbo.config.spring.ReferenceBean 17 Object sharedInstance = getSingleton(beanName); 18 if (sharedInstance != null && args == null) { 19 if (logger.isDebugEnabled()) { 20 if (isSingletonCurrentlyInCreation(beanName)) { 21 logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + 22 "' that is not fully initialized yet - a consequence of a circular reference"); 23 } 24 else { 25 logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); 26 } 27 } 28 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); 29 } 30 31 else { 32 // Fail if we're already creating this bean instance: 33 // We're assumably within a circular reference. 34 if (isPrototypeCurrentlyInCreation(beanName)) { 35 throw new BeanCurrentlyInCreationException(beanName); 36 } 37 38 // Check if bean definition exists in this factory. 39 BeanFactory parentBeanFactory = getParentBeanFactory(); 40 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 41 // Not found -> check parent. 42 String nameToLookup = originalBeanName(name); 43 if (args != null) { 44 // Delegation to parent with explicit args. 45 return (T) parentBeanFactory.getBean(nameToLookup, args); 46 } 47 else { 48 // No args -> delegate to standard getBean method. 49 return parentBeanFactory.getBean(nameToLookup, requiredType); 50 } 51 } 52 53 if (!typeCheckOnly) { 54 markBeanAsCreated(beanName); 55 } 56 57 try { 58 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 59 checkMergedBeanDefinition(mbd, beanName, args); 60 61 // Guarantee initialization of beans that the current bean depends on. 62 String[] dependsOn = mbd.getDependsOn(); 63 if (dependsOn != null) { 64 for (String dep : dependsOn) { 65 if (isDependent(beanName, dep)) { 66 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 67 "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); 68 } 69 registerDependentBean(dep, beanName); 70 try { 71 getBean(dep); 72 } 73 catch (NoSuchBeanDefinitionException ex) { 74 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 75 "'" + beanName + "' depends on missing bean '" + dep + "'", ex); 76 } 77 } 78 } 79 80 // Create bean instance. 81 if (mbd.isSingleton()) { 82 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { 83 @Override 84 public Object getObject() throws BeansException { 85 try { 86 return createBean(beanName, mbd, args); 87 } 88 catch (BeansException ex) { 89 // Explicitly remove instance from singleton cache: It might have been put there 90 // eagerly by the creation process, to allow for circular reference resolution. 91 // Also remove any beans that received a temporary reference to the bean. 92 destroySingleton(beanName); 93 throw ex; 94 } 95 } 96 }); 97 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 98 } 99 100 else if (mbd.isPrototype()) { 101 // It's a prototype -> create a new instance. 102 Object prototypeInstance = null; 103 try { 104 beforePrototypeCreation(beanName); 105 prototypeInstance = createBean(beanName, mbd, args); 106 } 107 finally { 108 afterPrototypeCreation(beanName); 109 } 110 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); 111 } 112 113 else { 114 String scopeName = mbd.getScope(); 115 final Scope scope = this.scopes.get(scopeName); 116 if (scope == null) { 117 throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); 118 } 119 try { 120 Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { 121 @Override 122 public Object getObject() throws BeansException { 123 beforePrototypeCreation(beanName); 124 try { 125 return createBean(beanName, mbd, args); 126 } 127 finally { 128 afterPrototypeCreation(beanName); 129 } 130 } 131 }); 132 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); 133 } 134 catch (IllegalStateException ex) { 135 throw new BeanCreationException(beanName, 136 "Scope '" + scopeName + "' is not active for the current thread; consider " + 137 "defining a scoped proxy for this bean if you intend to refer to it from a singleton", 138 ex); 139 } 140 } 141 } 142 catch (BeansException ex) { 143 cleanupAfterBeanCreationFailure(beanName); 144 throw ex; 145 } 146 } 147 148 // Check if required type matches the type of the actual bean instance. 149 if (requiredType != null && bean != null && !requiredType.isInstance(bean)) { 150 try { 151 return getTypeConverter().convertIfNecessary(bean, requiredType); 152 } 153 catch (TypeMismatchException ex) { 154 if (logger.isDebugEnabled()) { 155 logger.debug("Failed to convert bean '" + name + "' to required type '" + 156 ClassUtils.getQualifiedName(requiredType) + "'", ex); 157 } 158 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); 159 } 160 } 161 return (T) bean; 162 }
View Code
// ApplicationConfig 初始化时,调用dubbo实例进行初始化
1// org.springframework.beans.BeanUtils.instantiateClass 初始化 ReferenceConfig 类,通过反射调用 2 // public com.alibaba.dubbo.config.RegistryConfig() 3 public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException { 4 Assert.notNull(ctor, "Constructor must not be null"); 5 try { 6 ReflectionUtils.makeAccessible(ctor); 7 // 生成新的实例 8 return ctor.newInstance(args); 9 } 10 catch (InstantiationException ex) { 11 throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex); 12 } 13 catch (IllegalAccessException ex) { 14 throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex); 15 } 16 catch (IllegalArgumentException ex) { 17 throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex); 18 } 19 catch (InvocationTargetException ex) { 20 throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException()); 21 } 22 }
// 通过getBean, 转移到 ReferenceBean.getObject() 触发代理初始化

1// org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean, 触发 创建bean操作,触发 getObject() 进行初始化 2 protected <T> T doGetBean( 3 final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) 4 throws BeansException { 5 6 final String beanName = transformedBeanName(name); 7 Object bean; 8 9 // Eagerly check singleton cache for manually registered singletons. 10 Object sharedInstance = getSingleton(beanName); 11 if (sharedInstance != null && args == null) { 12 if (logger.isDebugEnabled()) { 13 if (isSingletonCurrentlyInCreation(beanName)) { 14 logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + 15 "' that is not fully initialized yet - a consequence of a circular reference"); 16 } 17 else { 18 logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); 19 } 20 } 21 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); 22 } 23 24 else { 25 // Fail if we're already creating this bean instance: 26 // We're assumably within a circular reference. 27 if (isPrototypeCurrentlyInCreation(beanName)) { 28 throw new BeanCurrentlyInCreationException(beanName); 29 } 30 31 // Check if bean definition exists in this factory. 32 BeanFactory parentBeanFactory = getParentBeanFactory(); 33 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 34 // Not found -> check parent. 35 String nameToLookup = originalBeanName(name); 36 if (args != null) { 37 // Delegation to parent with explicit args. 38 return (T) parentBeanFactory.getBean(nameToLookup, args); 39 } 40 else { 41 // No args -> delegate to standard getBean method. 42 return parentBeanFactory.getBean(nameToLookup, requiredType); 43 } 44 } 45 46 if (!typeCheckOnly) { 47 markBeanAsCreated(beanName); 48 } 49 50 try { 51 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 52 checkMergedBeanDefinition(mbd, beanName, args); 53 54 // Guarantee initialization of beans that the current bean depends on. 55 String[] dependsOn = mbd.getDependsOn(); 56 if (dependsOn != null) { 57 for (String dep : dependsOn) { 58 if (isDependent(beanName, dep)) { 59 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 60 "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); 61 } 62 registerDependentBean(dep, beanName); 63 try { 64 getBean(dep); 65 } 66 catch (NoSuchBeanDefinitionException ex) { 67 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 68 "'" + beanName + "' depends on missing bean '" + dep + "'", ex); 69 } 70 } 71 } 72 73 // Create bean instance. 74 if (mbd.isSingleton()) { 75 // 此处进行bean创建 76 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { 77 @Override 78 public Object getObject() throws BeansException { 79 try { 80 return createBean(beanName, mbd, args); 81 } 82 catch (BeansException ex) { 83 // Explicitly remove instance from singleton cache: It might have been put there 84 // eagerly by the creation process, to allow for circular reference resolution. 85 // Also remove any beans that received a temporary reference to the bean. 86 destroySingleton(beanName); 87 throw ex; 88 } 89 } 90 }); 91 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 92 } 93 94 else if (mbd.isPrototype()) { 95 // It's a prototype -> create a new instance. 96 Object prototypeInstance = null; 97 try { 98 beforePrototypeCreation(beanName); 99 prototypeInstance = createBean(beanName, mbd, args); 100 } 101 finally { 102 afterPrototypeCreation(beanName); 103 } 104 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); 105 } 106 107 else { 108 String scopeName = mbd.getScope(); 109 final Scope scope = this.scopes.get(scopeName); 110 if (scope == null) { 111 throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); 112 } 113 try { 114 Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { 115 @Override 116 public Object getObject() throws BeansException { 117 beforePrototypeCreation(beanName); 118 try { 119 return createBean(beanName, mbd, args); 120 } 121 finally { 122 afterPrototypeCreation(beanName); 123 } 124 } 125 }); 126 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); 127 } 128 catch (IllegalStateException ex) { 129 throw new BeanCreationException(beanName, 130 "Scope '" + scopeName + "' is not active for the current thread; consider " + 131 "defining a scoped proxy for this bean if you intend to refer to it from a singleton", 132 ex); 133 } 134 } 135 } 136 catch (BeansException ex) { 137 cleanupAfterBeanCreationFailure(beanName); 138 throw ex; 139 } 140 } 141 142 // Check if required type matches the type of the actual bean instance. 143 if (requiredType != null && bean != null && !requiredType.isInstance(bean)) { 144 try { 145 return getTypeConverter().convertIfNecessary(bean, requiredType); 146 } 147 catch (TypeMismatchException ex) { 148 if (logger.isDebugEnabled()) { 149 logger.debug("Failed to convert bean '" + name + "' to required type '" + 150 ClassUtils.getQualifiedName(requiredType) + "'", ex); 151 } 152 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); 153 } 154 } 155 return (T) bean; 156 } 157 158 159 // org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton 160 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { 161 Assert.notNull(beanName, "'beanName' must not be null"); 162 synchronized (this.singletonObjects) { 163 Object singletonObject = this.singletonObjects.get(beanName); 164 if (singletonObject == null) { 165 if (this.singletonsCurrentlyInDestruction) { 166 throw new BeanCreationNotAllowedException(beanName, 167 "Singleton bean creation not allowed while singletons of this factory are in destruction " + 168 "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); 169 } 170 if (logger.isDebugEnabled()) { 171 logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); 172 } 173 beforeSingletonCreation(beanName); 174 boolean newSingleton = false; 175 boolean recordSuppressedExceptions = (this.suppressedExceptions == null); 176 if (recordSuppressedExceptions) { 177 this.suppressedExceptions = new LinkedHashSet<Exception>(); 178 } 179 try { 180 singletonObject = singletonFactory.getObject(); 181 newSingleton = true; 182 } 183 catch (IllegalStateException ex) { 184 // Has the singleton object implicitly appeared in the meantime -> 185 // if yes, proceed with it since the exception indicates that state. 186 singletonObject = this.singletonObjects.get(beanName); 187 if (singletonObject == null) { 188 throw ex; 189 } 190 } 191 catch (BeanCreationException ex) { 192 if (recordSuppressedExceptions) { 193 for (Exception suppressedException : this.suppressedExceptions) { 194 ex.addRelatedCause(suppressedException); 195 } 196 } 197 throw ex; 198 } 199 finally { 200 if (recordSuppressedExceptions) { 201 this.suppressedExceptions = null; 202 } 203 afterSingletonCreation(beanName); 204 } 205 if (newSingleton) { 206 // ref是在此处进行初始化的,有点神奇 207 addSingleton(beanName, singletonObject); 208 } 209 } 210 return (singletonObject != NULL_OBJECT ? singletonObject : null); 211 } 212 } 213 214 // org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.addSingleton 215 protected void addSingleton(String beanName, Object singletonObject) { 216 // 就是该 synchronized 方法,触发了 ReferenceConfig.ref 的初始化,实际上是触发了 AbstractConfig.toString() 方法 217 synchronized (this.singletonObjects) { 218 this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT)); 219 this.singletonFactories.remove(beanName); 220 this.earlySingletonObjects.remove(beanName); 221 this.registeredSingletons.add(beanName); 222 } 223 }
View Code
通过 ReferenceBean.getObject() 方法,获取代理:
1// 由 com.alibaba.dubbo.config.spring.ReferenceBean.getObject 进行获取代理,从而进行代理创建 2 @Override 3 public Object getObject() throws Exception { 4 return get(); 5 } 6 7 // 调用父类 com.alibaba.dubbo.config.ReferenceConfig.get() 方法, 获取实例 8 public synchronized T get() { 9 if (destroyed) { 10 throw new IllegalStateException("Already destroyed!"); 11 } 12 if (ref == null) { 13 // 未初始化时,触发一次初始化 14 init(); 15 } 16 return ref; 17 }
真正的代理之路开始了:
1// 初始化代理,并设值到 ref 变量中 2 private void init() { 3 if (initialized) { 4 return; 5 } 6 initialized = true; 7 if (interfaceName == null || interfaceName.length() == 0) { 8 throw new IllegalStateException("<dubbo:reference interface=\"\" /> interface not allow null!"); 9 } 10 // 在此处添加堆栈打印,排除路径,如下 11 new Throwable("*******************************ReferenceConfig.init trace dump").printStackTrace(); 12 new Throwable().printStackTrace(); 13 // get consumer's global configuration 14 checkDefault(); 15 appendProperties(this); 16 if (getGeneric() == null && getConsumer() != null) { 17 setGeneric(getConsumer().getGeneric()); 18 } 19 if (ProtocolUtils.isGeneric(getGeneric())) { 20 interfaceClass = GenericService.class; 21 } else { 22 try { 23 interfaceClass = Class.forName(interfaceName, true, Thread.currentThread() 24 .getContextClassLoader()); 25 } catch (ClassNotFoundException e) { 26 throw new IllegalStateException(e.getMessage(), e); 27 } 28 checkInterfaceAndMethods(interfaceClass, methods); 29 } 30 String resolve = System.getProperty(interfaceName); 31 String resolveFile = null; 32 if (resolve == null || resolve.length() == 0) { 33 resolveFile = System.getProperty("dubbo.resolve.file"); 34 if (resolveFile == null || resolveFile.length() == 0) { 35 File userResolveFile = new File(new File(System.getProperty("user.home")), "dubbo-resolve.properties"); 36 if (userResolveFile.exists()) { 37 resolveFile = userResolveFile.getAbsolutePath(); 38 } 39 } 40 if (resolveFile != null && resolveFile.length() > 0) { 41 Properties properties = new Properties(); 42 FileInputStream fis = null; 43 try { 44 fis = new FileInputStream(new File(resolveFile)); 45 properties.load(fis); 46 } catch (IOException e) { 47 throw new IllegalStateException("Unload " + resolveFile + ", cause: " + e.getMessage(), e); 48 } finally { 49 try { 50 if (null != fis) fis.close(); 51 } catch (IOException e) { 52 logger.warn(e.getMessage(), e); 53 } 54 } 55 resolve = properties.getProperty(interfaceName); 56 } 57 } 58 if (resolve != null && resolve.length() > 0) { 59 url = resolve; 60 if (logger.isWarnEnabled()) { 61 if (resolveFile != null) { 62 logger.warn("Using default dubbo resolve file " + resolveFile + " replace " + interfaceName + "" + resolve + " to p2p invoke remote service."); 63 } else { 64 logger.warn("Using -D" + interfaceName + "=" + resolve + " to p2p invoke remote service."); 65 } 66 } 67 } 68 if (consumer != null) { 69 if (application == null) { 70 application = consumer.getApplication(); 71 } 72 if (module == null) { 73 module = consumer.getModule(); 74 } 75 if (registries == null) { 76 registries = consumer.getRegistries(); 77 } 78 if (monitor == null) { 79 monitor = consumer.getMonitor(); 80 } 81 } 82 if (module != null) { 83 if (registries == null) { 84 registries = module.getRegistries(); 85 } 86 if (monitor == null) { 87 monitor = module.getMonitor(); 88 } 89 } 90 if (application != null) { 91 if (registries == null) { 92 registries = application.getRegistries(); 93 } 94 if (monitor == null) { 95 monitor = application.getMonitor(); 96 } 97 } 98 checkApplication(); 99 // 检查mock配置情况,尝试调用mock实例 100 checkStubAndMock(interfaceClass); 101 Map<String, String> map = new HashMap<String, String>(); 102 Map<Object, Object> attributes = new HashMap<Object, Object>(); 103 map.put(Constants.SIDE_KEY, Constants.CONSUMER_SIDE); 104 map.put(Constants.DUBBO_VERSION_KEY, Version.getProtocolVersion()); 105 map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis())); 106 if (ConfigUtils.getPid() > 0) { 107 map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid())); 108 } 109 if (!isGeneric()) { 110 String revision = Version.getVersion(interfaceClass, version); 111 if (revision != null && revision.length() > 0) { 112 map.put("revision", revision); 113 } 114 115 // 获取wrapper方法 116 String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames(); 117 if (methods.length == 0) { 118 logger.warn("NO method found in service interface " + interfaceClass.getName()); 119 map.put("methods", Constants.ANY_VALUE); 120 } else { 121 map.put("methods", StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ",")); 122 } 123 } 124 map.put(Constants.INTERFACE_KEY, interfaceName); 125 appendParameters(map, application); 126 appendParameters(map, module); 127 appendParameters(map, consumer, Constants.DEFAULT_KEY); 128 appendParameters(map, this); 129 String prefix = StringUtils.getServiceKey(map); 130 if (methods != null && !methods.isEmpty()) { 131 for (MethodConfig method : methods) { 132 appendParameters(map, method, method.getName()); 133 String retryKey = method.getName() + ".retry"; 134 if (map.containsKey(retryKey)) { 135 String retryValue = map.remove(retryKey); 136 if ("false".equals(retryValue)) { 137 map.put(method.getName() + ".retries", "0"); 138 } 139 } 140 appendAttributes(attributes, method, prefix + "." + method.getName()); 141 checkAndConvertImplicitConfig(method, map, attributes); 142 } 143 } 144 145 String hostToRegistry = ConfigUtils.getSystemProperty(Constants.DUBBO_IP_TO_REGISTRY); 146 if (hostToRegistry == null || hostToRegistry.length() == 0) { 147 hostToRegistry = NetUtils.getLocalHost(); 148 } else if (isInvalidLocalHost(hostToRegistry)) { 149 throw new IllegalArgumentException("Specified invalid registry ip from property:" + Constants.DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry); 150 } 151 map.put(Constants.REGISTER_IP_KEY, hostToRegistry); 152 153 //attributes are stored by system context. 154 StaticContext.getSystemContext().putAll(attributes); 155 ref = createProxy(map); 156 ConsumerModel consumerModel = new ConsumerModel(getUniqueServiceName(), this, ref, interfaceClass.getMethods()); 157 ApplicationModel.initConsumerModel(getUniqueServiceName(), consumerModel); 158 } 159
控制权留给mock,先检查下是否有设置,有则先检查是否正确。
1// AbstractInterfaceConfig.checkStubAndMock() 2 protected void checkStubAndMock(Class<?> interfaceClass) { 3 if (ConfigUtils.isNotEmpty(local)) { 4 Class<?> localClass = ConfigUtils.isDefault(local) ? ReflectUtils.forName(interfaceClass.getName() + "Local") : ReflectUtils.forName(local); 5 if (!interfaceClass.isAssignableFrom(localClass)) { 6 throw new IllegalStateException("The local implementation class " + localClass.getName() + " not implement interface " + interfaceClass.getName()); 7 } 8 try { 9 ReflectUtils.findConstructor(localClass, interfaceClass); 10 } catch (NoSuchMethodException e) { 11 throw new IllegalStateException("No such constructor \"public " + localClass.getSimpleName() + "(" + interfaceClass.getName() + ")\" in local implementation class " + localClass.getName()); 12 } 13 } 14 if (ConfigUtils.isNotEmpty(stub)) { 15 Class<?> localClass = ConfigUtils.isDefault(stub) ? ReflectUtils.forName(interfaceClass.getName() + "Stub") : ReflectUtils.forName(stub); 16 if (!interfaceClass.isAssignableFrom(localClass)) { 17 throw new IllegalStateException("The local implementation class " + localClass.getName() + " not implement interface " + interfaceClass.getName()); 18 } 19 try { 20 ReflectUtils.findConstructor(localClass, interfaceClass); 21 } catch (NoSuchMethodException e) { 22 throw new IllegalStateException("No such constructor \"public " + localClass.getSimpleName() + "(" + interfaceClass.getName() + ")\" in local implementation class " + localClass.getName()); 23 } 24 } 25 if (ConfigUtils.isNotEmpty(mock)) { 26 if (mock.startsWith(Constants.RETURN_PREFIX)) { 27 String value = mock.substring(Constants.RETURN_PREFIX.length()); 28 try { 29 MockInvoker.parseMockValue(value); 30 } catch (Exception e) { 31 throw new IllegalStateException("Illegal mock json value in <dubbo:service ... mock=\"" + mock + "\" />"); 32 } 33 } else { 34 Class<?> mockClass = ConfigUtils.isDefault(mock) ? ReflectUtils.forName(interfaceClass.getName() + "Mock") : ReflectUtils.forName(mock); 35 if (!interfaceClass.isAssignableFrom(mockClass)) { 36 throw new IllegalStateException("The mock implementation class " + mockClass.getName() + " not implement interface " + interfaceClass.getName()); 37 } 38 try { 39 mockClass.getConstructor(new Class<?>[0]); 40 } catch (NoSuchMethodException e) { 41 throw new IllegalStateException("No such empty constructor \"public " + mockClass.getSimpleName() + "()\" in mock implementation class " + mockClass.getName()); 42 } 43 } 44 } 45 } 46
获取wrapper,以备后续调用:
1// com.alibaba.dubbo.common.bytecode.Wrapper 2 public static Wrapper getWrapper(Class<?> c) { 3 while (ClassGenerator.isDynamicClass(c)) // can not wrapper on dynamic class. 4 c = c.getSuperclass(); 5 6 if (c == Object.class) 7 return OBJECT_WRAPPER; 8 9 Wrapper ret = WRAPPER_MAP.get(c); 10 if (ret == null) { 11 ret = makeWrapper(c); 12 WRAPPER_MAP.put(c, ret); 13 } 14 return ret; 15 } 16 17 private static Wrapper makeWrapper(Class<?> c) { 18 if (c.isPrimitive()) 19 throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c); 20 21 String name = c.getName(); 22 ClassLoader cl = ClassHelper.getClassLoader(c); 23 24 StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ "); 25 StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ "); 26 StringBuilder c3 = new StringBuilder("public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws " + InvocationTargetException.class.getName() + "{ "); 27 28 c1.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }"); 29 c2.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }"); 30 c3.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }"); 31 32 Map<String, Class<?>> pts = new HashMap<String, Class<?>>(); // <property name, property types> 33 Map<String, Method> ms = new LinkedHashMap<String, Method>(); // <method desc, Method instance> 34 List<String> mns = new ArrayList<String>(); // method names. 35 List<String> dmns = new ArrayList<String>(); // declaring method names. 36 37 // get all public field. 38 for (Field f : c.getFields()) { 39 String fn = f.getName(); 40 Class<?> ft = f.getType(); 41 if (Modifier.isStatic(f.getModifiers()) || Modifier.isTransient(f.getModifiers())) 42 continue; 43 44 c1.append(" if( $2.equals(\"").append(fn).append("\") ){ w.").append(fn).append("=").append(arg(ft, "$3")).append("; return; }"); 45 c2.append(" if( $2.equals(\"").append(fn).append("\") ){ return ($w)w.").append(fn).append("; }"); 46 pts.put(fn, ft); 47 } 48 49 Method[] methods = c.getMethods(); 50 // get all public method. 51 boolean hasMethod = hasMethods(methods); 52 if (hasMethod) { 53 c3.append(" try{"); 54 } 55 for (Method m : methods) { 56 if (m.getDeclaringClass() == Object.class) //ignore Object's method. 57 continue; 58 59 String mn = m.getName(); 60 c3.append(" if( \"").append(mn).append("\".equals( $2 ) "); 61 int len = m.getParameterTypes().length; 62 c3.append(" && ").append(" $3.length == ").append(len); 63 64 boolean override = false; 65 for (Method m2 : methods) { 66 if (m != m2 && m.getName().equals(m2.getName())) { 67 override = true; 68 break; 69 } 70 } 71 if (override) { 72 if (len > 0) { 73 for (int l = 0; l < len; l++) { 74 c3.append(" && ").append(" $3[").append(l).append("].getName().equals(\"") 75 .append(m.getParameterTypes()[l].getName()).append("\")"); 76 } 77 } 78 } 79 80 c3.append(" ) { "); 81 82 if (m.getReturnType() == Void.TYPE) 83 c3.append(" w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");").append(" return null;"); 84 else 85 c3.append(" return ($w)w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");"); 86 87 c3.append(" }"); 88 89 mns.add(mn); 90 if (m.getDeclaringClass() == c) 91 dmns.add(mn); 92 ms.put(ReflectUtils.getDesc(m), m); 93 } 94 if (hasMethod) { 95 c3.append(" } catch(Throwable e) { "); 96 c3.append(" throw new java.lang.reflect.InvocationTargetException(e); "); 97 c3.append(" }"); 98 } 99 100 c3.append(" throw new " + NoSuchMethodException.class.getName() + "(\"Not found method \\\"\"+$2+\"\\\" in class " + c.getName() + ".\"); }"); 101 102 // deal with get/set method. 103 Matcher matcher; 104 for (Map.Entry<String, Method> entry : ms.entrySet()) { 105 String md = entry.getKey(); 106 Method method = (Method) entry.getValue(); 107 if ((matcher = ReflectUtils.GETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) { 108 String pn = propertyName(matcher.group(1)); 109 c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }"); 110 pts.put(pn, method.getReturnType()); 111 } else if ((matcher = ReflectUtils.IS_HAS_CAN_METHOD_DESC_PATTERN.matcher(md)).matches()) { 112 String pn = propertyName(matcher.group(1)); 113 c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }"); 114 pts.put(pn, method.getReturnType()); 115 } else if ((matcher = ReflectUtils.SETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) { 116 Class<?> pt = method.getParameterTypes()[0]; 117 String pn = propertyName(matcher.group(1)); 118 c1.append(" if( $2.equals(\"").append(pn).append("\") ){ w.").append(method.getName()).append("(").append(arg(pt, "$3")).append("); return; }"); 119 pts.put(pn, pt); 120 } 121 } 122 c1.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }"); 123 c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }"); 124 125 // make class 126 long id = WRAPPER_CLASS_COUNTER.getAndIncrement(); 127 ClassGenerator cc = ClassGenerator.newInstance(cl); 128 cc.setClassName((Modifier.isPublic(c.getModifiers()) ? Wrapper.class.getName() : c.getName() + "$sw") + id); 129 cc.setSuperClass(Wrapper.class); 130 131 cc.addDefaultConstructor(); 132 cc.addField("public static String[] pns;"); // property name array. 133 cc.addField("public static " + Map.class.getName() + " pts;"); // property type map. 134 cc.addField("public static String[] mns;"); // all method name array. 135 cc.addField("public static String[] dmns;"); // declared method name array. 136 for (int i = 0, len = ms.size(); i < len; i++) 137 cc.addField("public static Class[] mts" + i + ";"); 138 139 cc.addMethod("public String[] getPropertyNames(){ return pns; }"); 140 cc.addMethod("public boolean hasProperty(String n){ return pts.containsKey($1); }"); 141 cc.addMethod("public Class getPropertyType(String n){ return (Class)pts.get($1); }"); 142 cc.addMethod("public String[] getMethodNames(){ return mns; }"); 143 cc.addMethod("public String[] getDeclaredMethodNames(){ return dmns; }"); 144 cc.addMethod(c1.toString()); 145 cc.addMethod(c2.toString()); 146 cc.addMethod(c3.toString()); 147 148 try { 149 Class<?> wc = cc.toClass(); 150 // setup static field. 151 wc.getField("pts").set(null, pts); 152 wc.getField("pns").set(null, pts.keySet().toArray(new String[0])); 153 wc.getField("mns").set(null, mns.toArray(new String[0])); 154 wc.getField("dmns").set(null, dmns.toArray(new String[0])); 155 int ix = 0; 156 for (Method m : ms.values()) 157 wc.getField("mts" + ix++).set(null, m.getParameterTypes()); 158 return (Wrapper) wc.newInstance(); 159 } catch (RuntimeException e) { 160 throw e; 161 } catch (Throwable e) { 162 throw new RuntimeException(e.getMessage(), e); 163 } finally { 164 cc.release(); 165 ms.clear(); 166 mns.clear(); 167 dmns.clear(); 168 } 169 } 170
// InvokerInvocationHandler, 代理所有的dubbo请求处理
1// InvokerInvocationHandler, 代理所有的dubbo请求处理 2public class InvokerInvocationHandler implements InvocationHandler { 3 4 private final Invoker<?> invoker; 5 6 public InvokerInvocationHandler(Invoker<?> handler) { 7 this.invoker = handler; 8 } 9 10 @Override 11 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 12 String methodName = method.getName(); 13 Class<?>[] parameterTypes = method.getParameterTypes(); 14 if (method.getDeclaringClass() == Object.class) { 15 return method.invoke(invoker, args); 16 } 17 if ("toString".equals(methodName) && parameterTypes.length == 0) { 18 return invoker.toString(); 19 } 20 if ("hashCode".equals(methodName) && parameterTypes.length == 0) { 21 return invoker.hashCode(); 22 } 23 if ("equals".equals(methodName) && parameterTypes.length == 1) { 24 return invoker.equals(args[0]); 25 } 26 return invoker.invoke(new RpcInvocation(method, args)).recreate(); 27 } 28 29}
// 小插曲,日志打印
1//FailsafeLogger.warn(), 格式为: No spring extension(bean) named:defaultCompiler, try to find an extension(bean) of type java.lang.String, dubbo version: , current host: 192.168.11.6 2 3 @Override 4 public void warn(String msg, Throwable e) { 5 try { 6 logger.warn(appendContextMessage(msg), e); 7 } catch (Throwable t) { 8 } 9 } 10 private String appendContextMessage(String msg) { 11 return " [DUBBO] " + msg + ", dubbo version: " + Version.getVersion() + ", current host: " + NetUtils.getLocalHost(); 12 } 13 14 private Class<?> createAdaptiveExtensionClass() { 15 String code = createAdaptiveExtensionClassCode(); 16 ClassLoader classLoader = findClassLoader(); 17 com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension(); 18 return compiler.compile(code, classLoader); 19 }
// wrapper0
1// 生成的包装类如下: com.alibaba.dubbo.common.bytecode.Wrapper0 2package com.alibaba.dubbo.common.bytecode; 3 4import com.alibaba.dubbo.common.bytecode.ClassGenerator.DC; 5import com.alibaba.dubbo.demo.DemoService; 6import java.lang.reflect.InvocationTargetException; 7import java.util.Map; 8 9public class Wrapper0 extends Wrapper implements DC { 10 public static String[] pns; 11 public static Map pts; 12 public static String[] mns; 13 public static String[] dmns; 14 public static Class[] mts0; 15 16 public String[] getPropertyNames() { 17 return pns; 18 } 19 20 public boolean hasProperty(String var1) { 21 return pts.containsKey(var1); 22 } 23 24 public Class getPropertyType(String var1) { 25 return (Class)pts.get(var1); 26 } 27 28 public String[] getMethodNames() { 29 return mns; 30 } 31 32 public String[] getDeclaredMethodNames() { 33 return dmns; 34 } 35 36 public void setPropertyValue(Object var1, String var2, Object var3) { 37 try { 38 DemoService var4 = (DemoService)var1; 39 } catch (Throwable var6) { 40 throw new IllegalArgumentException(var6); 41 } 42 43 throw new NoSuchPropertyException("Not found property \"" + var2 + "\" filed or setter method in class com.alibaba.dubbo.demo.DemoService."); 44 } 45 46 public Object getPropertyValue(Object var1, String var2) { 47 try { 48 DemoService var3 = (DemoService)var1; 49 } catch (Throwable var5) { 50 throw new IllegalArgumentException(var5); 51 } 52 53 throw new NoSuchPropertyException("Not found property \"" + var2 + "\" filed or setter method in class com.alibaba.dubbo.demo.DemoService."); 54 } 55 56 public Object invokeMethod(Object var1, String var2, Class[] var3, Object[] var4) throws InvocationTargetException { 57 DemoService var5; 58 try { 59 var5 = (DemoService)var1; 60 } catch (Throwable var8) { 61 throw new IllegalArgumentException(var8); 62 } 63 64 try { 65 if ("sayHello".equals(var2) && var3.length == 1) { 66 return var5.sayHello((String)var4[0]); 67 } 68 } catch (Throwable var9) { 69 throw new InvocationTargetException(var9); 70 } 71 72 throw new NoSuchMethodException("Not found method \"" + var2 + "\" in class com.alibaba.dubbo.demo.DemoService."); 73 } 74 75 public Wrapper0() { 76 } 77}
// createProxy
1// com.alibaba.dubbo.common.bytecode.ClassGenerator, 生成class实例 2 public Class<?> toClass() { 3 return toClass(ClassHelper.getClassLoader(ClassGenerator.class), getClass().getProtectionDomain()); 4 } 5 6 public Class<?> toClass(ClassLoader loader, ProtectionDomain pd) { 7 if (mCtc != null) 8 mCtc.detach(); 9 long id = CLASS_NAME_COUNTER.getAndIncrement(); 10 try { 11 CtClass ctcs = mSuperClass == null ? null : mPool.get(mSuperClass); 12 if (mClassName == null) 13 mClassName = (mSuperClass == null || javassist.Modifier.isPublic(ctcs.getModifiers()) 14 ? ClassGenerator.class.getName() : mSuperClass + "$sc") + id; 15 mCtc = mPool.makeClass(mClassName); 16 if (mSuperClass != null) 17 mCtc.setSuperclass(ctcs); 18 // 添加dubbo ClassGenerator 生成的动态类的标志,接口方法为空 19 mCtc.addInterface(mPool.get(DC.class.getName())); // add dynamic class tag. 20 if (mInterfaces != null) 21 for (String cl : mInterfaces) mCtc.addInterface(mPool.get(cl)); 22 if (mFields != null) 23 for (String code : mFields) mCtc.addField(CtField.make(code, mCtc)); 24 if (mMethods != null) { 25 for (String code : mMethods) { 26 if (code.charAt(0) == ':') 27 mCtc.addMethod(CtNewMethod.copy(getCtMethod(mCopyMethods.get(code.substring(1))), code.substring(1, code.indexOf('(')), mCtc, null)); 28 else 29 mCtc.addMethod(CtNewMethod.make(code, mCtc)); 30 } 31 } 32 if (mDefaultConstructor) 33 mCtc.addConstructor(CtNewConstructor.defaultConstructor(mCtc)); 34 if (mConstructors != null) { 35 for (String code : mConstructors) { 36 if (code.charAt(0) == ':') { 37 mCtc.addConstructor(CtNewConstructor.copy(getCtConstructor(mCopyConstructors.get(code.substring(1))), mCtc, null)); 38 } else { 39 String[] sn = mCtc.getSimpleName().split("\\$+"); // inner class name include $. 40 mCtc.addConstructor(CtNewConstructor.make(code.replaceFirst(SIMPLE_NAME_TAG, sn[sn.length - 1]), mCtc)); 41 } 42 } 43 } 44 return mCtc.toClass(loader, pd); 45 } catch (RuntimeException e) { 46 throw e; 47 } catch (NotFoundException e) { 48 throw new RuntimeException(e.getMessage(), e); 49 } catch (CannotCompileException e) { 50 throw new RuntimeException(e.getMessage(), e); 51 } 52 } 53 54 55 // 创建操作代理类 56 // ref = createProxy(map); 生成新proxy {methods=sayHello, timestamp=1537527140342, dubbo=2.0.2, register.ip=192.168.11.6, application=demo-consumer, check=false, side=consumer, pid=8776, interface=com.alibaba.dubbo.demo.DemoService, qos.port=33333} 57 @SuppressWarnings({"unchecked", "rawtypes", "deprecation"}) 58 private T createProxy(Map<String, String> map) { 59 URL tmpUrl = new URL("temp", "localhost", 0, map); 60 final boolean isJvmRefer; 61 if (isInjvm() == null) { 62 if (url != null && url.length() > 0) { // if a url is specified, don't do local reference 63 isJvmRefer = false; 64 } else if (InjvmProtocol.getInjvmProtocol().isInjvmRefer(tmpUrl)) { 65 // by default, reference local service if there is 66 isJvmRefer = true; 67 } else { 68 isJvmRefer = false; 69 } 70 } else { 71 isJvmRefer = isInjvm().booleanValue(); 72 } 73 74 if (isJvmRefer) { 75 URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map); 76 invoker = refprotocol.refer(interfaceClass, url); 77 if (logger.isInfoEnabled()) { 78 logger.info("Using injvm service " + interfaceClass.getName()); 79 } 80 } else { 81 if (url != null && url.length() > 0) { // user specified URL, could be peer-to-peer address, or register center's address. 82 String[] us = Constants.SEMICOLON_SPLIT_PATTERN.split(url); 83 if (us != null && us.length > 0) { 84 for (String u : us) { 85 URL url = URL.valueOf(u); 86 if (url.getPath() == null || url.getPath().length() == 0) { 87 url = url.setPath(interfaceName); 88 } 89 if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) { 90 urls.add(url.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map))); 91 } else { 92 urls.add(ClusterUtils.mergeUrl(url, map)); 93 } 94 } 95 } 96 } else { // assemble URL from register center's configuration 97 //[registry://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?application=demo-consumer&dubbo=2.0.2&pid=8776&qos.port=33333®istry=zookeeper&timeout=2000×tamp=1537528008773] 98 // 最后得到的地址是这样的: registry://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?application=demo-consumer&dubbo=2.0.2&pid=14040&qos.port=33333&refer=application=demo-consumer%26check=false%26dubbo=2.0.2%26interface=com.alibaba.dubbo.demo.DemoService%26methods=sayHello%26pid=14040%26qos.port=33333%26register.ip=192.168.11.6%26side=consumer%26timestamp=1537844804936®istry=zookeeper&timeout=2000×tamp=1537847505648 99 List<URL> us = loadRegistries(false); 100 if (us != null && !us.isEmpty()) { 101 for (URL u : us) { 102 // 加载监控地址,以便进行上报数据 103 URL monitorUrl = loadMonitor(u); 104 if (monitorUrl != null) { 105 map.put(Constants.MONITOR_KEY, URL.encode(monitorUrl.toFullString())); 106 } 107 urls.add(u.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map))); 108 } 109 } 110 if (urls.isEmpty()) { 111 throw new IllegalStateException("No such any registry to reference " + interfaceName + " on the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", please config <dubbo:registry address=\"...\" /> to your spring config."); 112 } 113 } 114 115 if (urls.size() == 1) { 116 // Protocol$Adaptive, 动态生成的代理类,调用远程方法 com.alibaba.dubbo.remoting.transport.AbstractClient(), 先将自己注册到注册中心,再调用提供者方法 117 /** 118 "main@1" prio=5 tid=0x1 nid=NA runnable 119 java.lang.Thread.State: RUNNABLE 120 at com.alibaba.dubbo.remoting.transport.AbstractClient.<init>(AbstractClient.java:80) 121 at com.alibaba.dubbo.remoting.transport.netty.NettyClient.<init>(NettyClient.java:59) 122 at com.alibaba.dubbo.remoting.transport.netty.NettyTransporter.connect(NettyTransporter.java:37) 123 at com.alibaba.dubbo.remoting.Transporter$Adaptive.connect(Transporter$Adaptive.java:-1) 124 at com.alibaba.dubbo.remoting.Transporters.connect(Transporters.java:75) 125 at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchanger.connect(HeaderExchanger.java:39) 126 at com.alibaba.dubbo.remoting.exchange.Exchangers.connect(Exchangers.java:109) 127 at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol.initClient(DubboProtocol.java:417) 128 at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol.getSharedClient(DubboProtocol.java:384) 129 - locked <0xb4f> (a java.lang.Object) 130 at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol.getClients(DubboProtocol.java:355) 131 at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol.refer(DubboProtocol.java:337) 132 at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper.refer(ProtocolFilterWrapper.java:108) 133 at com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper.refer(ProtocolListenerWrapper.java:67) 134 at com.alibaba.dubbo.rpc.Protocol$Adaptive.refer(Protocol$Adaptive.java:-1) 135 at com.alibaba.dubbo.registry.integration.RegistryDirectory.toInvokers(RegistryDirectory.java:387) 136 at com.alibaba.dubbo.registry.integration.RegistryDirectory.refreshInvoker(RegistryDirectory.java:253) 137 at com.alibaba.dubbo.registry.integration.RegistryDirectory.notify(RegistryDirectory.java:223) 138 - locked <0xb2f> (a com.alibaba.dubbo.registry.integration.RegistryDirectory) 139 at com.alibaba.dubbo.registry.support.AbstractRegistry.notify(AbstractRegistry.java:414) 140 at com.alibaba.dubbo.registry.support.FailbackRegistry.doNotify(FailbackRegistry.java:280) 141 at com.alibaba.dubbo.registry.support.FailbackRegistry.notify(FailbackRegistry.java:266) 142 at com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistry.doSubscribe(ZookeeperRegistry.java:190) 143 at com.alibaba.dubbo.registry.support.FailbackRegistry.subscribe(FailbackRegistry.java:196) 144 at com.alibaba.dubbo.registry.integration.RegistryDirectory.subscribe(RegistryDirectory.java:159) 145 at com.alibaba.dubbo.registry.integration.RegistryProtocol.doRefer(RegistryProtocol.java:307) 146 at com.alibaba.dubbo.registry.integration.RegistryProtocol.refer(RegistryProtocol.java:288) 147 at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper.refer(ProtocolFilterWrapper.java:106) 148 at com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper.refer(ProtocolListenerWrapper.java:65) 149 // 从此处开始进行调用 150 at com.alibaba.dubbo.rpc.Protocol$Adaptive.refer(Protocol$Adaptive.java:-1) 151 at com.alibaba.dubbo.config.ReferenceConfig.createProxy(ReferenceConfig.java:395) 152 at com.alibaba.dubbo.config.ReferenceConfig.init(ReferenceConfig.java:334) 153 at com.alibaba.dubbo.config.ReferenceConfig.get(ReferenceConfig.java:163) 154 - locked <0x76b> (a com.alibaba.dubbo.config.spring.ReferenceBean) 155 at com.alibaba.dubbo.config.spring.ReferenceBean.getObject(ReferenceBean.java:66) 156 at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:170) 157 at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:103) 158 - locked <0x790> (a java.util.concurrent.ConcurrentHashMap) 159 at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1640) 160 at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:254) 161 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 162 at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) 163 at com.alibaba.dubbo.demo.consumer.Consumer.main(Consumer.java:30) 164 */ 165 invoker = refprotocol.refer(interfaceClass, urls.get(0)); 166 } else { 167 List<Invoker<?>> invokers = new ArrayList<Invoker<?>>(); 168 URL registryURL = null; 169 for (URL url : urls) { 170 invokers.add(refprotocol.refer(interfaceClass, url)); 171 if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) { 172 registryURL = url; // use last registry url 173 } 174 } 175 if (registryURL != null) { // registry url is available 176 // use AvailableCluster only when register's cluster is available 177 URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME); 178 invoker = cluster.join(new StaticDirectory(u, invokers)); 179 } else { // not a registry url 180 invoker = cluster.join(new StaticDirectory(invokers)); 181 } 182 } 183 } 184 185 Boolean c = check; 186 if (c == null && consumer != null) { 187 c = consumer.isCheck(); 188 } 189 if (c == null) { 190 c = true; // default true 191 } 192 if (c && !invoker.isAvailable()) { 193 throw new IllegalStateException("Failed to check the status of the service " + interfaceName + ". No provider available for the service " + (group == null ? "" : group + "/") + interfaceName + (version == null ? "" : ":" + version) + " from the url " + invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion()); 194 } 195 if (logger.isInfoEnabled()) { 196 logger.info("Refer dubbo service " + interfaceClass.getName() + " from url " + invoker.getUrl()); 197 } 198 // create service proxy 199 return (T) proxyFactory.getProxy(invoker); 200 } 201 202 // loadRegistries 203 204 protected List<URL> loadRegistries(boolean provider) { 205 // 加载前,先检查是否已初始化 206 checkRegistry(); 207 List<URL> registryList = new ArrayList<URL>(); 208 if (registries != null && !registries.isEmpty()) { 209 for (RegistryConfig config : registries) { 210 String address = config.getAddress(); 211 if (address == null || address.length() == 0) { 212 address = Constants.ANYHOST_VALUE; 213 } 214 String sysaddress = System.getProperty("dubbo.registry.address"); 215 if (sysaddress != null && sysaddress.length() > 0) { 216 address = sysaddress; 217 } 218 if (address.length() > 0 && !RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(address)) { 219 Map<String, String> map = new HashMap<String, String>(); 220 appendParameters(map, application); 221 appendParameters(map, config); 222 map.put("path", RegistryService.class.getName()); 223 map.put("dubbo", Version.getProtocolVersion()); 224 map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis())); 225 if (ConfigUtils.getPid() > 0) { 226 map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid())); 227 } 228 if (!map.containsKey("protocol")) { 229 if (ExtensionLoader.getExtensionLoader(RegistryFactory.class).hasExtension("remote")) { 230 map.put("protocol", "remote"); 231 } else { 232 map.put("protocol", "dubbo"); 233 } 234 } 235 // 解析注册中心地址列表 236 List<URL> urls = UrlUtils.parseURLs(address, map); 237 for (URL url : urls) { 238 url = url.addParameter(Constants.REGISTRY_KEY, url.getProtocol()); 239 url = url.setProtocol(Constants.REGISTRY_PROTOCOL); 240 if ((provider && url.getParameter(Constants.REGISTER_KEY, true)) 241 || (!provider && url.getParameter(Constants.SUBSCRIBE_KEY, true))) { 242 registryList.add(url); 243 } 244 } 245 } 246 } 247 } 248 return registryList; 249 }
//
1// com.alibaba.dubbo.rpc.Protocol$Adaptive, 动态生成的类,去调用远程方法 2 3public class Protocol$Adaptive implements Protocol { 4 public void destroy() { 5 throw new UnsupportedOperationException("method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!"); 6 } 7 8 public int getDefaultPort() { 9 throw new UnsupportedOperationException("method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!"); 10 } 11 12 public Invoker refer(Class var1, URL var2) throws RpcException { 13 if (var2 == null) { 14 throw new IllegalArgumentException("url == null"); 15 } else { 16 String var4 = var2.getProtocol() == null ? "dubbo" : var2.getProtocol(); 17 if (var4 == null) { 18 throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + var2.toString() + ") use keys([protocol])"); 19 } else { 20 Protocol var5 = (Protocol)ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(var4); 21 return var5.refer(var1, var2); 22 } 23 } 24 } 25 26 public Exporter export(Invoker var1) throws RpcException { 27 if (var1 == null) { 28 throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null"); 29 } else if (var1.getUrl() == null) { 30 throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null"); 31 } else { 32 URL var2 = var1.getUrl(); 33 String var3 = var2.getProtocol() == null ? "dubbo" : var2.getProtocol(); 34 if (var3 == null) { 35 throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + var2.toString() + ") use keys([protocol])"); 36 } else { 37 Protocol var4 = (Protocol)ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(var3); 38 return var4.export(var1); 39 } 40 } 41 } 42 43 public Protocol$Adaptive() { 44 } 45} 46 47// com.alibaba.dubbo.registry.integration.RegistryDirectory.subscribe, 订阅服务 48 public void subscribe(URL url) { 49 setConsumerUrl(url); 50 registry.subscribe(url, this); 51 } 52 53 54 // 以zookeeper订阅为例,看一下订阅过程,com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistry.doSubscribe() 55 @Override 56 protected void doSubscribe(final URL url, final NotifyListener listener) { 57 try { 58 if (Constants.ANY_VALUE.equals(url.getServiceInterface())) { 59 String root = toRootPath(); 60 ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url); 61 if (listeners == null) { 62 zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>()); 63 listeners = zkListeners.get(url); 64 } 65 ChildListener zkListener = listeners.get(listener); 66 if (zkListener == null) { 67 listeners.putIfAbsent(listener, new ChildListener() { 68 @Override 69 public void childChanged(String parentPath, List<String> currentChilds) { 70 for (String child : currentChilds) { 71 child = URL.decode(child); 72 if (!anyServices.contains(child)) { 73 anyServices.add(child); 74 subscribe(url.setPath(child).addParameters(Constants.INTERFACE_KEY, child, 75 Constants.CHECK_KEY, String.valueOf(false)), listener); 76 } 77 } 78 } 79 }); 80 zkListener = listeners.get(listener); 81 } 82 zkClient.create(root, false); 83 List<String> services = zkClient.addChildListener(root, zkListener); 84 if (services != null && !services.isEmpty()) { 85 for (String service : services) { 86 service = URL.decode(service); 87 anyServices.add(service); 88 subscribe(url.setPath(service).addParameters(Constants.INTERFACE_KEY, service, 89 Constants.CHECK_KEY, String.valueOf(false)), listener); 90 } 91 } 92 } else { 93 List<URL> urls = new ArrayList<URL>(); 94 for (String path : toCategoriesPath(url)) { 95 ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url); 96 if (listeners == null) { 97 zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>()); 98 listeners = zkListeners.get(url); 99 } 100 ChildListener zkListener = listeners.get(listener); 101 if (zkListener == null) { 102 listeners.putIfAbsent(listener, new ChildListener() { 103 @Override 104 public void childChanged(String parentPath, List<String> currentChilds) { 105 ZookeeperRegistry.this.notify(url, listener, toUrlsWithEmpty(url, parentPath, currentChilds)); 106 } 107 }); 108 zkListener = listeners.get(listener); 109 } 110 zkClient.create(path, false); 111 List<String> children = zkClient.addChildListener(path, zkListener); 112 if (children != null) { 113 urls.addAll(toUrlsWithEmpty(url, path, children)); 114 } 115 } 116 notify(url, listener, urls); 117 } 118 } catch (Throwable e) { 119 throw new RpcException("Failed to subscribe " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e); 120 } 121 } 122 123 124 125 // com.alibaba.dubbo.registry.support.AbstractRegistry.notify, 获取服务提供者地址 126 protected void notify(URL url, NotifyListener listener, List<URL> urls) { 127 if (url == null) { 128 throw new IllegalArgumentException("notify url == null"); 129 } 130 if (listener == null) { 131 throw new IllegalArgumentException("notify listener == null"); 132 } 133 if ((urls == null || urls.isEmpty()) 134 && !Constants.ANY_VALUE.equals(url.getServiceInterface())) { 135 logger.warn("Ignore empty notify urls for subscribe url " + url); 136 return; 137 } 138 if (logger.isInfoEnabled()) { 139 logger.info("Notify urls for subscribe url " + url + ", urls: " + urls); 140 } 141 Map<String, List<URL>> result = new HashMap<String, List<URL>>(); 142 for (URL u : urls) { 143 if (UrlUtils.isMatch(url, u)) { 144 String category = u.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY); 145 List<URL> categoryList = result.get(category); 146 if (categoryList == null) { 147 categoryList = new ArrayList<URL>(); 148 result.put(category, categoryList); 149 } 150 categoryList.add(u); 151 } 152 } 153 if (result.size() == 0) { 154 return; 155 } 156 Map<String, List<URL>> categoryNotified = notified.get(url); 157 if (categoryNotified == null) { 158 notified.putIfAbsent(url, new ConcurrentHashMap<String, List<URL>>()); 159 categoryNotified = notified.get(url); 160 } 161 // 通知观察者 162 for (Map.Entry<String, List<URL>> entry : result.entrySet()) { 163 String category = entry.getKey(); 164 List<URL> categoryList = entry.getValue(); 165 categoryNotified.put(category, categoryList); 166 saveProperties(url); 167 listener.notify(categoryList); 168 } 169 } 170 171 172// 获取registry,以决定调用哪个协议实现 173 @Override 174 public Registry getRegistry(URL url) { 175 url = url.setPath(RegistryService.class.getName()) 176 .addParameter(Constants.INTERFACE_KEY, RegistryService.class.getName()) 177 .removeParameters(Constants.EXPORT_KEY, Constants.REFER_KEY); 178 String key = url.toServiceString(); 179 // Lock the registry access process to ensure a single instance of the registry 180 LOCK.lock(); 181 try { 182 Registry registry = REGISTRIES.get(key); 183 if (registry != null) { 184 return registry; 185 } 186 // 创建registry, 该方法为抽象方法只能由具体的实现类实现 187 registry = createRegistry(url); 188 if (registry == null) { 189 throw new IllegalStateException("Can not create registry " + url); 190 } 191 REGISTRIES.put(key, registry); 192 return registry; 193 } finally { 194 // Release the lock 195 LOCK.unlock(); 196 } 197 } 198 199 // 该方法为在生成代理时自动生成实现 200 protected abstract Registry createRegistry(URL url); 201 202 // 生成的registry代理类如下 203package com.alibaba.dubbo.registry; 204 205import com.alibaba.dubbo.common.URL; 206import com.alibaba.dubbo.common.extension.ExtensionLoader; 207 208public class RegistryFactory$Adaptive implements RegistryFactory { 209 public Registry getRegistry(URL var1) { 210 if (var1 == null) { 211 throw new IllegalArgumentException("url == null"); 212 } else { 213 String var3 = var1.getProtocol() == null ? "dubbo" : var1.getProtocol(); 214 if (var3 == null) { 215 throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.registry.RegistryFactory) name from url(" + var1.toString() + ") use keys([protocol])"); 216 } else { 217 RegistryFactory var4 = (RegistryFactory)ExtensionLoader.getExtensionLoader(RegistryFactory.class).getExtension(var3); 218 return var4.getRegistry(var1); 219 } 220 } 221 } 222 223 public RegistryFactory$Adaptive() { 224 } 225} 226 227// 创建 Registry, todo: 返回xxxRegistry 实例 228 @SuppressWarnings("unchecked") 229 private T createExtension(String name) { 230 Class<?> clazz = getExtensionClasses().get(name); 231 if (clazz == null) { 232 throw findException(name); 233 } 234 try { 235 T instance = (T) EXTENSION_INSTANCES.get(clazz); 236 if (instance == null) { 237 EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); 238 instance = (T) EXTENSION_INSTANCES.get(clazz); 239 } 240 injectExtension(instance); 241 Set<Class<?>> wrapperClasses = cachedWrapperClasses; 242 if (wrapperClasses != null && !wrapperClasses.isEmpty()) { 243 for (Class<?> wrapperClass : wrapperClasses) { 244 instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); 245 } 246 } 247 return instance; 248 } catch (Throwable t) { 249 throw new IllegalStateException("Extension instance(name: " + name + ", class: " + 250 type + ") could not be instantiated: " + t.getMessage(), t); 251 } 252 } 253 254 255 // com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol.refer, 256 @Override 257 public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException { 258 optimizeSerialization(url); 259 // create rpc invoker. 初始化调用远程方法 260 DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers); 261 invokers.add(invoker); 262 return invoker; 263 } 264 265 // 266 private ExchangeClient[] getClients(URL url) { 267 // whether to share connection 268 boolean service_share_connect = false; 269 int connections = url.getParameter(Constants.CONNECTIONS_KEY, 0); 270 // if not configured, connection is shared, otherwise, one connection for one service 271 if (connections == 0) { 272 service_share_connect = true; 273 connections = 1; 274 } 275 276 ExchangeClient[] clients = new ExchangeClient[connections]; 277 for (int i = 0; i < clients.length; i++) { 278 if (service_share_connect) { 279 clients[i] = getSharedClient(url); 280 } else { 281 clients[i] = initClient(url); 282 } 283 } 284 return clients; 285 }
// netty 连接远程服务过程

1// 初始化调用端,此处开始连接netty 2 private ExchangeClient initClient(URL url) { 3 4 // client type setting. 5 String str = url.getParameter(Constants.CLIENT_KEY, url.getParameter(Constants.SERVER_KEY, Constants.DEFAULT_REMOTING_CLIENT)); 6 7 url = url.addParameter(Constants.CODEC_KEY, DubboCodec.NAME); 8 // enable heartbeat by default 9 url = url.addParameterIfAbsent(Constants.HEARTBEAT_KEY, String.valueOf(Constants.DEFAULT_HEARTBEAT)); 10 11 // BIO is not allowed since it has severe performance issue. 12 if (str != null && str.length() > 0 && !ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str)) { 13 throw new RpcException("Unsupported client type: " + str + "," + 14 " supported client type is " + StringUtils.join(ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions(), " ")); 15 } 16 17 ExchangeClient client; 18 try { 19 // connection should be lazy 20 if (url.getParameter(Constants.LAZY_CONNECT_KEY, false)) { 21 client = new LazyConnectExchangeClient(url, requestHandler); 22 } else { 23 client = Exchangers.connect(url, requestHandler); 24 } 25 } catch (RemotingException e) { 26 throw new RpcException("Fail to create remoting client for service(" + url + "): " + e.getMessage(), e); 27 } 28 return client; 29 } 30 31 // com.alibaba.dubbo.remoting.exchange.Exchangers.connect 32 public static ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException { 33 if (url == null) { 34 throw new IllegalArgumentException("url == null"); 35 } 36 if (handler == null) { 37 throw new IllegalArgumentException("handler == null"); 38 } 39 url = url.addParameterIfAbsent(Constants.CODEC_KEY, "exchange"); 40 return getExchanger(url).connect(url, handler); 41 } 42 43 // com.alibaba.dubbo.remoting.Transporters.connect 44 public static Client connect(URL url, ChannelHandler... handlers) throws RemotingException { 45 if (url == null) { 46 throw new IllegalArgumentException("url == null"); 47 } 48 ChannelHandler handler; 49 if (handlers == null || handlers.length == 0) { 50 handler = new ChannelHandlerAdapter(); 51 } else if (handlers.length == 1) { 52 handler = handlers[0]; 53 } else { 54 handler = new ChannelHandlerDispatcher(handlers); 55 } 56 return getTransporter().connect(url, handler); 57 } 58 59// com.alibaba.dubbo.remoting.transport.netty 60public class NettyTransporter implements Transporter { 61 62 public static final String NAME = "netty"; 63 64 @Override 65 public Server bind(URL url, ChannelHandler listener) throws RemotingException { 66 return new NettyServer(url, listener); 67 } 68 69 @Override 70 public Client connect(URL url, ChannelHandler listener) throws RemotingException { 71 return new NettyClient(url, listener); 72 } 73 74} 75 76 77 // com.alibaba.dubbo.remoting.transport.AbstractClient 78 public AbstractClient(URL url, ChannelHandler handler) throws RemotingException { 79 super(url, handler); 80 81 send_reconnect = url.getParameter(Constants.SEND_RECONNECT_KEY, false); 82 83 shutdown_timeout = url.getParameter(Constants.SHUTDOWN_TIMEOUT_KEY, Constants.DEFAULT_SHUTDOWN_TIMEOUT); 84 85 // The default reconnection interval is 2s, 1800 means warning interval is 1 hour. 86 reconnect_warning_period = url.getParameter("reconnect.waring.period", 1800); 87 88 try { 89 // 模板方法,由子类实现 90 doOpen(); 91 } catch (Throwable t) { 92 close(); 93 throw new RemotingException(url.toInetSocketAddress(), null, 94 "Failed to start " + getClass().getSimpleName() + " " + NetUtils.getLocalAddress() 95 + " connect to the server " + getRemoteAddress() + ", cause: " + t.getMessage(), t); 96 } 97 try { 98 // connect. 99 connect(); 100 if (logger.isInfoEnabled()) { 101 logger.info("Start " + getClass().getSimpleName() + " " + NetUtils.getLocalAddress() + " connect to the server " + getRemoteAddress()); 102 } 103 } catch (RemotingException t) { 104 if (url.getParameter(Constants.CHECK_KEY, true)) { 105 close(); 106 throw t; 107 } else { 108 logger.warn("Failed to start " + getClass().getSimpleName() + " " + NetUtils.getLocalAddress() 109 + " connect to the server " + getRemoteAddress() + " (check == false, ignore and retry later!), cause: " + t.getMessage(), t); 110 } 111 } catch (Throwable t) { 112 close(); 113 throw new RemotingException(url.toInetSocketAddress(), null, 114 "Failed to start " + getClass().getSimpleName() + " " + NetUtils.getLocalAddress() 115 + " connect to the server " + getRemoteAddress() + ", cause: " + t.getMessage(), t); 116 } 117 118 executor = (ExecutorService) ExtensionLoader.getExtensionLoader(DataStore.class) 119 .getDefaultExtension().get(Constants.CONSUMER_SIDE, Integer.toString(url.getPort())); 120 ExtensionLoader.getExtensionLoader(DataStore.class) 121 .getDefaultExtension().remove(Constants.CONSUMER_SIDE, Integer.toString(url.getPort())); 122 } 123 // 将连接步骤固化,调用实现类的 doConnect 124 protected void connect() throws RemotingException { 125 connectLock.lock(); 126 try { 127 if (isConnected()) { 128 return; 129 } 130 initConnectStatusCheckCommand(); 131 doConnect(); 132 if (!isConnected()) { 133 throw new RemotingException(this, "Failed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " " 134 + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion() 135 + ", cause: Connect wait timeout: " + getTimeout() + "ms."); 136 } else { 137 if (logger.isInfoEnabled()) { 138 logger.info("Successed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " " 139 + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion() 140 + ", channel is " + this.getChannel()); 141 } 142 } 143 reconnect_count.set(0); 144 reconnect_error_log_flag.set(false); 145 } catch (RemotingException e) { 146 throw e; 147 } catch (Throwable e) { 148 throw new RemotingException(this, "Failed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " " 149 + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion() 150 + ", cause: " + e.getMessage(), e); 151 } finally { 152 connectLock.unlock(); 153 } 154 } 155 156 157// com.alibaba.dubbo.remoting.transport.netty.NettyClient. 158public class NettyClient extends AbstractClient { 159 160 private static final Logger logger = LoggerFactory.getLogger(NettyClient.class); 161 162 // ChannelFactory's closure has a DirectMemory leak, using static to avoid 163 // https://issues.jboss.org/browse/NETTY-424 164 private static final ChannelFactory channelFactory = new NioClientSocketChannelFactory(Executors.newCachedThreadPool(new NamedThreadFactory("NettyClientBoss", true)), 165 Executors.newCachedThreadPool(new NamedThreadFactory("NettyClientWorker", true)), 166 Constants.DEFAULT_IO_THREADS); 167 private ClientBootstrap bootstrap; 168 169 private volatile Channel channel; // volatile, please copy reference to use 170 171 public NettyClient(final URL url, final ChannelHandler handler) throws RemotingException { 172 super(url, wrapChannelHandler(url, handler)); 173 } 174 175 @Override 176 protected void doOpen() throws Throwable { 177 NettyHelper.setNettyLoggerFactory(); 178 bootstrap = new ClientBootstrap(channelFactory); 179 // config 180 // @see org.jboss.netty.channel.socket.SocketChannelConfig 181 bootstrap.setOption("keepAlive", true); 182 bootstrap.setOption("tcpNoDelay", true); 183 bootstrap.setOption("connectTimeoutMillis", getTimeout()); 184 final NettyHandler nettyHandler = new NettyHandler(getUrl(), this); 185 bootstrap.setPipelineFactory(new ChannelPipelineFactory() { 186 @Override 187 public ChannelPipeline getPipeline() { 188 NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyClient.this); 189 ChannelPipeline pipeline = Channels.pipeline(); 190 pipeline.addLast("decoder", adapter.getDecoder()); 191 pipeline.addLast("encoder", adapter.getEncoder()); 192 pipeline.addLast("handler", nettyHandler); 193 return pipeline; 194 } 195 }); 196 } 197 198 @Override 199 protected void doConnect() throws Throwable { 200 long start = System.currentTimeMillis(); 201 ChannelFuture future = bootstrap.connect(getConnectAddress()); 202 try { 203 boolean ret = future.awaitUninterruptibly(getConnectTimeout(), TimeUnit.MILLISECONDS); 204 205 if (ret && future.isSuccess()) { 206 Channel newChannel = future.getChannel(); 207 newChannel.setInterestOps(Channel.OP_READ_WRITE); 208 try { 209 // Close old channel 210 Channel oldChannel = NettyClient.this.channel; // copy reference 211 if (oldChannel != null) { 212 try { 213 if (logger.isInfoEnabled()) { 214 logger.info("Close old netty channel " + oldChannel + " on create new netty channel " + newChannel); 215 } 216 oldChannel.close(); 217 } finally { 218 NettyChannel.removeChannelIfDisconnected(oldChannel); 219 } 220 } 221 } finally { 222 if (NettyClient.this.isClosed()) { 223 try { 224 if (logger.isInfoEnabled()) { 225 logger.info("Close new netty channel " + newChannel + ", because the client closed."); 226 } 227 newChannel.close(); 228 } finally { 229 NettyClient.this.channel = null; 230 NettyChannel.removeChannelIfDisconnected(newChannel); 231 } 232 } else { 233 NettyClient.this.channel = newChannel; 234 } 235 } 236 } else if (future.getCause() != null) { 237 throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server " 238 + getRemoteAddress() + ", error message is:" + future.getCause().getMessage(), future.getCause()); 239 } else { 240 throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server " 241 + getRemoteAddress() + " client-side timeout " 242 + getConnectTimeout() + "ms (elapsed: " + (System.currentTimeMillis() - start) + "ms) from netty client " 243 + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion()); 244 } 245 } finally { 246 if (!isConnected()) { 247 future.cancel(); 248 } 249 } 250 } 251 252 @Override 253 protected void doDisConnect() throws Throwable { 254 try { 255 NettyChannel.removeChannelIfDisconnected(channel); 256 } catch (Throwable t) { 257 logger.warn(t.getMessage()); 258 } 259 } 260 261 @Override 262 protected void doClose() throws Throwable { 263 /*try { 264 bootstrap.releaseExternalResources(); 265 } catch (Throwable t) { 266 logger.warn(t.getMessage()); 267 }*/ 268 } 269 270 @Override 271 protected com.alibaba.dubbo.remoting.Channel getChannel() { 272 Channel c = channel; 273 if (c == null || !c.isConnected()) 274 return null; 275 return NettyChannel.getOrAddChannel(c, getUrl(), this); 276 } 277 278} 279 280 281 // com.alibaba.dubbo.rpc.proxy.wrapper.StubProxyFactoryWrapper.getProxy 282 @Override 283 @SuppressWarnings({"unchecked", "rawtypes"}) 284 public <T> T getProxy(Invoker<T> invoker) throws RpcException { 285 T proxy = proxyFactory.getProxy(invoker); 286 if (GenericService.class != invoker.getInterface()) { 287 String stub = invoker.getUrl().getParameter(Constants.STUB_KEY, invoker.getUrl().getParameter(Constants.LOCAL_KEY)); 288 if (ConfigUtils.isNotEmpty(stub)) { 289 Class<?> serviceType = invoker.getInterface(); 290 if (ConfigUtils.isDefault(stub)) { 291 if (invoker.getUrl().hasParameter(Constants.STUB_KEY)) { 292 stub = serviceType.getName() + "Stub"; 293 } else { 294 stub = serviceType.getName() + "Local"; 295 } 296 } 297 try { 298 Class<?> stubClass = ReflectUtils.forName(stub); 299 if (!serviceType.isAssignableFrom(stubClass)) { 300 throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + serviceType.getName()); 301 } 302 try { 303 Constructor<?> constructor = ReflectUtils.findConstructor(stubClass, serviceType); 304 proxy = (T) constructor.newInstance(new Object[]{proxy}); 305 //export stub service 306 URL url = invoker.getUrl(); 307 if (url.getParameter(Constants.STUB_EVENT_KEY, Constants.DEFAULT_STUB_EVENT)) { 308 url = url.addParameter(Constants.STUB_EVENT_METHODS_KEY, StringUtils.join(Wrapper.getWrapper(proxy.getClass()).getDeclaredMethodNames(), ",")); 309 url = url.addParameter(Constants.IS_SERVER_KEY, Boolean.FALSE.toString()); 310 try { 311 export(proxy, (Class) invoker.getInterface(), url); 312 } catch (Exception e) { 313 LOGGER.error("export a stub service error.", e); 314 } 315 } 316 } catch (NoSuchMethodException e) { 317 throw new IllegalStateException("No such constructor \"public " + stubClass.getSimpleName() + "(" + serviceType.getName() + ")\" in stub implementation class " + stubClass.getName(), e); 318 } 319 } catch (Throwable t) { 320 LOGGER.error("Failed to create stub implementation class " + stub + " in consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", cause: " + t.getMessage(), t); 321 // ignore 322 } 323 } 324 } 325 return proxy; 326 }
View Code
1/** 2 * AbstractProxyFactory com.alibaba.dubbo.rpc.proxy.AbstractProxyFactory 3 */ 4public abstract class AbstractProxyFactory implements ProxyFactory { 5 6 @Override 7 public <T> T getProxy(Invoker<T> invoker) throws RpcException { 8 return getProxy(invoker, false); 9 } 10 11 @Override 12 public <T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException { 13 Class<?>[] interfaces = null; 14 String config = invoker.getUrl().getParameter("interfaces"); 15 if (config != null && config.length() > 0) { 16 String[] types = Constants.COMMA_SPLIT_PATTERN.split(config); 17 if (types != null && types.length > 0) { 18 interfaces = new Class<?>[types.length + 2]; 19 interfaces[0] = invoker.getInterface(); 20 interfaces[1] = EchoService.class; 21 for (int i = 0; i < types.length; i++) { 22 interfaces[i + 1] = ReflectUtils.forName(types[i]); 23 } 24 } 25 } 26 if (interfaces == null) { 27 interfaces = new Class<?>[]{invoker.getInterface(), EchoService.class}; 28 } 29 30 if (!invoker.getInterface().equals(GenericService.class) && generic) { 31 int len = interfaces.length; 32 Class<?>[] temp = interfaces; 33 interfaces = new Class<?>[len + 1]; 34 System.arraycopy(temp, 0, interfaces, 0, len); 35 interfaces[len] = GenericService.class; 36 } 37 38 return getProxy(invoker, interfaces); 39 } 40 41 public abstract <T> T getProxy(Invoker<T> invoker, Class<?>[] types); 42 43} 44 45// com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory, 调用 wrapper 去处理 46public class JavassistProxyFactory extends AbstractProxyFactory { 47 48 @Override 49 @SuppressWarnings("unchecked") 50 public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) { 51 return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker)); 52 } 53 54 @Override 55 public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) { 56 // TODO Wrapper cannot handle this scenario correctly: the classname contains '$' 57 final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type); 58 return new AbstractProxyInvoker<T>(proxy, type, url) { 59 @Override 60 protected Object doInvoke(T proxy, String methodName, 61 Class<?>[] parameterTypes, 62 Object[] arguments) throws Throwable { 63 return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments); 64 } 65 }; 66 } 67 68} 69 70 // 保存调用路径 71 public static boolean initConsumerModel(String serviceName, ConsumerModel consumerModel) { 72 if (consumedServices.putIfAbsent(serviceName, consumerModel) != null) { 73 logger.warn("Already register the same consumer:" + serviceName); 74 return false; 75 } 76 return true; 77 }
// String hello = demoService.sayHello("world"); // call remote method,
// 启用该远程方法,其实是调用的一个代理类,动态生成
1/** 2"main@1" prio=5 tid=0x1 nid=NA runnable 3 java.lang.Thread.State: RUNNABLE 4 at com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler.invoke(InvokerInvocationHandler.java:38) 5 at com.alibaba.dubbo.common.bytecode.proxy0.sayHello(proxy0.java:-1) 6 at com.alibaba.dubbo.demo.consumer.Consumer.main(Consumer.java:35) 7*/ 8// 调用动态代理类的方法,其实为调用 InvocationHandler方法 9public class proxy0 implements DC, EchoService, DemoService { 10 public static Method[] methods; 11 private InvocationHandler handler; 12 13 public String sayHello(String var1) { 14 Object[] var2 = new Object[]{var1}; 15 Object var3 = this.handler.invoke(this, methods[0], var2); 16 return (String)var3; 17 } 18 19 public Object $echo(Object var1) { 20 Object[] var2 = new Object[]{var1}; 21 Object var3 = this.handler.invoke(this, methods[1], var2); 22 return (Object)var3; 23 } 24 25 public proxy0() { 26 } 27 28 public proxy0(InvocationHandler var1) { 29 this.handler = var1; 30 } 31} 32// com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler.invoke 方法,使用反射调用 invoker方法 33public class InvokerInvocationHandler implements InvocationHandler { 34 35 private final Invoker<?> invoker; 36 37 public InvokerInvocationHandler(Invoker<?> handler) { 38 this.invoker = handler; 39 } 40 41 @Override 42 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 43 String methodName = method.getName(); 44 Class<?>[] parameterTypes = method.getParameterTypes(); 45 if (method.getDeclaringClass() == Object.class) { 46 return method.invoke(invoker, args); 47 } 48 if ("toString".equals(methodName) && parameterTypes.length == 0) { 49 return invoker.toString(); 50 } 51 if ("hashCode".equals(methodName) && parameterTypes.length == 0) { 52 return invoker.hashCode(); 53 } 54 if ("equals".equals(methodName) && parameterTypes.length == 1) { 55 return invoker.equals(args[0]); 56 } 57 // 调用通用方法 58 return invoker.invoke(new RpcInvocation(method, args)).recreate(); 59 } 60 61} 62 63 64 // com.alibaba.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker. 65 @Override 66 public Result invoke(Invocation invocation) throws RpcException { 67 Result result = null; 68 69 String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim(); 70 if (value.length() == 0 || value.equalsIgnoreCase("false")) { 71 //no mock, 调用真实代理 72 result = this.invoker.invoke(invocation); 73 } else if (value.startsWith("force")) { 74 if (logger.isWarnEnabled()) { 75 logger.info("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + directory.getUrl()); 76 } 77 //force:direct mock 78 result = doMockInvoke(invocation, null); 79 } else { 80 //fail-mock 81 try { 82 result = this.invoker.invoke(invocation); 83 } catch (RpcException e) { 84 if (e.isBiz()) { 85 throw e; 86 } else { 87 if (logger.isWarnEnabled()) { 88 logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + directory.getUrl(), e); 89 } 90 result = doMockInvoke(invocation, e); 91 } 92 } 93 } 94 return result; 95 } 96 97 // com.alibaba.dubbo.rpc.cluster.support.AbstractClusterInvoker.invoke 98 @Override 99 public Result invoke(final Invocation invocation) throws RpcException { 100 checkWhetherDestroyed(); 101 LoadBalance loadbalance = null; 102 List<Invoker<T>> invokers = list(invocation); 103 if (invokers != null && !invokers.isEmpty()) { 104 // 获取负载均衡策略,默认为 random 105 loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl() 106 .getMethodParameter(RpcUtils.getMethodName(invocation), Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE)); 107 } 108 // 如果是异步调用,会先创建一个调用id,以便在需要的时候使用 109 RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation); 110 return doInvoke(invocation, invokers, loadbalance); 111 } 112 113 // 模板方法 114 protected abstract Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, 115 LoadBalance loadbalance) throws RpcException; 116 117// 快速失败 invoker 调用 118public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> { 119 120 private static final Logger logger = LoggerFactory.getLogger(FailoverClusterInvoker.class); 121 122 public FailoverClusterInvoker(Directory<T> directory) { 123 super(directory); 124 } 125 126 @Override 127 @SuppressWarnings({"unchecked", "rawtypes"}) 128 public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException { 129 List<Invoker<T>> copyinvokers = invokers; 130 checkInvokers(copyinvokers, invocation); 131 int len = getUrl().getMethodParameter(invocation.getMethodName(), Constants.RETRIES_KEY, Constants.DEFAULT_RETRIES) + 1; 132 if (len <= 0) { 133 len = 1; 134 } 135 // retry loop. 136 RpcException le = null; // last exception. 137 List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyinvokers.size()); // invoked invokers. 138 Set<String> providers = new HashSet<String>(len); 139 for (int i = 0; i < len; i++) { 140 //Reselect before retry to avoid a change of candidate `invokers`. 141 //NOTE: if `invokers` changed, then `invoked` also lose accuracy. 142 if (i > 0) { 143 checkWhetherDestroyed(); 144 copyinvokers = list(invocation); 145 // check again 146 checkInvokers(copyinvokers, invocation); 147 } 148 // 调用AbstractClusterInvoker的负载均衡算法 149 Invoker<T> invoker = select(loadbalance, invocation, copyinvokers, invoked); 150 invoked.add(invoker); 151 RpcContext.getContext().setInvokers((List) invoked); 152 try { 153 Result result = invoker.invoke(invocation); 154 if (le != null && logger.isWarnEnabled()) { 155 logger.warn("Although retry the method " + invocation.getMethodName() 156 + " in the service " + getInterface().getName() 157 + " was successful by the provider " + invoker.getUrl().getAddress() 158 + ", but there have been failed providers " + providers 159 + " (" + providers.size() + "/" + copyinvokers.size() 160 + ") from the registry " + directory.getUrl().getAddress() 161 + " on the consumer " + NetUtils.getLocalHost() 162 + " using the dubbo version " + Version.getVersion() + ". Last error is: " 163 + le.getMessage(), le); 164 } 165 return result; 166 } catch (RpcException e) { 167 if (e.isBiz()) { // biz exception. 168 throw e; 169 } 170 le = e; 171 } catch (Throwable e) { 172 le = new RpcException(e.getMessage(), e); 173 } finally { 174 providers.add(invoker.getUrl().getAddress()); 175 } 176 } 177 throw new RpcException(le != null ? le.getCode() : 0, "Failed to invoke the method " 178 + invocation.getMethodName() + " in the service " + getInterface().getName() 179 + ". Tried " + len + " times of the providers " + providers 180 + " (" + providers.size() + "/" + copyinvokers.size() 181 + ") from the registry " + directory.getUrl().getAddress() 182 + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version " 183 + Version.getVersion() + ". Last error is: " 184 + (le != null ? le.getMessage() : ""), le != null && le.getCause() != null ? le.getCause() : le); 185 } 186 187}
// 负载均衡
1// 2 protected Invoker<T> select(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException { 3 if (invokers == null || invokers.isEmpty()) 4 return null; 5 String methodName = invocation == null ? "" : invocation.getMethodName(); 6 7 boolean sticky = invokers.get(0).getUrl().getMethodParameter(methodName, Constants.CLUSTER_STICKY_KEY, Constants.DEFAULT_CLUSTER_STICKY); 8 { 9 //ignore overloaded method 10 if (stickyInvoker != null && !invokers.contains(stickyInvoker)) { 11 stickyInvoker = null; 12 } 13 //ignore concurrency problem 14 if (sticky && stickyInvoker != null && (selected == null || !selected.contains(stickyInvoker))) { 15 if (availablecheck && stickyInvoker.isAvailable()) { 16 return stickyInvoker; 17 } 18 } 19 } 20 Invoker<T> invoker = doSelect(loadbalance, invocation, invokers, selected); 21 22 if (sticky) { 23 stickyInvoker = invoker; 24 } 25 return invoker; 26 } 27 28 private Invoker<T> doSelect(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException { 29 if (invokers == null || invokers.isEmpty()) 30 return null; 31 // 如果只有一个提供者,就不用负载均衡了 32 if (invokers.size() == 1) 33 return invokers.get(0); 34 if (loadbalance == null) { 35 loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(Constants.DEFAULT_LOADBALANCE); 36 } 37 Invoker<T> invoker = loadbalance.select(invokers, getUrl(), invocation); 38 39 //If the `invoker` is in the `selected` or invoker is unavailable && availablecheck is true, reselect. 40 if ((selected != null && selected.contains(invoker)) 41 || (!invoker.isAvailable() && getUrl() != null && availablecheck)) { 42 try { 43 Invoker<T> rinvoker = reselect(loadbalance, invocation, invokers, selected, availablecheck); 44 if (rinvoker != null) { 45 invoker = rinvoker; 46 } else { 47 //Check the index of current selected invoker, if it's not the last one, choose the one at index+1. 48 int index = invokers.indexOf(invoker); 49 try { 50 //Avoid collision 51 invoker = index < invokers.size() - 1 ? invokers.get(index + 1) : invokers.get(0); 52 } catch (Exception e) { 53 logger.warn(e.getMessage() + " may because invokers list dynamic change, ignore.", e); 54 } 55 } 56 } catch (Throwable t) { 57 logger.error("cluster reselect fail reason is :" + t.getMessage() + " if can not solve, you can set cluster.availablecheck=false in url", t); 58 } 59 } 60 return invoker; 61 } 62 63// 随机负载均衡策略的选择算法 64public class RandomLoadBalance extends AbstractLoadBalance { 65 66 public static final String NAME = "random"; 67 68 private final Random random = new Random(); 69 70 @Override 71 protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) { 72 int length = invokers.size(); // Number of invokers 73 int totalWeight = 0; // The sum of weights 74 boolean sameWeight = true; // Every invoker has the same weight? 75 for (int i = 0; i < length; i++) { 76 int weight = getWeight(invokers.get(i), invocation); 77 totalWeight += weight; // Sum 78 if (sameWeight && i > 0 79 && weight != getWeight(invokers.get(i - 1), invocation)) { 80 sameWeight = false; 81 } 82 } 83 if (totalWeight > 0 && !sameWeight) { 84 // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeight. 85 int offset = random.nextInt(totalWeight); 86 // Return a invoker based on the random value. 87 for (int i = 0; i < length; i++) { 88 offset -= getWeight(invokers.get(i), invocation); 89 if (offset < 0) { 90 return invokers.get(i); 91 } 92 } 93 } 94 // If all invokers have the same weight value or totalWeight=0, return evenly. 95 return invokers.get(random.nextInt(length)); 96 } 97 98} 99 100 // filter 过滤器调用 101 private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) { 102 Invoker<T> last = invoker; 103 List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group); 104 if (!filters.isEmpty()) { 105 for (int i = filters.size() - 1; i >= 0; i--) { 106 final Filter filter = filters.get(i); 107 final Invoker<T> next = last; 108 last = new Invoker<T>() { 109 110 @Override 111 public Class<T> getInterface() { 112 return invoker.getInterface(); 113 } 114 115 @Override 116 public URL getUrl() { 117 return invoker.getUrl(); 118 } 119 120 @Override 121 public boolean isAvailable() { 122 return invoker.isAvailable(); 123 } 124 125 @Override 126 public Result invoke(Invocation invocation) throws RpcException { 127 return filter.invoke(next, invocation); 128 } 129 130 @Override 131 public void destroy() { 132 invoker.destroy(); 133 } 134 135 @Override 136 public String toString() { 137 return invoker.toString(); 138 } 139 }; 140 } 141 } 142 return last; 143 }
// filter调用链
1@Activate(group = Constants.CONSUMER, order = -10000) 2public class ConsumerContextFilter implements Filter { 3 4 @Override 5 public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { 6 RpcContext.getContext() 7 .setInvoker(invoker) 8 .setInvocation(invocation) 9 .setLocalAddress(NetUtils.getLocalHost(), 0) 10 .setRemoteAddress(invoker.getUrl().getHost(), 11 invoker.getUrl().getPort()); 12 if (invocation instanceof RpcInvocation) { 13 ((RpcInvocation) invocation).setInvoker(invoker); 14 } 15 try { 16 // 同步异步调用 17 RpcResult result = (RpcResult) invoker.invoke(invocation); 18 RpcContext.getServerContext().setAttachments(result.getAttachments()); 19 return result; 20 } finally { 21 RpcContext.getContext().clearAttachments(); 22 } 23 } 24 25} 26 27 // com.alibaba.dubbo.rpc.protocol.dubbo.filter.FutureFilter.invoke 28@Activate(group = Constants.CONSUMER) 29public class FutureFilter implements Filter { 30 31 protected static final Logger logger = LoggerFactory.getLogger(FutureFilter.class); 32 33 @Override 34 public Result invoke(final Invoker<?> invoker, final Invocation invocation) throws RpcException { 35 final boolean isAsync = RpcUtils.isAsync(invoker.getUrl(), invocation); 36 37 fireInvokeCallback(invoker, invocation); 38 // need to configure if there's return value before the invocation in order to help invoker to judge if it's 39 // necessary to return future. 40 // 此处为链式调用,先调用 monitor, 再调用具体的方法 DubboInvoker 41 Result result = invoker.invoke(invocation); 42 if (isAsync) { 43 // 如果url参数中标识为异步调用,则执行异步调用 44 asyncCallback(invoker, invocation); 45 } else { 46 // 否则同步调用 47 syncCallback(invoker, invocation, result); 48 } 49 return result; 50 } 51 52 private void syncCallback(final Invoker<?> invoker, final Invocation invocation, final Result result) { 53 if (result.hasException()) { 54 fireThrowCallback(invoker, invocation, result.getException()); 55 } else { 56 fireReturnCallback(invoker, invocation, result.getValue()); 57 } 58 } 59 60 private void asyncCallback(final Invoker<?> invoker, final Invocation invocation) { 61 Future<?> f = RpcContext.getContext().getFuture(); 62 if (f instanceof FutureAdapter) { 63 ResponseFuture future = ((FutureAdapter<?>) f).getFuture(); 64 future.setCallback(new ResponseCallback() { 65 @Override 66 public void done(Object rpcResult) { 67 if (rpcResult == null) { 68 logger.error(new IllegalStateException("invalid result value : null, expected " + Result.class.getName())); 69 return; 70 } 71 ///must be rpcResult 72 if (!(rpcResult instanceof Result)) { 73 logger.error(new IllegalStateException("invalid result type :" + rpcResult.getClass() + ", expected " + Result.class.getName())); 74 return; 75 } 76 Result result = (Result) rpcResult; 77 // 结果通知回调 78 if (result.hasException()) { 79 fireThrowCallback(invoker, invocation, result.getException()); 80 } else { 81 fireReturnCallback(invoker, invocation, result.getValue()); 82 } 83 } 84 85 @Override 86 public void caught(Throwable exception) { 87 fireThrowCallback(invoker, invocation, exception); 88 } 89 }); 90 } 91 } 92 93 private void fireInvokeCallback(final Invoker<?> invoker, final Invocation invocation) { 94 final Method onInvokeMethod = (Method) StaticContext.getSystemContext().get(StaticContext.getKey(invoker.getUrl(), invocation.getMethodName(), Constants.ON_INVOKE_METHOD_KEY)); 95 final Object onInvokeInst = StaticContext.getSystemContext().get(StaticContext.getKey(invoker.getUrl(), invocation.getMethodName(), Constants.ON_INVOKE_INSTANCE_KEY)); 96 97 if (onInvokeMethod == null && onInvokeInst == null) { 98 return; 99 } 100 if (onInvokeMethod == null || onInvokeInst == null) { 101 throw new IllegalStateException("service:" + invoker.getUrl().getServiceKey() + " has a onreturn callback config , but no such " + (onInvokeMethod == null ? "method" : "instance") + " found. url:" + invoker.getUrl()); 102 } 103 if (!onInvokeMethod.isAccessible()) { 104 onInvokeMethod.setAccessible(true); 105 } 106 107 Object[] params = invocation.getArguments(); 108 try { 109 onInvokeMethod.invoke(onInvokeInst, params); 110 } catch (InvocationTargetException e) { 111 fireThrowCallback(invoker, invocation, e.getTargetException()); 112 } catch (Throwable e) { 113 fireThrowCallback(invoker, invocation, e); 114 } 115 } 116 117 private void fireReturnCallback(final Invoker<?> invoker, final Invocation invocation, final Object result) { 118 final Method onReturnMethod = (Method) StaticContext.getSystemContext().get(StaticContext.getKey(invoker.getUrl(), invocation.getMethodName(), Constants.ON_RETURN_METHOD_KEY)); 119 final Object onReturnInst = StaticContext.getSystemContext().get(StaticContext.getKey(invoker.getUrl(), invocation.getMethodName(), Constants.ON_RETURN_INSTANCE_KEY)); 120 121 //not set onreturn callback, 回调设置了 onreturn 方法 122 if (onReturnMethod == null && onReturnInst == null) { 123 return; 124 } 125 126 if (onReturnMethod == null || onReturnInst == null) { 127 throw new IllegalStateException("service:" + invoker.getUrl().getServiceKey() + " has a onreturn callback config , but no such " + (onReturnMethod == null ? "method" : "instance") + " found. url:" + invoker.getUrl()); 128 } 129 if (!onReturnMethod.isAccessible()) { 130 onReturnMethod.setAccessible(true); 131 } 132 133 Object[] args = invocation.getArguments(); 134 Object[] params; 135 Class<?>[] rParaTypes = onReturnMethod.getParameterTypes(); 136 if (rParaTypes.length > 1) { 137 if (rParaTypes.length == 2 && rParaTypes[1].isAssignableFrom(Object[].class)) { 138 params = new Object[2]; 139 params[0] = result; 140 params[1] = args; 141 } else { 142 params = new Object[args.length + 1]; 143 params[0] = result; 144 System.arraycopy(args, 0, params, 1, args.length); 145 } 146 } else { 147 params = new Object[]{result}; 148 } 149 try { 150 onReturnMethod.invoke(onReturnInst, params); 151 } catch (InvocationTargetException e) { 152 fireThrowCallback(invoker, invocation, e.getTargetException()); 153 } catch (Throwable e) { 154 fireThrowCallback(invoker, invocation, e); 155 } 156 } 157 158 private void fireThrowCallback(final Invoker<?> invoker, final Invocation invocation, final Throwable exception) { 159 final Method onthrowMethod = (Method) StaticContext.getSystemContext().get(StaticContext.getKey(invoker.getUrl(), invocation.getMethodName(), Constants.ON_THROW_METHOD_KEY)); 160 final Object onthrowInst = StaticContext.getSystemContext().get(StaticContext.getKey(invoker.getUrl(), invocation.getMethodName(), Constants.ON_THROW_INSTANCE_KEY)); 161 162 //onthrow callback not configured 163 if (onthrowMethod == null && onthrowInst == null) { 164 return; 165 } 166 if (onthrowMethod == null || onthrowInst == null) { 167 throw new IllegalStateException("service:" + invoker.getUrl().getServiceKey() + " has a onthrow callback config , but no such " + (onthrowMethod == null ? "method" : "instance") + " found. url:" + invoker.getUrl()); 168 } 169 if (!onthrowMethod.isAccessible()) { 170 onthrowMethod.setAccessible(true); 171 } 172 Class<?>[] rParaTypes = onthrowMethod.getParameterTypes(); 173 if (rParaTypes[0].isAssignableFrom(exception.getClass())) { 174 try { 175 Object[] args = invocation.getArguments(); 176 Object[] params; 177 178 if (rParaTypes.length > 1) { 179 if (rParaTypes.length == 2 && rParaTypes[1].isAssignableFrom(Object[].class)) { 180 params = new Object[2]; 181 params[0] = exception; 182 params[1] = args; 183 } else { 184 params = new Object[args.length + 1]; 185 params[0] = exception; 186 System.arraycopy(args, 0, params, 1, args.length); 187 } 188 } else { 189 params = new Object[]{exception}; 190 } 191 onthrowMethod.invoke(onthrowInst, params); 192 } catch (Throwable e) { 193 logger.error(invocation.getMethodName() + ".call back method invoke error . callback method :" + onthrowMethod + ", url:" + invoker.getUrl(), e); 194 } 195 } else { 196 logger.error(invocation.getMethodName() + ".call back method invoke error . callback method :" + onthrowMethod + ", url:" + invoker.getUrl(), exception); 197 } 198 } 199} 200
//
1// 调用具体的远程方法类 2public class DubboInvoker<T> extends AbstractInvoker<T> { 3 4 private final ExchangeClient[] clients; 5 6 private final AtomicPositiveInteger index = new AtomicPositiveInteger(); 7 8 private final String version; 9 10 private final ReentrantLock destroyLock = new ReentrantLock(); 11 12 private final Set<Invoker<?>> invokers; 13 14 public DubboInvoker(Class<T> serviceType, URL url, ExchangeClient[] clients) { 15 this(serviceType, url, clients, null); 16 } 17 18 public DubboInvoker(Class<T> serviceType, URL url, ExchangeClient[] clients, Set<Invoker<?>> invokers) { 19 super(serviceType, url, new String[]{Constants.INTERFACE_KEY, Constants.GROUP_KEY, Constants.TOKEN_KEY, Constants.TIMEOUT_KEY}); 20 this.clients = clients; 21 // get version. 22 this.version = url.getParameter(Constants.VERSION_KEY, "0.0.0"); 23 this.invokers = invokers; 24 } 25 26 // 实际调用 27 @Override 28 protected Result doInvoke(final Invocation invocation) throws Throwable { 29 RpcInvocation inv = (RpcInvocation) invocation; 30 final String methodName = RpcUtils.getMethodName(invocation); 31 inv.setAttachment(Constants.PATH_KEY, getUrl().getPath()); 32 inv.setAttachment(Constants.VERSION_KEY, version); 33 34 ExchangeClient currentClient; 35 if (clients.length == 1) { 36 currentClient = clients[0]; 37 } else { 38 currentClient = clients[index.getAndIncrement() % clients.length]; 39 } 40 try { 41 boolean isAsync = RpcUtils.isAsync(getUrl(), invocation); 42 boolean isOneway = RpcUtils.isOneway(getUrl(), invocation); 43 int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT); 44 if (isOneway) { 45 // 单向调用,立马返回 46 boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false); 47 currentClient.send(inv, isSent); 48 RpcContext.getContext().setFuture(null); 49 return new RpcResult(); 50 } else if (isAsync) { 51 // 异步调用,立马返回,后续接收结果 52 ResponseFuture future = currentClient.request(inv, timeout); 53 RpcContext.getContext().setFuture(new FutureAdapter<Object>(future)); 54 return new RpcResult(); 55 } else { 56 // 一般调用都是这个,同步+超时调用 57 RpcContext.getContext().setFuture(null); 58 return (Result) currentClient.request(inv, timeout).get(); 59 } 60 } catch (TimeoutException e) { 61 throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e); 62 } catch (RemotingException e) { 63 throw new RpcException(RpcException.NETWORK_EXCEPTION, "Failed to invoke remote method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e); 64 } 65 } 66 67 @Override 68 public boolean isAvailable() { 69 if (!super.isAvailable()) 70 return false; 71 for (ExchangeClient client : clients) { 72 if (client.isConnected() && !client.hasAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY)) { 73 //cannot write == not Available ? 74 return true; 75 } 76 } 77 return false; 78 } 79 80}
dubbo还是个不错的rpc框架了,在其多年不维护的情况仍然拥有大量的用户,自有其道理。
罗列其中几个比较有借鉴意义的地方:
1. 面向接口编程,全局使用代理模式进行rpc方法调用,使rpc访问更加透明如本地方法;
2. 使用模板方法模式,由抽象父类实现框架式方法,调用由子类实现其中某个特有功能,更好的封装;
3. 使用外观模式,将多个实现不一的类,统一暴露为一个统一的接口,更易于使用方的调用;
4. 使用字节码生成技术,动态生成各种代理类,使实现更灵活;
5. 懒加载的应用,单例模式的应用;
6. 借助spring进行bean管理,更符合市场需要;
7. 使用观察者模式,进行提供者消费者通知,使变更能够周知需要的监听者;
8. filter的应用,责任链模式,更易于扩展辅助功能;
9. 使用策略模式,使多个负载均衡统一调度,这也大量在SPI机制中体现;