dubbo和sofa相关分析和积累

    技术2023-07-27  76

    dubbo知识累计

    官网文档:http://dubbo.apache.org/zh-cn/docs/user/configuration/properties.html

    1 dubbo接口测试

    1)使用telnet连接对应的dubbo服务,telnet xxip port(服务端dubbo端口);

    2 )invoke com.xx.method({jsonstr})

    2.查看zookeeper服务中注册的dubbo服务

    1.进入到dubbo服务的物理机,然后ps -ef | grep zookeeper 查看到zookeeper的路径

    2.进入路径后,bash zkCli.sh,这样就能进入zk服务l

    3.查看providers ls /dubbo/xx类/providers  查看comsumer ls /dubbo/xx类/consumers

    3 dubbo配置

    注意:如果在classpath下有超过一个dubbo.properties文件,比如,两个jar包都各自包含了dubbo.properties,dubbo将随机选择一个加载,并且打印错误日志。

    dubbo.application.name=xx

    dubbo.registry.protocol=zookeeper

    dubbo.registry.address=zookeeper://xxip:port

    dubbo.protocol.port=3222 //dubbo服务调用接口端口号,可以根据这个端口号去invoke

    dubbo.protocol.name=dubbo //不可随意更改

    dubbo.scan.base-packages =//服务接口扫描基础路径

    dubbo.application.qos.accept.foreign.ip=false//默认情况下,dubbo 接收任何主机发起的命令,这样配置,拒绝远端主机发出的命令,只允许服务本机执行

    4.dubbo序列化方式

    在dubbo RPC中,同时支持多种序列化方式,例如:

    dubbo序列化:阿里尚未开发成熟的高效java序列化实现,阿里不建议在生产环境使用它hessian2序列化:hessian是一种跨语言的高效二进制序列化方式。但这里实际不是原生的hessian2序列化,而是阿里修改过的hessian lite,它是dubbo RPC默认启用的序列化方式json序列化:目前有两种实现,一种是采用的阿里的fastjson库,另一种是采用dubbo中自己实现的简单json库,但其实现都不是特别成熟,而且json这种文本序列化性能一般不如上面两种二进制序列化。java序列化:主要是采用JDK自带的Java序列化实现,性能很不理想。

    在通常情况下,这四种主要序列化方式的性能从上到下依次递减。对于dubbo RPC这种追求高性能的远程调用方式来说,实际上只有1、2两种高效序列化方式比较般配,而第1个dubbo序列化由于还不成熟,所以实际只剩下2可用,所以dubbo RPC默认采用hessian2序列化。

    dubbo支持拓展序列化方式,序列化需要实现org.apache.dubbo.common.serialize.Serialization接口

    目前所有的序列化方式为

    dubbo更改序列化框架

    更改序列化方式有2个步骤

    1.在META-INF/dubbo下建立纯文本org.apache.dubbo.common.serialize.Serialization,然后在该文件下编写xxx=com.XxxSerialization,例如 fastJson=org.apache.dubbo.common.serialize.fastjson.FastJsonSerialization

    2.在application.yml配置文件中编写dubbo.protocol.Serialization=fastJson,这样既可更改序列化方式

     

    dubbo问题分析

    1 forbid consumer xx_ip access xxservice  from registry

    这两天经常被这个dubbo的错误所困扰,其实解决完之后才发现其实并没有那么难,最核心的就是要保证服务器的provider和consumer之间的版本要对应上,如果没有对应上,就会报这个错误,其实这个错误挺误导人的,因为错误上说的是拒绝这个consumer调用dubbo的服务,给出的提示是查看访问列表,黑名单白名单,但是读过源码才知道,其实就是consumer要调用provider没有找到,可以简单的理解成NullPointerException

    2.Caused by: java.lang.IllegalStateException: No registry config found or it's not a valid config! The registry config is: <dubbo:registry valid="false" zookeeperProtocol="false" prefix="dubbo.registry" />

    原因是application的配置文件是不存在的或者配置文件有误,尤其是yml文件需要注意空格,否则很容易出错

    3.dubbo  invoke  invalid json argument ,cause:com/alibaba/fastjson

    原因之一是因为缺少fastjson的jar包引用

    4.instance must be started before calling this method

    由于ZooKeeper原生的客户端比较低层,而且使用起来不方便,Netflix公司对ZooKeeper客户端API进行了封闭,提供一可以替代原生ZooKeeper客户端的框架——Curator,换成兼容的jar包即可

    5 dubbo接口注册不上zookeeper,原因可能有多种

         1)看下zookeeper服务是不是ping的通

         2)看下是不是其他接口有注册到zookeeper上,看下接口provider的相关dubbo的注册url信息,从注册信息中看下是否有问题,

         3)看下换一个zookeeper服务重试,看下dubbo接口是不是能够注册到新的zookeeper上

      (1)遇到一个dubbo接口注册不上zookeeper的原因是因为接口名称换了,然后zookeeper一直缓存原来的接口名称,并且由于maven deploy到仓库的接口jar包是没有clean过的,导致原来改名之前的接口类依然存在,其他服务依赖该接口出现了连不上该dubbo接口问题。同时原来的容器实例被瞎掉了,可以看下是不是实例依旧存在。

     

    springboot下dubbo启动过程

    对于dubbo而言,有两个很重要的类ServiceBean和ReferenceBean,这两个类分别调用ServiceBean.export和ReferenceBean.get分别暴露服务以及获取远程服务。Dubbo程序是以Spring Beans的形式存在于Spring容器中,随着Spring容器启动而启动。在使,用这两个bean的时候,dubbo的设计者希望可以让用户通过以Annotation的方式使用dubbo,所以他们使用了spring的很多拓展点,在spring容器启动过程中分别自动发现,注册,实例化ServiceBean和ReferenceBean。

     

     

    dubbo服务源码分析

    在dubbo中,服务接口+服务分组+服务版本能够顾唯一确定一个服务,同一个服务接口可以有不同的版本以便服务升级

    dubbo中有两个比较重要的类ServiceConfig和ReferenceConfig,真正的dubbo暴露服务和调用服务如下:

    /** **暴露服务过程 */ //创建serviceConfig实例 ServiceConfig<xxInterface> serviceConfig=new ServiceConfig(xxInterface); //设置应用程序配置 serviceConfig.setApplication(new ApplicationConfig("first-dubbo-provider")); //设置服务注册中心信息 RegistryConfig registryConfig=new RegistryConfig("zookeeper://127.0.0.1:3444"); serviceConfig.setRegistry(registryConfig) //设置接口和实现类 serviceConfig.setInterface(xxInterface.class); serviceConfig.setRef(new xxInterfaceImpl()); serviceConfig.setVersion("1.0.0"); serviceConfig.setGroup("dubbo"); //设置线程池策略 /HashMap<String,String> params=new HashMap(); //params.put("threadpool","mythreadPool"); //serviceConfig.setParameters(params); //导出服务 serviceConfig.export(); //dubbo服务同时支持本地导出和远程导出协议,其中none表示不到处服务,remote表示之淡出远程服务,local只导出本地服务 serviceConfig.setScope("remote") //挂起服务,避免服务停止 System.in.read(); //创建服务引用对象实例 RefereceConfig<xxInterface> referenceConfig=new ReferenceConfig<xxInterface>(); //设置应用程序信息 referenceConfig.setApplication(new ApplicationConfig("first-dubbo-consumer")); //设置服务注册中心 referenceConfig.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:3344")); //设置服务接口和超时时间 referenceCOnfig.setInterface(xxInterface.class); referenceConfig.setTimeout(5000); //设置自定义负载策略和集群容错策略 //referenceConfig.setLoadBalance("myLoadBalance"); //referenceConfig.setCluster("myBroadCast"); //设置服务分组和版本 referenceConfig.setVersion("1.0.0"); referenceConfig.setGroup("dubbo"); //可以设置为异步的 //refereceConfig.setAysc(true); //引用服务 xxInterface xxinter=referenceConfig.get(); //设置隐式参数 RpcCOntext.getContext().setAttachment("param1","parm"); //调用服务,如果服务设置为异步的,此时返回的是null xxInter.xxmethod(); //如果是异步调用的,这样才会获取得到异步调用的值,这里借助了netty底层IO线程,在接收到响应后自动毁掉注册的回调函数,dubbo2.7版本以后支持CompletableFuture Future<xx> future=RpcContext.getContext().getFuture(); future.setCallback(new ResponseCallback(){ @Override public void done(Object response){ //TODO } });

    dubbo的分层架构

    dubbo的分层架构一共有10层,就像是网络的7层协议一样,每一个上层都会依赖下层的功能,下层的改变对上层来说是不可见的,并且每一层都是可以替换的组件。

    10层从上到下分别是service,config,proxy,registry,cluster,monitor,protocol,exchange,transport,serialize,除了serivce和config层,其他组件都是SPI(Service Provider Interface)层,并且这些层都有一个扩展点接口,每个拓展点接口都有@SPI标注,表明默认使用某个实现类(可以通过配置文件更改)

    proxy层:SPI扩展接口类是ProxyFactory,其默认的实现类是JavassistProxyFactory(JdkProxyFactory),如下图,其中JavassistProxyFactory为每个服务提供者实现类生成了Wrapper类

    Registry层:SPI扩展接口是RegistryFactory,其默认的实现类是DubboRegistryFactory

     

    dubbo在springboot的fresh context阶段第一步如下:

    可以看到获取的ExensionLoader内部有type属性(如Filter.class)以及ExtensionFactory实例(实际上就是AdaptiveExtensionFactory对象)

    AdaptiveExtensionFactory内部有两个ExtensionFactory,一个是SpiExtensionFactory,一个是DubboExtensionFactory

    获取扩展器实例如下

    需要经过createAdaptiveExtension()->getAdaptiveExensionClass-》createAdaptiveExendsionClass

    实际上内部最终调用了loadExtensionClasses方法进行加载实现类,loadExtensionClass实际上是从META-INF/dubbo/internal,MEAT-INF/services以及META-INF/dubbo资源路径下获取classes

    除此之外,dubbo在getExtensionClasses里面的loadDirectory()->loadResource->loadClass方法除了加载加载拓展接口的所有实现类的class独享,还对包装类Wrapper类进行了收集

    wrapper类的判断时wrapper类必须含有参数为实现接口的实现类

    如下图所示ProtocolListenerWrapper含有参数为Protocol的实现类,同时它也继承了Protocol接口

    dubbo会给每个服务提供者的服务接口实现类生产一个Wrapper类,这个Wrapper类里面最终调用的服务提供者的服务接口实现类,Wrapper类的存在意义是为了减少反射的调用,当服务提供方收到来回消费方的请求,需要根据消费者传递过来的方法名和参数反射调用服务提供者的实现类,而反射本身是具有性能开销的,dubbo把每个服务提供者的实现类通过JavaAssist包装成一个Wrapper类以减少反射的调用开销。

    public class GreetingServiceImpl implemets GreetingService{ @Override public String sayHello(String name){ return "hello "+name; } //对应的wrapper类的源码就是 public class Wrapper1 extends Wrapper implements ClassGenerator.DC{ public Object invokeMethod(Object object,String string,Class[] arrclass,Object[] arrobject) throw InvocationTargetException{ GreetingServiceImpl greetintgServiceimpl; try{ greetingServiceImpl=(GreetingServiceImpl) object; }catch(Throwable throwable){ throw new IllegalArgumentsException(throwable) } } } //dubbo接口实现类的wrapper类是在ProxyFactory中产生的,Dubbo提供的实现主要是JavassistProxyFactory(默认的)和JdkProxyFactory

    dubbo里面的DubboProtol经过了两层包装,第一次使用ProtocolListenerWrapper类对dubboProtocol进行了包装,这个时候ProtocolListenerWrapper里面的impl就是DubboProtocol,然后第二次适宜用了ProtocolFilterWrapper对ProtocolListenerWrapper进行了包装,也就是说ProtocolFilterWrapper里面的impl就是ProtocolListenerWrapper,这个时候适配器Protocol$Adaptive的export方法,如果URL对象里面的protocol就是dubbo的话,那么在扩展点自动包装室,protocol。export返回的就是ProtocolFitlerWrapper.

    实际上REGISTERY_PROTOCOL可以分为几种类型,如果为远程服务暴露,则内部的protocol类型是retistry,会选择protocol的实现类RegistryProtocol,如果为本地服务暴露,则根据url的protocol类型为injvm,会选择InjvmProtocol

    //ProtocolListenerWrapper的输出方法 @Override public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException { //REGISTRY_PROTOCOL="registry" if (REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) { return protocol.export(invoker); } return new ListenerExporterWrapper<T>(protocol.export(invoker), //EXPORTER_LISTENER_KEY="exporter.listener" Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class) .getActivateExtension(invoker.getUrl(), EXPORTER_LISTENER_KEY))); } //实际上ServiceConfig里面exporters.add(exporter),这个exporter最终获取的就是ListenerExporterWrapper new ListenerExporterWrapper<T>(protocol.export(invoker), Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class) .getActivateExtension(invoker.getUrl(), EXPORTER_LISTENER_KEY))); @Override public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException { if (REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) { return protocol.export(invoker); } //SERVICE_FILTER_KEY="service.filter" //buildInvokeChain得到的是new CallbackRegistrationInvoker<> return protocol.export(buildInvokerChain(invoker, SERVICE_FILTER_KEY, CommonConstants.PROVIDER)); }

    可以看到ExtendsionLoader的类型参数都是ExensionFactory,然后ExtensionFactory有两种,一种SpiExtensionFactory,另一种是SpringExtensionFactory

    每一个扩展接口都有扩展实现类,选择某个实现类实际上是通过适配器来选择的,适配器是通过dubbo的Compiler接口生成接口的适配器,如下卖弄生成Protocol接口的适配器,核心方法使用过ExtensionLoader.createAdaptiveExtensionClass,内部通过AdaptiveCompiler.compile(code,ClassLoader),编译生成class对象,所以适配器类是dubbo动态生成的

    每一个扩展接口都有一个ExtendsionLoader对应,ExtensionLoader.getExtensionLoader中获取对应的ExtensionLoader,如果没有,则创建一个,在ServiceConfig中代码如下

    ExtensionLoader内部有个EXTENSION_LOADERS,类型为ConcurrentMap<Class<?>, ExtensionLoader<?>>,key是Filter这些需要扩展的类class,但是真正的以拓展接口的类为key,以ExntensionLoader为value

    ExtendsionLoader内部方法getExtensionClasses(xxx)通过META-INF/dubbo/internal,以及META-INF/dubbo以及META-INF/services这三个路径下面获取所有的Protocol实现类

    package org.apache.dubbo.rpc; import org.apache.dubbo.common.extension.ExtensionLoader; public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol { public void destroy() { throw new UnsupportedOperationException("The method public abstract void org.apache.dubbo.rpc.Protocol.destroy() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!"); } public int getDefaultPort() { throw new UnsupportedOperationException("The method public abstract int org.apache.dubbo.rpc.Protocol.getDefaultPort() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!"); } public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException { if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null"); if (arg0.getUrl() == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null"); org.apache.dubbo.common.URL url = arg0.getUrl(); String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() ); if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])"); org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName); return extension.export(arg0); } public org.apache.dubbo.rpc.Invoker refer(java.lang.Class arg0, org.apache.dubbo.common.URL arg1) throws org.apache.dubbo.rpc.RpcException { if (arg1 == null) throw new IllegalArgumentException("url == null"); org.apache.dubbo.common.URL url = arg1; String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() ); if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])"); org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName); return extension.refer(arg0, arg1); } }

    有的时候我们的扩展接口只需要所有实现类中的其中一个,但是现在有些扩展接口需要使用到全部扩展接口,例如Filter

    比如ProtocolFilterWrapper类中的buildInvokerChain方法在建立filter责任链时,需要把属于某一个group中的所有Filter放入到责任链中,那是通过获取属于某个组的Filter来扩展实现类,当服务提供端启动时只会加载group名为provider的filter扩展实现类,而消费启动时只会加载group名为consumer的filter的扩展类

    @Activate(group=Constants.PROVIDER,value=Constants.EXECUTES_KEY) public class ExecuteLimitFilter implements Filter @Activate(group=Constants.CONSUMER,value=Constants.ACTIVES_KEY) public class ActiveLimitFilter implements Filter

    dubbo 服务导出过程解析

    dubbo服务发布导出过程是在Context fresh阶段通过ServiceBean(该服务通过实现ApplicationListener去部署dubbo服务)

     

    在dubbo里会将所有参数都封装到一个url中然后具体执行服务导出,其核心方法是ServiceConfig中断doExportUrlsFor1Protocol,如果是延迟发布,则会使用scheduledExecutorService来实现,可以在serviceConfig中setDelay(int)来设置发布时间,dubbo在服务导出过程中会将所有参数拼接成url,然后执行具体的导出过程.

    Javaassist 就是一个用来处理 Java 字节码的类库。它可以在一个已经编译好的类中添加新的方法,或者是修改已有的方法,并且不需要对字节码方面有深入的了解。不需要了解字节码指令(同类型的ASM需要),性能比ASM稍差些,但是简单,同时也可以去生成一个新的类对象,通过完全手动的方式。

    首先ExtensionLoader会根据在getExtension中从cachedInstance中获取holder,发现holder为null的时候,会调用createExtension(可能会有wrapper进行增强),wraper类也是实现接口(protocol)的类,不同的是,extensionloader在寻找接口实现类的时候回根据isWrapperclass函数来判断(内部判断逻辑就是这个类有没有一个参数为接口对象的拷贝构造函数)。

     

     

    Wrapper

    dubbo在导出服务的时候,会给每个发布的接口实现上套上一层wrapper

    在服务(本地和远程)暴露的时候会调用proxyFactory.getInvoker方法

    具体位置:

    本地暴露:ServiceConfig#exportLocal line:538远程暴露: ServiceConfig#doExportUrlsFor1Protocol line:512

    会先调用AOP织入的类StubProxyFactoryWrapper#getInvoker

    然后执行JavassistProxyFactory#getInvoker

    JavassistProxyFactory#getInvoker如下: 得到的AbstractProxyInvoke后面在调用invoke方法的时候实际上里面调用的是对应wrapper的invokeMethod方法。

    public class JavassistProxyFactory extends AbstractProxyFactory { @Override @SuppressWarnings("unchecked") public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) { return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker)); } @Override public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) { // TODO Wrapper cannot handle this scenario correctly: the classname contains '$' final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type); return new AbstractProxyInvoker<T>(proxy, type, url) { @Override protected Object doInvoke(T proxy, String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Throwable { return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments); } }; } } //待发布的接口 public interface TestService { String getData(String var1); List<String> getList(); } //首先通过makWrapper得到Wrapper对象,wrapper对象如下: public class Wrapper0 extends com.alibaba.dubbo.common.bytecode.Wrapper { /** * 属性名, 属性类型 */ public static java.util.Map pts = new HashMap<String, Class<?>>(); public static String[] pns = new String[0]; /** * 所有的方法名 */ public static String[] mns = {"getData"}; /** * 本类中的所有方法名 */ public static String[] dmns = {"getData"}; /** * 一个方法中所有的参数类型 mts[n]属性的个数和方法的个数形同 */ public static Class[] mts0 = {String.class}; public static Class[] mts1 = {List.class}; @Override public String[] getPropertyNames() { return pns; } @Override public boolean hasProperty(String n) { return pts.containsKey(n); } @Override public Class getPropertyType(String n) { return (Class) pts.get(n); } @Override public String[] getMethodNames() { return mns; } @Override public String[] getDeclaredMethodNames() { return dmns; } @Override public void setPropertyValue(Object o, String n, Object v) { per.qiao.service.TestService w; try { w = ((per.qiao.service.TestService) o); } catch (Throwable e) { throw new IllegalArgumentException(e); } throw new com.alibaba.dubbo.common.bytecode.NoSuchPropertyException("Not found property \"" + n + "\" filed or setter method in class per.qiao.service.TestService."); } @Override public Object getPropertyValue(Object o, String n) { per.qiao.service.TestService w; try { w = ((per.qiao.service.TestService) o); } catch (Throwable e) { throw new IllegalArgumentException(e); } if (n.equals("list")) { return w.getList(); } throw new com.alibaba.dubbo.common.bytecode.NoSuchPropertyException("Not found property \"" + n + "\" filed or setter method in class per.qiao.service.TestService."); } /** * 在调用接口时,就时调用的这个方法 @param o 接口实例 @param n 方法名 @param p 参数类型 @param v 参数 */ @Override public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws java.lang.reflect.InvocationTargetException { per.qiao.service.TestService w; try { w = ((per.qiao.service.TestService) o); } catch (Throwable e) { throw new IllegalArgumentException(e); } try { //这个try范围内就是你所需要暴露的所有方法 //可以看到生成的wrapper是直接调用的对象的方法,而不是通过反射来调用的,因此dubbo接口在调用的时候可以减少传统反射带来的开销 if ("getData".equals(n) && p.length == 1) { return w.getData((java.lang.String) v[0]); } if ("getList".equals(n) && p.length == 0) { return w.getList(); } } catch (Throwable e) { throw new java.lang.reflect.InvocationTargetException(e); } throw new com.alibaba.dubbo.common.bytecode.NoSuchMethodException("Not found method \"" + n + "\" in class per.qiao.service.TestService."); } }

    生成wrapper以后,这些wrapper会保存在Wrapper类的WRAPPER_MAP中

    public static Wrapper getWrapper(Class<?> c) { while (ClassGenerator.isDynamicClass(c)) // can not wrapper on dynamic class. { c = c.getSuperclass(); } if (c == Object.class) { return OBJECT_WRAPPER; } Wrapper ret = WRAPPER_MAP.get(c); if (ret == null) { ret = makeWrapper(c); WRAPPER_MAP.put(c, ret); } return ret; }

    得到wrapper以后使用DelegateProviderMetaDataInvoker包装AbstractProxyInvoker和metaData(实际上就是ServiceConfig)

    public class DelegateProviderMetaDataInvoker<T> implements Invoker { protected final Invoker<T> invoker; private ServiceConfig metadata; public DelegateProviderMetaDataInvoker(Invoker<T> invoker, ServiceConfig metadata) { this.invoker = invoker; this.metadata = metadata; } }

    在dubboProtocol中有个Map<String, Exporter<?>> exporterMap = new ConcurrentHashMap<String, Exporter<?>>();

    实际上存储的key是serviceKey,这个key实际上是[serviceGroup/]serviceName[:serviceVersion]:port

    存储的value是 DubboExporter

    在发布的时候有个url参数optimizer是可以

    //dubboProtocol方法 private void optimizeSerialization(URL url) throws RpcException { String className = url.getParameter(OPTIMIZER_KEY, ""); if (StringUtils.isEmpty(className) || optimizers.contains(className)) { return; } logger.info("Optimizing the serialization process for Kryo, FST, etc..."); try { Class clazz = Thread.currentThread().getContextClassLoader().loadClass(className); if (!SerializationOptimizer.class.isAssignableFrom(clazz)) { throw new RpcException("The serialization optimizer " + className + " isn't an instance of " + SerializationOptimizer.class.getName()); } SerializationOptimizer optimizer = (SerializationOptimizer) clazz.newInstance(); if (optimizer.getSerializableClasses() == null) { return; } for (Class c : optimizer.getSerializableClasses()) { SerializableClassRegistry.registerClass(c); } optimizers.add(className); 。。。。。。。

     

    export发布服务过程

    发布服务以后,dubbo的ServiceBean会调用ApplicationEventPublisher来发布事件

    //1.ServiceBean通过继实现ApplicationListener方法来监听ContextRefreshedEvent事件 @Override public void onApplicationEvent(ContextRefreshedEvent event) { if (!isExported() && !isUnexported()) { if (logger.isInfoEnabled()) { logger.info("The service ready on spring started. service: " + getInterface()); } export(); } } //2.export服务 //ServiceBean通过继承ApplicationEventPublisherAware接口来获取ApplicationEventPublisher private void publishExportEvent() { ServiceBeanExportedEvent exportEvent = new ServiceBeanExportedEvent(this); applicationEventPublisher.publishEvent(exportEvent); }

    注意:dubbo的javassist动态代理是覆盖在springframework的cglib动态代理之上的

    Processed: 0.011, SQL: 9