實現dubbo隨機埠,解決重啟Address already in use異常
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
*/
@Component
public class DynamicDubboPortReaderImpl implements ApplicationContextAware {
@Autowired
private ApplicationContext applicationContext;
private int port = 20880;
@PostConstruct
public 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);
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = (ConfigurableApplicationContext) applicationContext;
}
}
相關文章
- 解決 eclipse出現 Address already in use: bindEclipse
- Address already in use: JVM_Bind:80 解決方案JVM
- Redis 啟動報錯Address already in useRedis
- 解決svnserve: Can't bind server socket: Address already in useServer
- 解決nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)NginxAI
- startNodeManager埠被佔用:java.net.BindException: Address already in useJavaIndexException
- java.net.bindexception:address already in use: connectJavaIndexException
- java.net.BindException: Address already in use: JVM_BindJavaIndexExceptionJVM
- 解決ProtocolHandler ["ajp-nio-8009"] java.net.BindException: Address already in use: bind問題ProtocolJavaIndexException
- bind (ERROR 502): bind(0.0.0.0:8811) failed. Error: Address already in use [98] (埠被佔用)ErrorAI
- URL重寫(rewrite)的具體實現與異常問題解決
- 啟動tomcat時 錯誤: 代理丟擲異常 : java.rmi.server.ExportException: Port already in use: 1099的解決辦法TomcatJavaServerExportException
- xxl-job 報:java.net.BindException: Address already in use: bindJavaIndexException
- win10遊戲環境異常請重啟機器後再試怎麼解決Win10遊戲
- [異常筆記] zookeeper叢集啟動異常: Cannot open channel to 2 at election address ……筆記
- 重啟docker服務後,容器啟動報錯:Error response from daemon: id already in useDockerError
- win10提示您的遊戲環境異常請重啟機器後再試怎麼解決Win10遊戲
- Hive多視窗啟動異常(已解決!)Hive
- Java 異常 隨機數 包裝類Java隨機
- efcore This MySqlConnection is already in useMySql
- win10專業版你的遊戲環境異常請重啟機器再試怎麼解決Win10遊戲
- Android關機重啟實現Android
- 錯誤: 代理丟擲異常錯誤: java.rmi.server.ExportException: Port already in use: 1099;JavaServerExportException
- Ionic異常及解決
- 詳解Apache Dubbo的SPI實現機制Apache
- 權重隨機演算法的java實現隨機演算法Java
- 解決交換機埠出現err-disabled現象
- 解決一次gitlab因異常關機導致啟動失敗Gitlab
- javaWeb常見異常的解決方法JavaWeb
- 解決tomcat啟動時無法找到GroovyObject 異常TomcatObject
- C++ 異常處理機制的實現C++
- flume file channel 異常解決
- Unknowncolumn'*'in'fieldlist'異常解決
- PostgreSQL異常重啟postmaster.pid處理SQLAST
- Java常出現的異常解決方法總結(不斷更新)Java
- 異常-自定義異常的實現和測試
- CentOS 常見異常及解決辦法CentOS
- 啟科 QuSaaS 真隨機數解決方案與 Amazon Braket 結合實踐隨機