最近維護(hù)的系統(tǒng)切換了網(wǎng)絡(luò)環(huán)境,由聯(lián)通換成了電信網(wǎng)絡(luò),因?yàn)槟承┻^濾規(guī)則導(dǎo)致系統(tǒng)連不上zookeeper服務(wù)器(應(yīng)用系統(tǒng)機(jī)器在深圳,網(wǎng)絡(luò)為電信線路,zookeeper服務(wù)器在北京,網(wǎng)絡(luò)為聯(lián)通線路),因?yàn)槲也皇沁\(yùn)維人員也不懂運(yùn)維相關(guān)的技術(shù),所以排查了很久也不知道原因,最后無奈之下把深圳這邊的網(wǎng)絡(luò)切回了聯(lián)通,系統(tǒng)恢復(fù)正常。
但是因?yàn)楸敬问鹿鼠w現(xiàn)了一個(gè)很嚴(yán)重的問題,即當(dāng)zookeeper注冊(cè)中心連不上時(shí)dubbo的線程會(huì)無限等待,因?yàn)橄到y(tǒng)有一些定時(shí)任務(wù)會(huì)比較頻繁地開啟新線程連接dubbo,所以導(dǎo)致的結(jié)果是tomcat一會(huì)兒線程池就滿了,其它的不依賴dubbo的功能也被阻塞無法使用。
所以需要解決一個(gè)問題,即在斷網(wǎng)的情況下要保證應(yīng)用程序可以運(yùn)行(有很多功能不依賴外網(wǎng)),一開始我以為dubbo應(yīng)該有對(duì)ZKClient連接相關(guān)的超時(shí)時(shí)間配置,結(jié)果找了很久也沒發(fā)現(xiàn),后來debug了dubbo的源代碼發(fā)現(xiàn)根本就沒有設(shè)置超時(shí)時(shí)間,ZKClient默認(rèn)的超時(shí)時(shí)間是Integer.MAX_VALUE,幾乎等于無限等待,所以無奈之下只好重寫了dubbo的ZookeeperClient實(shí)現(xiàn),好在dubbo的擴(kuò)展性非常好,基于SPI的擴(kuò)展非常方便,下面是我的擴(kuò)展代碼:
1、增加一個(gè)文件com.alibaba.dubbo.remoting.zookeeper.ZookeeperTransporter放置于項(xiàng)目的META-INF/dubbo/internal文件夾下,dubbo便會(huì)自動(dòng)掃描到這個(gè)文件。文件內(nèi)容很簡單就一句話:zkclient=com.gwall.zookeeper.ZkclientZookeeperTransporter
即把dubbo原來的默認(rèn)實(shí)現(xiàn)替換為我的實(shí)現(xiàn)。
2、ZkclientZookeeperTransporter并不是我想替換的代碼,我要替換的是ZkclientZookeeperTransporter的成員變量ZookeeperClient,只是dubbo只在ZookeeperTransporter上加了SPI注解,所以只好這樣辦了,ZkclientZookeeperTransporter代碼照抄過來。
3、在ZkclientZookeeperTransporter里面使用自己的ZkclientZookeeperClient,代碼如下:
package com.gwall.zookeeper;
import java.util.List;
import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.IZkStateListener;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.exception.ZkNoNodeException;
import org.I0Itec.zkclient.exception.ZkNodeExistsException;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.remoting.zookeeper.ChildListener;
import com.alibaba.dubbo.remoting.zookeeper.StateListener;
import com.alibaba.dubbo.remoting.zookeeper.support.AbstractZookeeperClient;
/** * 修改dubbo提供的ZkclientZookeeperClient * 主要目的是增加一個(gè)連接zookeeper的超時(shí)時(shí)間,避免ZkClient默認(rèn)的無限等待 * @author long.zr * */
public class ZkclientZookeeperClient extends AbstractZookeeperClient {
private final ZkClient client;
private volatile KeeperState state = KeeperState.SyncConnected;
public ZkclientZookeeperClient(URL url) {
super(url);
//設(shè)置超時(shí)時(shí)間為5000毫秒
client = new ZkClient(url.getBackupAddress(),5000);
client.subscribeStateChanges(new IZkStateListener() {
public void handleStateChanged(KeeperState state) throws Exception {
ZkclientZookeeperClient.this.state = state;
if (state == KeeperState.Disconnected) {
stateChanged(StateListener.DISCONNECTED);
} else if (state == KeeperState.SyncConnected) {
stateChanged(StateListener.CONNECTED);
}
}
public void handleNewSession() throws Exception {
stateChanged(StateListener.RECONNECTED);
}
});
}
public void createPersistent(String path) {
try {
client.createPersistent(path, true);
} catch (ZkNodeExistsException e) {
}
}
public void createEphemeral(String path) {
try {
client.createEphemeral(path);
} catch (ZkNodeExistsException e) {
}
}
public void delete(String path) {
try {
client.delete(path);
} catch (ZkNoNodeException e) {
}
}
public List getChildren(String path) {
try {
return client.getChildren(path);
} catch (ZkNoNodeException e) {
return null;
}
}
public boolean isConnected() {
return state == KeeperState.SyncConnected;
}
public void doClose() {
client.close();
}
public IZkChildListener createTargetChildListener(String path, final ChildListener listener) {
return new IZkChildListener() {
public void handleChildChange(String parentPath, List currentChilds)
throws Exception {
listener.childChanged(parentPath, currentChilds);
}
};
}
public List addTargetChildListener(String path, final IZkChildListener listener) {
return client.subscribeChildChanges(path, listener);
}
public void removeTargetChildListener(String path, IZkChildListener listener) {
client.unsubscribeChildChanges(path,? listener);
}
}
框架/平臺(tái)構(gòu)成:
Maven+Springmvc + Mybatis + Shiro(權(quán)限)+ Tiles(模板) +ActiveMQ(消息隊(duì)列) + Rest(服務(wù)) + WebService(服務(wù))+ EHcache(緩存) + Quartz(定時(shí)調(diào)度)+ Html5(支持PC、IOS、Android)
用戶權(quán)限系統(tǒng):
組織結(jié)構(gòu):角色、用戶、用戶組、組織機(jī)構(gòu);權(quán)限點(diǎn):頁面、方法、按鈕、數(shù)據(jù)權(quán)限、分級(jí)授權(quán)
項(xiàng)目管理新體驗(yàn):
快速出原型系統(tǒng)、組件樹、版本控制、模塊移植、協(xié)同開發(fā)、實(shí)時(shí)監(jiān)控、發(fā)布管理
可持續(xù)集成:
所有組件可移植、可定制、可擴(kuò)充,開發(fā)成果不斷積累,形成可持續(xù)發(fā)展的良性循環(huán)
支持平臺(tái)平臺(tái):
Windows XP、Windows 7 、Windows 10 、 Linux 、 Unix
服務(wù)器容器:
Tomcat 5/6/7 、Jetty、JBoss、WebSphere 8.5




