PHystrix 參照了 Netflix的項(xiàng)目 Hystrix。我們叫豪豬。豪豬的作用。
部署hystrix-dashboard界面工具。
作為一個(gè)壓根不懂java的程序員。跑java程序當(dāng)然不是難事。
打war包
wiki中有教你的。../gradlew jettyRun
。但也許實(shí)際上會(huì)遇到一些問(wèn)題。比如,我用gradlew 會(huì)提示我下載安裝對(duì)應(yīng)的gradle。結(jié)果沒(méi)下載下來(lái)。尷尬啊。在了解了什么是gradlew(會(huì)指定對(duì)應(yīng)的版本)之后。我用brew intall gradle 下載了比較新的版本。然后直接用gradle jettyRun運(yùn)行。默認(rèn)是跑得 是 7979端口。不用打包就可以跑。
war包
gradle build 執(zhí)行。war包在 /hystrix-dashboard/build/libs 下
部署到tomcat下
下載一個(gè)tomcat。bin目錄下點(diǎn)擊運(yùn)行文件直接運(yùn)行(linux有start_up.sh)。這玩意兒比nginx簡(jiǎn)單。一個(gè)war包扔到 webapps目錄下就執(zhí)行了。
瀏覽器輸入:http://localhost:8080/hystrix-dashboard
PHystrix的準(zhǔn)備
需要準(zhǔn)備好 apc模塊。php7及以上安裝 apcu。
pecl 的方式安裝。
可以通過(guò)運(yùn)行 apc.php文件,看apc使用情況。
具體的操作配置,看下面的參考。這里注意你的php版本。
參考鏈接: 《PHP之APC緩存詳細(xì)介紹》http://www.cnblogs.com/Alight/archive/2013/06/06/3121000.html
phystrix-dashboard 代碼,為java的dashboard工具提供數(shù)據(jù)流
文檔中的代碼即可
$config = new Zend\Config\Config(array(/* ... */));
$metricsPoller = new \Odesk\PhystrixDashboard\MetricsEventStream\ApcMetricsPoller($config);
$metricsServer = new \Odesk\PhystrixDashboard\MetricsEventStream\MetricsServer($metricsPoller);
$metricsServer->run();
我們創(chuàng)建一個(gè)控制器 叫做 DashBoard,寫(xiě)個(gè)方法叫Log。我們請(qǐng)求這個(gè)方法。
驚喜的發(fā)現(xiàn) 數(shù)據(jù)流出來(lái)了。 ok,我們打開(kāi)dashBoard的界面。然后,開(kāi)心的填入鏈接。添加監(jiān)聽(tīng)觀察。然后開(kāi)始不開(kāi)心了。
參考鏈接: https://github.com/upwork/phystrix-dashboard
PHP豪豬集成遇到的問(wèn)題。
不開(kāi)心的地方在于。dashboard 展示出現(xiàn)死循環(huán)。滿屏的 PhystrixCommand\UnReadCntCommand
。愣是沒(méi)出現(xiàn)圖形的東東。看下圖。
于是,開(kāi)始郁悶。為什么會(huì)出現(xiàn)死循環(huán)。我對(duì)比了別人寫(xiě)的demo。跑了下,沒(méi)有死循環(huán),顯示正常。我摘了端數(shù)據(jù)流。compare了下,感覺(jué)沒(méi)什么差異。那就奇怪了。既然數(shù)據(jù)格式一樣。問(wèn)題只能在js端排查。
于是開(kāi)始找循環(huán)的前端代碼。
在hystrixCommand.js
文件中搜self.eventSourceMessageListener
,在這個(gè)方法中。獲取數(shù)據(jù)并解析。我對(duì)比了正常的data跟我的data。格式一樣。那么問(wèn)題。還不是出現(xiàn)數(shù)據(jù)結(jié)構(gòu)上。
那么開(kāi)始找展示的html(通過(guò)id搜索下)。中間展示圖形html代碼在hystrixCircuitContainer.html
中。
<div class="monitor" id="CIRCUIT_<%= name + '_' + index %>" style="position:relative;">
發(fā)現(xiàn)界面死循環(huán),會(huì)產(chǎn)生多個(gè)相同的id值。那么我懷疑id是不起作用的,所以數(shù)據(jù)無(wú)法填充。導(dǎo)致圖形界面出不來(lái)。進(jìn)一步驗(yàn)證。$("#CIRCUIT_PhystrixCommand\UnReadCntCommand_0").length。打印出來(lái)是0 ,逆天了。
那么在js文件中,肯定有相關(guān)的操作。比如定位id填充數(shù)據(jù)的操作。于是,在hystrixCommand.js
代碼中找到如下這個(gè)函數(shù)displayCircuit
。這個(gè)函數(shù)中有對(duì)長(zhǎng)度進(jìn)行判斷,然后進(jìn)行相關(guān)的數(shù)據(jù)渲染操作。
if(!$('#CIRCUIT_' + data.escapedName).length) {
// args for display
if(self.args.includeDetailIcon != undefined && self.args.includeDetailIcon) {
data.includeDetailIcon = true;
}else {
data.includeDetailIcon = false;
}
// it doesn't exist so add it
var html = tmpl(hystrixTemplateCircuitContainer, data);
console.log('#CIRCUIT_' + data.escapedName);
console.log("3333333333330000");
// remove the loading thing first
$('#' + containerId + ' span.loading').remove();
// now create the new data and add it
$('#' + containerId + '').append(html);
// add the default sparkline graph
d3.selectAll('#graph_CIRCUIT_' + data.escapedName + ' svg').append("svg:path");
// remember this is new so we can trigger a sort after setting data
addNew = true;
}
既然發(fā)現(xiàn)問(wèn)題。如何解決。key中帶\
所以id元素length為0。那么就在數(shù)據(jù)渲染之前,把escapedName中的\
替換成空字符串。
找到了這個(gè)方法preProcessData
(UI展示錢的數(shù)據(jù)處理),找到了如下代碼。
data.escapedName = data.name.replace(/([ !"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g,'\\$1') + '_' + data.index;
于是在這行代碼上面加了一行 data.name = data.name.replace("\\", '');
。問(wèn)題就這么解決了。
但,這樣結(jié)束真的好嗎?
我們?yōu)槭裁床辉趯?xiě)緩存的時(shí)候,用不帶\
的Key呢?
在文件AbstractCommand
中,有一個(gè)屬性 protected $commandKey
。在我們的文件繼承中。我們?cè)O(shè)置這個(gè)屬性即可。我們?cè)陬?code>PhystrixCommand\UnReadCntCommand中。繼承這個(gè)屬性把key設(shè)置成UnReadCntCommand
即可。
看來(lái)都是命名空間惹的禍。為什么存的key是命名空間的呢?那一定是調(diào)用的時(shí)候,內(nèi)部存到了APC里面。在文件AbstractCommand
有這個(gè)代碼。代碼很容易明白,你不指定commandKey。那么通過(guò)class名字當(dāng)做key。于是,才有了命名空間的key。
public function getCommandKey()
{
if ($this->commandKey) {
return $this->commandKey;
} else {
// If the command key hasn't been defined in the class we use the current class name
return get_class($this);
}
}
參考資料: