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