假期結(jié)束,開始收心回來繼續(xù)工作。晚上有一個(gè)項(xiàng)目要發(fā)布,公司的同事突然打手機(jī)給我,說ASF的文件解析又出了上次的問題,希望盡快解決。
問題描述:
上一次問題:
多臺(tái)機(jī)器運(yùn)行同一個(gè)分支的應(yīng)用,但是有些機(jī)器正常,有一臺(tái)機(jī)器始終在啟動(dòng)的時(shí)候報(bào)文件解析錯(cuò)誤,從提示看來,主要是因?yàn)榻馕雠渲梦募臅r(shí)候校驗(yàn)dtd失效,這臺(tái)機(jī)器無法連接外網(wǎng)。最后降低了我們內(nèi)部的核心解析包,問題解決(或者讓這臺(tái)機(jī)器連接到外網(wǎng))。(當(dāng)時(shí)由于自己手頭工作比較多,也沒有在意,既然解決了就隨之過去了)
此次問題:
問題的提示和上次的類似,不過這次的機(jī)器時(shí)連接外網(wǎng)的。
問題查找:
解析出錯(cuò)的文件是ASF(SCA的服務(wù)框架)的組件配置文件(composite文件),格式為xml的格式,解析方式是通過StAX標(biāo)準(zhǔn)來實(shí)現(xiàn)的。
按照上一次的解決方法,我將內(nèi)部的tuscany0.998降級(jí)到tuscany0.997,解析正常。看了一下我對(duì)于這兩個(gè)版本升級(jí)作的修改,主要是支持了SCA框架中的Spring配置文件能夠使用import的標(biāo)簽,內(nèi)簽多個(gè)標(biāo)準(zhǔn)的spring文件。
跟蹤代碼內(nèi)部發(fā)現(xiàn),果然是在解析某幾個(gè)spring的配置文件時(shí)出現(xiàn)了問題,比較了一下ASF的Spring(正常解析)和標(biāo)準(zhǔn)的Spring配置文件,差別主要是在關(guān)于Xml的校驗(yàn)申明的區(qū)別。ASF的Spring配置文件是由ASF Spring插件來自己解析的(采用Schema申明(固定的Target namingspace),因此早先所有的ASF的Spring我都要求大家采用Schema的校驗(yàn)申明),而對(duì)于原來不是ASF的spring都是采用dtd的校驗(yàn)方式申明(互相拷貝導(dǎo)致都是這樣)。下面就是兩種申明:
Schema:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sca="http://www.springframework.org/schema/sca"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/sca http://www.springframework.org/schema/sca/spring-sca.xsd">
Dtd:
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
早先由于在0.997版本中沒有支持import,因此也就不會(huì)去解析那些不是ASF的Spring文件,而現(xiàn)在因?yàn)樾枨笾С至薸mport所以需要解析那些原來不屬于ASF的Spring的配置文件。因此降低版本不是解決問題的辦法。
進(jìn)一步跟進(jìn)問題,發(fā)現(xiàn)是在解析Dtd的申明時(shí)候出現(xiàn)問題,拋出異常說連接超時(shí)。通過IE訪問了一下dtd的地址,的卻也是有問題,無法連接。看來是Spring的dtd的服務(wù)器出現(xiàn)了問題,導(dǎo)致了我們解析文件時(shí)候校驗(yàn)無法正常,最終無法正常啟動(dòng)。
問題解決:
這里先說一下最后解決的幾個(gè)方案,后面會(huì)有一些詳細(xì)的解釋和說明。
1. 升級(jí)ASF的Spring插件包,去除對(duì)于Xml的格式校驗(yàn)。
XMLInputFactory xmlFactory = XMLInputFactory.newInstance();
//add by wenchu.cenwc cancel support dtd check
xmlFactory.setProperty(XMLInputFactory.SUPPORT_DTD, "false");
2. 將Dtd的校驗(yàn)申明修改成為Schema的校驗(yàn)申明。
3. 建立公司的Xml校驗(yàn)服務(wù)器,控制管理dtd或者schema,將所有的xml Schema或者dtd申明指向該服務(wù)器。
問題延伸開來的思考:
就問題的解決方案來看這個(gè)問題的一些值得注意和思考的地方。
方案1:
當(dāng)前對(duì)于XML解析來說,各種框架都已經(jīng)統(tǒng)一的實(shí)現(xiàn)了StAX的標(biāo)準(zhǔn),同時(shí)在jdk6得rt.jar中都已經(jīng)將StAX API作為基礎(chǔ)框架API納入其內(nèi)。而通常情況下,如果不配置是否校驗(yàn)Xml,那么都將默認(rèn)會(huì)主動(dòng)校驗(yàn)Xml,此時(shí)就會(huì)出現(xiàn)上面我所遇到的問題,如果當(dāng)你依賴的Xml DTD 或者 Schema服務(wù)器出現(xiàn)問題,就會(huì)導(dǎo)致你本地應(yīng)用可能受到影響。在Dtd的申明說明中,<!DOCTYPE rootElement PUBLIC "PublicIdentifier" "URIreference">紅色部分說可以在網(wǎng)絡(luò)出現(xiàn)問題或者網(wǎng)絡(luò)速度很慢的時(shí)候被部分xml解析器替代URIreference使用,不過我這邊沒有成功過。我通過自己屏蔽網(wǎng)絡(luò)連接來模擬環(huán)境的情況,都是無法通過的。(Schema比較奇怪,就算無法連接網(wǎng)絡(luò)還是可以正常的,這個(gè)后續(xù)需要繼續(xù)研究看看,或者有朋友對(duì)這個(gè)問題有了解請(qǐng)告知一下)
方案2:
其實(shí)早在2002年就已經(jīng)有將dtd替換成為schema的趨勢了,兩者的區(qū)別和優(yōu)劣網(wǎng)上的文章介紹了很多了,這兒不再羅列,其實(shí)最更本一點(diǎn)就是schema就是用xml來校驗(yàn)xml,而dtd卻采用了另一套規(guī)則來校驗(yàn)xml,其本身也是xml,擴(kuò)展性,可讀性,學(xué)習(xí)曲線等等都次與schema。除了遺留系統(tǒng),我個(gè)人看不出還有什么必要去使用老的dtd來校驗(yàn)xml的格式。Spring的dtd服務(wù)的出現(xiàn)問題,也說明了其實(shí)對(duì)于dtd這種方式的校驗(yàn),spring也已經(jīng)不會(huì)保證幾個(gè)9的穩(wěn)定性。
Xml常常會(huì)被作為數(shù)據(jù)承載中介,使雙方能夠在跨平臺(tái)跨語言的情況下松耦合的交互信息,也是現(xiàn)在的SOA的實(shí)施基礎(chǔ)。那么雙方勢必需要有協(xié)議和數(shù)據(jù)格式規(guī)范來約束,schema作為dtd的新一代替代者已經(jīng)廣為使用。另一方面,xsd也早已獨(dú)立于wsdl作為數(shù)據(jù)描述和可重用的數(shù)據(jù)描述說明被采用到各種互聯(lián)網(wǎng)應(yīng)用。
看看國外的Facebook,亞馬遜,ebay等公司的REST風(fēng)格的API,就可以清楚地了解到xsd十分適合作為輕量級(jí)的數(shù)據(jù)交互協(xié)議。在后續(xù)ASF中融入REST配置的實(shí)現(xiàn)中,也需要采用XSD這種Schema描述來實(shí)現(xiàn)數(shù)據(jù)交互解析。
因此替換掉Dtd的配置是遲早要做的一件事情,所以遲作不如早作,更避免拷貝引起的問題放大效果(不過這個(gè)問題由于要考慮QA和業(yè)務(wù)組的項(xiàng)目經(jīng)理的顧慮,因此我只能做到的是建議)。
方案3:
看看Maven這些年這么火,其實(shí)在我們自己公司內(nèi)部的antx同樣都是在做一件事情,就是對(duì)于第三方的依賴包的版本控制。對(duì)于開源項(xiàng)目依賴的管理其實(shí)很重要,作的好項(xiàng)目能夠很好的利用已有的成果,管理的不好就會(huì)被一些不太穩(wěn)定的開源項(xiàng)目搞得頭破血流。
記得在上次三亞的聚會(huì)上談到了對(duì)于Tuscany的依賴,其實(shí)對(duì)于這個(gè)項(xiàng)目來說,如果要作為成熟的產(chǎn)品來說,那么勢必要獲取一個(gè)版本然后就作為穩(wěn)定的依賴,而不是一味的升級(jí)更新,由于我們產(chǎn)品的特殊性以及早期的Tuscany的不成熟,因此我們僅僅只是使用了Tuscany的最核心解析文件框架部分,其他的插件都采取自己設(shè)計(jì)或者在原有設(shè)計(jì)上優(yōu)化和更新的做法。當(dāng)然這不是說對(duì)于所有的第三方依賴都是采取這樣的策略,其實(shí)如果不是基礎(chǔ)框架設(shè)計(jì),僅僅只是應(yīng)用級(jí)別的使用,只需要拿來主義就完全可以了。
回過頭來看,大家現(xiàn)在對(duì)于類庫的管理已經(jīng)都很重視了,但是對(duì)于配置性的或者數(shù)據(jù)格式類的文件還沒有引起足夠的重視,不過看到很多朋友已經(jīng)在本地作了這樣的工作,不過就我來看,如果能夠?qū)td,schema作版本控制和服務(wù)器搭建,在長遠(yuǎn)來看還是有一定的好處的,只是說根據(jù)各自的需求來做這樣的工作。
后續(xù)
問題出現(xiàn)的當(dāng)天,我其實(shí)晚上就一直比較擔(dān)心,因?yàn)槿绻麊栴}不解決,那么將會(huì)影響到很多項(xiàng)目組(框架被使用的越廣泛,自己所要承擔(dān)的責(zé)任越重大)。其實(shí)也是由于自己上次對(duì)于這個(gè)問題的不上心,導(dǎo)致了問題的再次出現(xiàn)。刨根問底是件好事,做我們這行的還是需要多問一些為什么,這樣就會(huì)少不少危急時(shí)刻的怎么辦了。
很多時(shí)候?yàn)槭裁闯绦騿T自己喜歡什么都自己做,因?yàn)檎莆赵谧约菏种械氖虑榭偸悄軌蚪鉀Q,但是現(xiàn)在項(xiàng)目中對(duì)于第三方的依賴越來越多,在選擇和控制上必須慎之又慎,有時(shí)候依賴也是雙刃劍。