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