实现dubbo随机端口

来源:互联网 发布:淘宝steam钱包充值码 编辑:程序博客网 时间:2024/05/06 01:54

dubbo每次从tomcat中undeploy似乎端口都还占用着,网上查了下,说dubbo的关闭是绑定tomcat的关闭事件,然而在项目开发时并不可能每次都关闭tomcat,可能仅仅只需要更新一下提供者就可以了

如有其它解决方案的感谢留言,如今方案纯属下策,由于初次接触dubbo,也没有太熟练.所以就只有先这么玩了..


那么如何避免dubbo的端口配置呢,这个网上有说,不过网上没有提到一些要点,避免其他人跟我一样纠结的调了半天源码才懵懵懂懂的找到原因,将其中的一些细节补充一下

首先是dubbo的配置文件

此处主要是配置dynamicDubboPortReaderDao的这个Bean,class指向你的自定义实现类

PS:<dubbo:protocol name="dubbo">此处不能省,虽然之后dubbo会默认产生一个dubbo的protocol,但据我测试就是不行,不配他会先去生成一个似乎.具体没看源码

<span style="white-space:pre"></span> <!-- 提供方应用信息,用于计算依赖关系 -->    <dubbo:application name="base-service" logger="log4j"  />        <bean id="dynamicDubboPortReaderDao" class="com.cykj.base.service.dubbo.DynamicDubboPortReaderImpl"     init-method="init" />     <!-- 使用multicast广播注册中心暴露服务地址  --><!--     <dubbo:registry protocol="zookeeper" address="127.0.0.1:2181" timeout="5000" /> -->    <dubbo:registry protocol="zookeeper" address="192.168.2.18:2181" timeout="5000" />     <!-- 用dubbo协议在20880端口暴露服务 -->    <dubbo:protocol name="dubbo" />    <dubbo:annotation package="com.cykj.base.service.provideImpl"/>         <dubbo:provider  retries="0" timeout="10000" />    <span style="white-space:pre"></span>    <dubbo:consumer retries="0" timeout="10000" /><span style="white-space:pre"></span>       <!--  <bean id="sysUserService" class="com.cykj.base.service.provideImpl.sys.SysUserServiceImpk" />-->           <!-- 声明需要暴露的服务接口 -->     <!-- <dubbo:service  ref="sysUserService" interface="com.cykj.base.core.provide.sys.SysUserService"/>      --> 

接下来贴出自定义实现类的代码,

PS:此处有个细节,让我折腾了半天,注意spring配置文件处一定不能写class:applicationContext-*.xml,一定不要让spring走扫描配置文件,否则spring配置文件加载顺序出错,会导致spring在没有初始化dubbo配置文件时初始化service,那么这时候service在初始化,而service暴露给了dubbo,那么dubbo会在此时强制初始化一次,就会先开始dubbo的初始化配置了,而上面配置的bean并没有被用到,所以被延迟实例化了.导致前几个服务会注册到20880端口上

顺便提一下spring配置文件加载顺序:

1.a)如果配置的是*.xml,则扫到一个文件初始化一个文件,此时并没有实例化,只是记录

   b)如果配置的是a.xml,b.xml,c.xml的具体文件,则spring按照指定顺序开始扫描

2.spring此时开始实例化扫描到的第一个配置文件从上至下,如果遇到引用的/autoWired等需要注入的对象时,spring将会从实例缓存中寻找该对象,如果有则注入,如果无则实例化该对象后注入,以此类推,完成整个bean的所有注入.

故而产生了上方所述情况,service先加载了,强制实例化了dubbo,而dubbo中配置的bean并没有被引用,所以bean还没有实例化,那么修改端口的操作也就延迟执行了.SO....you know...

package com.cykj.base.service.dubbo;import java.util.Map;import java.util.Map.Entry;import javax.annotation.PostConstruct;import org.springframework.beans.BeansException;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.stereotype.Component;import com.alibaba.dubbo.common.utils.NetUtils;import com.alibaba.dubbo.config.ProtocolConfig;/** * 在dubbo加载配置文件时,会实例化该类,执行init-method配置的init方法 * 此时通过spring获取所有ProtocolConfig的实体(实际上好像就一个),并将其端口设为随机一个未被使用的端口 * 源码中随机端口通过new Socket实现,而后将Socket关闭,更多细节不再说 * @author LeiYong */@Componentpublic class DynamicDubboPortReaderImpl implements ApplicationContextAware {@Autowiredprivate ApplicationContext applicationContext;private int port = 20880;@PostConstructpublic void init() {Map<String, ProtocolConfig> beansOfType = applicationContext.getBeansOfType(ProtocolConfig.class);for (Entry<String, ProtocolConfig> item : beansOfType.entrySet()) {port = NetUtils.getAvailablePort();System.out.println("##################use sure###########################"+port);item.getValue().setPort(port);}}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = (ConfigurableApplicationContext) applicationContext;}}


1 0
原创粉丝点击