Dubbo服务调用动态选择版本.docx_第1页
Dubbo服务调用动态选择版本.docx_第2页
Dubbo服务调用动态选择版本.docx_第3页
Dubbo服务调用动态选择版本.docx_第4页
Dubbo服务调用动态选择版本.docx_第5页
已阅读5页,还剩25页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Dubbo服务调用动态选择版本问题说明Dubbo是阿里巴巴SOA服务化治理方案的核心框架,致力于高性能和透明化的远程服务调用方案和服务治理方案。官方文档见:http:/alibaba.github.io/dubbo-doc-static/Home-zh.htm。Dubbo可以和Spring无缝集成,示例如下:1. 服务提供端Provider.xmlHelloServiceImpl.javapackage vider;import org.springframework.stereotype.Service;import f.IHelloService;Service(helloService)public class HelloServiceImpl implements IHelloServiceOverridepublic String sayHello(String name) return Hello +name;2. 客户端调用Consumer.xml服务端 dubbo:service 和 客户端 dubbo:reference 分别有1个version属性。说明:服务端发布provider时可以为服务分配1个版本号,客户端调用服务端的provider时,需要指定调用哪1个版本的服务。项目实施过程碰到一些问题:1. version属性在xml文件中配置,意味着服务端升级版本号,客户端也要相应修改配置文件并重启应用。2. 项目中存在灰度发布的要求,服务端的provider可能同时存在多个版本,客户端根据用户工号来选择调用哪个版本,比如指定一批测试工号,来测试新版本的provider。整个发布过程需要不重启web应用实现无缝切换,客户端在xml文件中指定版本号就显得不够,dubbo需要支持客户端自行实现版本选择规则,根据规则决定调用相应版本的provider。本文描述了如何重载dubbo的部分代码实现客户端版本规则。实现思路通过分析dubbo 2.5.3 的源码, 标签对应的类是 com.alibaba.dubbo.config.spring.ReferenceBean的version属性被写到ReferenceBean的version属性中,可以通过ReferenceBean.getVersion() 来获取配置文件中指定的远程服务的版本号。该类是工厂类,实现 org.springframework.beans.factory.FactoryBean,第64行代码public Object getObject() throws Exception return get(); 返回IHelloService的代理对象,调用该对象的sayHello方法即可调用远程dubbo服务,远程服务的版本号由ReferenceBean的version属性决定。本文的实现方法是重载 ReferenceBean 的get() 方法,使用javassist技术构造一个新的代理,根据用户自定义的规则来调用相应版本的dubbo服务。实现方法重写ReferenceBeanpackage com.telecom.dubbo.extend;import java.lang.reflect.Method;import java.util.concurrent.ConcurrentHashMap;import org.springframework.context.ApplicationContext;import com.alibaba.dubbo.config.ReferenceConfig;import com.alibaba.dubbo.config.annotation.Reference;import xy.MethodHandler;import xy.ProxyFactory;import xy.ProxyObject;/* * 自定义的referencebean,该类会创建动态代理,运行时根据上下文的版本号选择远程服务 * author wuchangzheng * * param */public class ReferenceBean extends com.alibaba.dubbo.config.spring.ReferenceBean implements Cloneableprivate static final long serialVersionUID = 8383612147446385736L;private transient T proxy;/代理private transient IVersionDesider versionDesider;/版本决定器private transient ApplicationContext applicationContext;private transient ReferenceBean self_=this;private transient ConcurrentHashMap versionMap = new ConcurrentHashMap();private transient final String DEFAULT_VERSION=DEFAULT_VERSION;SuppressWarnings( all)public void setApplicationContext(ApplicationContext applicationContext)super.setApplicationContext(applicationContext);this.applicationContext=applicationContext;SuppressWarnings( all) public void afterPropertiesSet() throws Exceptionsuper.afterPropertiesSet();tryversionDesider=applicationContext.getBean(IVersionDesider.class);/从上下文中查找IVersionDesider实现,该实现代表用户自定义版本规则catch(Exception ex)versionDesider = null;proxy=getVersionDecideProxy();/创建代理对象/* * * return * throws ClassNotFoundException * throws InstantiationException * throws IllegalAccessException */SuppressWarnings( all)private T getVersionDecideProxy() throws ClassNotFoundException, InstantiationException, IllegalAccessException/ 创建代理工厂 ProxyFactory proxyFactory = new ProxyFactory(); Class interfaces=Class.forName(this.getInterface(); proxyFactory.setInterfaces(interfaces); / 创建代理类型的Class Class proxyClass = proxyFactory.createClass(); T proxy = (T) proxyClass.newInstance(); (ProxyObject) proxy).setHandler(new MethodHandler() Override public T invoke(Object self, Method thisMethod, Method proceed, Object args) throws Throwable T target = null; String version=DEFAULT_VERSION; if (versionDesider!=null) version=versionDesider.desideVersion(self_); if (version=null) version=DEFAULT_VERSION; ReferenceConfig config =null; synchronized(self_) config=versionMap.get(version); if (config=null) config=(ReferenceConfig)self_.clone(); config.setVersion(version); config.setCheck(false);/ versionMap.put(version, config); target = (T)config.get(); T retObj = (T)thisMethod.invoke(target, args); return retObj; ); return proxy;public Object getObject() throws Exception return proxy; 重载dubbo命名空间解析器/* * Copyright 1999-2011 Alibaba Group. * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * /licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.telecom.dubbo.extend;import org.springframework.beans.factory.xml.NamespaceHandlerSupport;import mon.Version;import com.alibaba.dubbo.config.ApplicationConfig;import com.alibaba.dubbo.config.ConsumerConfig;import com.alibaba.dubbo.config.ModuleConfig;import com.alibaba.dubbo.config.MonitorConfig;import com.alibaba.dubbo.config.ProtocolConfig;import com.alibaba.dubbo.config.ProviderConfig;import com.alibaba.dubbo.config.RegistryConfig;import com.alibaba.dubbo.config.spring.AnnotationBean;import com.telecom.dubbo.extend.ReferenceBean;import com.alibaba.dubbo.config.spring.ServiceBean;/* * DubboNamespaceHandler * * author william.liangf * export */public class DubboNamespaceHandler extends NamespaceHandlerSupport static Version.checkDuplicate(DubboNamespaceHandler.class);public void init() registerBeanDefinitionParser(application, new DubboBeanDefinitionParser(ApplicationConfig.class, true); registerBeanDefinitionParser(module, new DubboBeanDefinitionParser(ModuleConfig.class, true); registerBeanDefinitionParser(registry, new DubboBeanDefinitionParser(RegistryConfig.class, true); registerBeanDefinitionParser(monitor, new DubboBeanDefinitionParser(MonitorConfig.class, true); registerBeanDefinitionParser(provider, new DubboBeanDefinitionParser(ProviderConfig.class, true); registerBeanDefinitionParser(consumer, new DubboBeanDefinitionParser(ConsumerConfig.class, true); registerBeanDefinitionParser(protocol, new DubboBeanDefinitionParser(ProtocolConfig.class, true); registerBeanDefinitionParser(service, new DubboBeanDefinitionParser(ServiceBean.class, true); registerBeanDefinitionParser(reference, new DubboBeanDefinitionParser(ReferenceBean.class, false); registerBeanDefinitionParser(annotation, new DubboBeanDefinitionParser(AnnotationBean.class, true); /* * Copyright 1999-2011 Alibaba Group. * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * /licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.telecom.dubbo.extend;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.util.Date;import java.util.HashSet;import java.util.Set;import java.util.regex.Pattern;import org.springframework.beans.PropertyValue;import org.springframework.beans.factory.config.BeanDefinition;import org.springframework.beans.factory.config.BeanDefinitionHolder;import org.springframework.beans.factory.config.RuntimeBeanReference;import org.springframework.beans.factory.config.TypedStringValue;import org.springframework.beans.factory.support.ManagedList;import org.springframework.beans.factory.support.ManagedMap;import org.springframework.beans.factory.support.RootBeanDefinition;import org.springframework.beans.factory.xml.BeanDefinitionParser;import org.springframework.beans.factory.xml.ParserContext;import org.w3c.dom.Element;import org.w3c.dom.NamedNodeMap;import org.w3c.dom.Node;import org.w3c.dom.NodeList;import mon.Constants;import mon.extension.ExtensionLoader;import mon.logger.Logger;import mon.logger.LoggerFactory;import mon.utils.ReflectUtils;import mon.utils.StringUtils;import com.alibaba.dubbo.config.ArgumentConfig;import com.alibaba.dubbo.config.ConsumerConfig;import com.alibaba.dubbo.config.MethodConfig;import com.alibaba.dubbo.config.MonitorConfig;import com.alibaba.dubbo.config.ProtocolConfig;import com.alibaba.dubbo.config.ProviderConfig;import com.alibaba.dubbo.config.RegistryConfig;import com.telecom.dubbo.extend.ReferenceBean;import com.alibaba.dubbo.config.spring.ServiceBean;import com.alibaba.dubbo.rpc.Protocol;/* * AbstractBeanDefinitionParser * * author william.liangf * export */public class DubboBeanDefinitionParser implements BeanDefinitionParser private static final Logger logger = LoggerFactory.getLogger(DubboBeanDefinitionParser.class); private final Class beanClass; private final boolean required; public DubboBeanDefinitionParser(Class beanClass, boolean required) this.beanClass = beanClass; this.required = required; public BeanDefinition parse(Element element, ParserContext parserContext) return parse(element, parserContext, beanClass, required); SuppressWarnings(unchecked) private static BeanDefinition parse(Element element, ParserContext parserContext, Class beanClass, boolean required) RootBeanDefinition beanDefinition = new RootBeanDefinition(); beanDefinition.setBeanClass(beanClass); beanDefinition.setLazyInit(false); String id = element.getAttribute(id); if (id = null | id.length() = 0) & required) String generatedBeanName = element.getAttribute(name); if (generatedBeanName = null | generatedBeanName.length() = 0) if (ProtocolConfig.class.equals(beanClass) generatedBeanName = dubbo; else generatedBeanName = element.getAttribute(interface); if (generatedBeanName = null | generatedBeanName.length() = 0) generatedBeanName = beanClass.getName(); id = generatedBeanName; int counter = 2; while(parserContext.getRegistry().containsBeanDefinition(id) id = generatedBeanName + (counter +); if (id != null & id.length() 0) if (parserContext.getRegistry().containsBeanDefinition(id) throw new IllegalStateException(Duplicate spring bean id + id); parserContext.getRegistry().registerBeanDefinition(id, beanDefinition); beanDefinition.getPropertyValues().addPropertyValue(id, id); if (ProtocolConfig.class.equals(beanClass) for (String name : parserContext.getRegistry().getBeanDefinitionNames() BeanDefinition definition = parserContext.getRegistry().getBeanDefinition(name); PropertyValue property = definition.getPropertyValues().getPropertyValue(protocol); if (property != null) Object value = property.getValue(); if (value instanceof ProtocolConfig & id.equals(ProtocolConfig) value).getName() definition.getPropertyValues().addPropertyValue(protocol, new RuntimeBeanReference(id); else if (ServiceBean.class.equals(beanClass) String className = element.getAttribute(class); if(className != null & className.length() 0) RootBeanDefinition classDefinition = new RootBeanDefinition(); classDefinition.setBeanClass(ReflectUtils.forName(className); classDefinition.setLazyInit(false); parseProperties(element.getChildNodes(), classDefinition); beanDefinition.getPropertyValues().addPropertyValue(ref, new BeanDefinitionHolder(classDefinition, id + Impl); else if (ProviderConfig.class.equals(beanClass) parseNested(element, parserContext, ServiceBean.class, true, service, provider, id, beanDefinition); else if (ConsumerConfig.class.equals(beanClass) parseNested(element, parserContext, ReferenceBean.class, false, reference, consumer, id, beanDefinition); Set props = new HashSet(); ManagedMap parameters = null; for (Method setter : beanClass.getMethods() String name = setter.getName(); if (name.length() 3 & name.startsWith(set) & Modifier.isPublic(setter.getModifiers() & setter.getParameterTypes().length = 1) Class type = setter.getParameterTypes()0; String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() + name.substring(4), -); props.add(property); Method getter = null; try getter = beanClass.getMethod(get + name.substring(3), new Class0); catch (NoSuchMethodException e) try getter = beanClass.getMethod(is + name.substring(3), new Class0); catch (NoSuchMethodException e2) if (getter = null | ! Modifier.isPublic(getter.getModifiers() | ! type.equals(getter.getReturnType() continue; if (parameters.equals(property) parameters = parseParameters(element.getChildNodes(), beanDefinition); else if (methods.equals(property) parseMethods(id, element.getChildNodes(), beanDefinition, parserContext); else if (arguments.equals(property) parseArguments(id, element.getChildNodes(), beanDefinition, parserContext); else String value = element.getAttribute(property); if (value != null) value = value.trim(); if (value.length() 0) if (registry.equals(property) & RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(value) RegistryConfig registryConfig = new RegistryConfig(); registryConfig.setAddress(RegistryConfig.NO_AVAILABLE); beanDefinition.getPropertyValues().addPropertyValue(property, registryConfig); else if (registry.equals(property) & value.indexOf(,) !=

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论