2007年1月19日
#
初衷是希望有一個(gè)簡(jiǎn)便,不需要配置文件的辦法,提高數(shù)據(jù)層的事務(wù)處理能力。以及對(duì)連接池的支持。
解決思路是通過(guò)修改Spring框架,修改BeanFactory的類搜索機(jī)制,默認(rèn)載入相應(yīng)的類。
并采用繼承的方式,在基類中提供默認(rèn)方法,允許Spring注入在對(duì)象實(shí)例中。然后再對(duì)象實(shí)例中調(diào)用。
最近項(xiàng)目組要求使用普元EOS進(jìn)行項(xiàng)目開(kāi)發(fā),使用了兩個(gè)月左右,雖然說(shuō)有一些心得(這個(gè)以后會(huì)寫(xiě)出來(lái)),但更多是看到了不足的地方,在這里就討論一下一個(gè)成熟的應(yīng)用框架到底應(yīng)該有哪些因素。
底層技術(shù):
Application Framework(下稱應(yīng)用框架)是為解決問(wèn)題而生的,無(wú)論是基于JAVA、C++、Ruby等等語(yǔ)言,都必須有基礎(chǔ)技術(shù)的支持。如JAVA就有經(jīng)典的Struts+Spring+Hibernate的組合,因此,一個(gè)成熟的應(yīng)用框架,必須擁有完善的MVC框架,以及完整的業(yè)務(wù)組件管理容器,還有一個(gè)成熟的數(shù)據(jù)訪問(wèn)框架。這個(gè)是一切的基礎(chǔ)。
權(quán)限管理:
擁有一個(gè)成熟基礎(chǔ)權(quán)限架構(gòu)能夠?yàn)閼?yīng)用框架增色不少。如果能夠和框架本身更好地融合,這樣更好。其實(shí)目前有很多實(shí)現(xiàn)是俄可以借鑒的,如:ACEGI和Spring。
UI:
標(biāo)簽已經(jīng)非常流行,擁有完善的標(biāo)簽庫(kù)是必不可少的,Struts是個(gè)很好的典范。
Ajax大行其道,如果沒(méi)有整合一些方便易用的AJAX控件,估計(jì)也算不上是一個(gè)好框架。
另外還有類似于Freemarker、Velocity之類的簡(jiǎn)化UI開(kāi)發(fā)的好東東,整合一兩個(gè),對(duì)于減少開(kāi)發(fā)、提高維護(hù)性有很大幫助。
開(kāi)發(fā)工具:
提供敏捷快速的開(kāi)發(fā)工具是一個(gè)成熟應(yīng)用框架所不可或缺的。使用一個(gè)成熟的應(yīng)用框架的開(kāi)發(fā)工具進(jìn)行開(kāi)發(fā),可以讓開(kāi)發(fā)者最大程度減少對(duì)于技術(shù)上的瓶頸,讓開(kāi)發(fā)者很輕松就可以完成高質(zhì)量的代碼,剩下的精力可以用于專注于業(yè)務(wù)等其它方面。
另外還有像:?jiǎn)卧獪y(cè)試、應(yīng)用部署等等方面,都是必不可少的一部分。(PS:我是非常痛恨維護(hù)幾百行ANT的build.xml代碼的人)
這里不得不稱贊一下普元,普元提供的開(kāi)發(fā)環(huán)境和它自身的底層技術(shù)融合的非常好,對(duì)于開(kāi)發(fā)者而言,是非常方便的,可以不需要很多的培訓(xùn)就可以使用IDE開(kāi)發(fā)出完整的應(yīng)用。而且測(cè)試和部署都很方便。
代碼生成器:
其實(shí)這個(gè)應(yīng)該和開(kāi)發(fā)工具放在一起,但是因?yàn)楸容^重要,所以單獨(dú)提出來(lái)說(shuō)。
一個(gè)好的代碼生成器可以省去開(kāi)發(fā)人員很多不必要的麻煩,能夠非常大地提高開(kāi)發(fā)效率。普元的代碼生成器是個(gè)不錯(cuò)的典范。
我們公司自己也有一個(gè)JOP的應(yīng)用框架,但非常簡(jiǎn)陋,和普元的設(shè)計(jì)思想不可同日而語(yǔ)。呵呵~~有點(diǎn)扯遠(yuǎn)了,但能夠看得出,代碼生成器對(duì)于應(yīng)用框架是必不可少的。
協(xié)同開(kāi)發(fā):
整合一個(gè)好的協(xié)同開(kāi)發(fā)和版本管理工具,能夠最大程度地降低溝通成本。除了能夠支持類似SVN或VSS之類的代碼版本管理工具之外,還應(yīng)該融合進(jìn)類似Visual Studio Team的任務(wù)管理和缺陷管理工具。最好擁有一個(gè)可以進(jìn)行自我積累的知識(shí)庫(kù)的實(shí)現(xiàn)。WIKI是個(gè)不錯(cuò)的主意。
設(shè)計(jì)器:
我提出這個(gè)是因?yàn)榭吹搅薎BM的RUP,擁有一個(gè)能夠從設(shè)計(jì)到代碼實(shí)現(xiàn)乃至后面的測(cè)試這樣一個(gè)全流程開(kāi)發(fā)工具,一直是IT人員的一個(gè)美好夢(mèng)想。
一個(gè)好的設(shè)計(jì)器,可以很輕松地在設(shè)計(jì)圖和代碼之間相互轉(zhuǎn)換,對(duì)于需求變更,設(shè)計(jì)管理、甚至項(xiàng)目后期的文檔都有很重要的意義。
這里又要提到普元,普元在這方面很聰明,走了一條不同的路,它把代碼變成一個(gè)個(gè)圖標(biāo)時(shí),本身就實(shí)現(xiàn)了對(duì)于設(shè)計(jì)圖和代碼之間互轉(zhuǎn)關(guān)系。(當(dāng)然,實(shí)現(xiàn)的方式有點(diǎn)土,而且沒(méi)有辦法支持標(biāo)準(zhǔn)的UML)
運(yùn)行容器:
大家可能覺(jué)得奇怪,容器為什么要單獨(dú)提出來(lái)說(shuō),很多JAVA開(kāi)發(fā)者都會(huì)說(shuō),只有遵循JAVA標(biāo)準(zhǔn)就可以啦~。其實(shí)不然,一個(gè)成熟的應(yīng)用框架當(dāng)然要考慮其兼容性,但是有時(shí)候,過(guò)多考慮兼容性往往會(huì)犧牲效率。事實(shí)上,很多應(yīng)用框架被開(kāi)發(fā)出來(lái),都是有一定的局限性的使用場(chǎng)景,針對(duì)使用場(chǎng)景的環(huán)境進(jìn)行優(yōu)化,絕對(duì)比使用通用的方法效率要高的多。如我們公司的移動(dòng)項(xiàng)目使用的是WebSphere,我們的框架就有一個(gè)針對(duì)WebSphere優(yōu)化的版本,但同時(shí)也存在一個(gè)通用版本。
當(dāng)然還有其它方面也可以引用這種思路,比如使用Oracle自帶的一些JDBC類,其效率就比使用JAVA標(biāo)準(zhǔn)的JDBC類要高得多。
其實(shí)應(yīng)用框架被創(chuàng)造出來(lái)的目的就是快速、高效、低成本地解決問(wèn)題,這個(gè)大家都知道,但是何謂“成熟”,估計(jì)100個(gè)人應(yīng)該有100個(gè)答案,這里我的理解就是開(kāi)發(fā)快捷、較低的學(xué)習(xí)成本、運(yùn)行穩(wěn)定,就是一個(gè)成熟的應(yīng)用框架。
PS:上面好像說(shuō)了一些不少普元的好話,大家千萬(wàn)不要以為我是普元的“托”,晚點(diǎn)我再寫(xiě)遍罵它的文章吧~~呵呵~~。其實(shí)我更喜歡SpringSide,但是除了“底層技術(shù)”這塊之外,在其它方面還有很長(zhǎng)的路要走,希望江南白衣兄能夠堅(jiān)持下去。
今年真的是郁悶透頂了。項(xiàng)目組居然叫我去做我從來(lái)沒(méi)有做過(guò)的接口方面的編程,搞得我焦頭爛額。
因?yàn)闆](méi)有經(jīng)驗(yàn),寫(xiě)的代碼亂七八糟,出了好多問(wèn)題,不過(guò),也學(xué)了不少東西。
首先就是Socket的編程,我只是在學(xué)習(xí)JAVA時(shí)寫(xiě)了一些socket方面的例子,從來(lái)就沒(méi)有仔細(xì)研究過(guò),組長(zhǎng)居然叫我設(shè)計(jì)一個(gè)JAVA的接口平臺(tái)。胡弄了一通之后,系統(tǒng)上線了。但是問(wèn)題就來(lái)了。
首先第一個(gè)問(wèn)題,長(zhǎng)連接必須有心跳。因?yàn)橹皡f(xié)議中沒(méi)有定義心跳協(xié)議,而我又沒(méi)有經(jīng)驗(yàn),所以等真正上線之后才發(fā)現(xiàn),如果長(zhǎng)連接沒(méi)有心跳,很容易導(dǎo)致在Socket連接中,長(zhǎng)時(shí)間沒(méi)有通訊的話,就會(huì)導(dǎo)致連接雖然保持,但不能正常通訊的問(wèn)題。
第二個(gè)問(wèn)題,必須加入流量控制。這個(gè)問(wèn)題出現(xiàn)在業(yè)務(wù)高峰期時(shí),會(huì)接收到大量請(qǐng)求,這時(shí)業(yè)務(wù)系統(tǒng)的處理速度跟不上請(qǐng)求發(fā)起方,導(dǎo)致大量請(qǐng)求積壓在Socket服務(wù)器端,導(dǎo)致JVM崩潰。這個(gè)問(wèn)題我之前是使用了JAVA5中所帶的ExecutorService,通過(guò)設(shè)置固定的線程池?cái)?shù)量的方式做流量控制,后來(lái)發(fā)現(xiàn)不行,線程會(huì)不斷增加,導(dǎo)致JVM崩潰。不知道是我代碼問(wèn)題還是ExecutorService本身的問(wèn)題。建議使用BlockingQueue來(lái)做隊(duì)列,我目前用起來(lái)還是比較穩(wěn)定。
第三個(gè)問(wèn)題,是由上面的問(wèn)題衍生出來(lái)的一個(gè)問(wèn)題,就是效率問(wèn)題。我之前的線程處理方式是每接到一個(gè)請(qǐng)求,會(huì)在主線程實(shí)例化一個(gè)線程實(shí)例,再把線程放到線程池中運(yùn)行,這個(gè)方式除了導(dǎo)致上面的問(wèn)題以外,而且效率很慢,我稱之為“推”的方式。現(xiàn)在經(jīng)過(guò)改良后,在服務(wù)起來(lái)之后,先事先運(yùn)行固定數(shù)量的線程,然后所有線程都從同一個(gè)BlockingQueue中獲取指令,我稱之為“拉”的方式。這種方式讓程序效率提高了很多,省去了每次生成對(duì)象的過(guò)程。而且這個(gè)設(shè)計(jì)本身也實(shí)現(xiàn)了處理量的控制。
第四個(gè)問(wèn)題,就是指令的返回問(wèn)題。在處理每個(gè)異步指令的過(guò)程時(shí),對(duì)于返回指令,通常的做法是將返回結(jié)果指令放入隊(duì)列中,然后再逐一返回。這個(gè)做法就存在了一個(gè)隱患,就是當(dāng)服務(wù)器的進(jìn)程core掉,或者因其它原因中斷,所有的返回指令都會(huì)丟失。建議的做法是在得到返回指令之后,將要返回的結(jié)果指令持久化,通常是放入數(shù)據(jù)表或者緩存文件中,然后再操作,這樣的話,當(dāng)重啟進(jìn)程,也可以重新讀取返回指令,最大可能保證接口的數(shù)據(jù)準(zhǔn)確性。
第五個(gè)問(wèn)題,其實(shí)跟上面有一些接近,就是做接口程序,有一個(gè)大原則,就是一切有跡可尋。在受理時(shí)要寫(xiě)日志,執(zhí)行業(yè)務(wù)時(shí)要記錄、返回結(jié)果時(shí)要入庫(kù)。總之讓運(yùn)維人員可以很方便的定位問(wèn)題,排除問(wèn)題。否則,只能麻煩自己啦!
至于其它錯(cuò)誤我就不一一羅列了,總之在錯(cuò)誤中進(jìn)步,還是學(xué)到不少知識(shí)。呵呵~~
???非常有幸能調(diào)到公司的J2EE基礎(chǔ)架構(gòu)組,負(fù)責(zé)為公司預(yù)研一套完整的架構(gòu)模型。主要是引入SOA、WorkFlow、AJAX等新技術(shù)。
???
???做了開(kāi)發(fā)人員這么久,也做了這么久項(xiàng)目,根本就沒(méi)有時(shí)間好好坐下來(lái)研究一下新技術(shù)。現(xiàn)在必須先跟一跟潮流,看看那些流行的技術(shù)以及概念了,呵呵。。。。。。
???研究主要是分三個(gè)方向:UI、BPM/SOA、構(gòu)件化。希望能在這幾個(gè)方面有所收獲吧!努力努力!!!