<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    coolfiry

    認(rèn)認(rèn)真真做人,兢兢業(yè)業(yè)做事!
    posts - 39, comments - 17, trackbacks - 0, articles - 0

    2006年9月14日

    在這篇文章中將我們一起來探討當(dāng)前的API網(wǎng)關(guān)的作用。 

    一、API網(wǎng)關(guān)的用處

    API網(wǎng)關(guān)我的分析中會(huì)用到以下三種場(chǎng)景。 

    1. Open API。 企業(yè)需要將自身數(shù)據(jù)、能力等作為開發(fā)平臺(tái)向外開放,通常會(huì)以rest的方式向外提供,最好的例子就是淘寶開放平臺(tái)、騰訊公司的QQ開放平臺(tái)、微信開放平臺(tái)。 Open API開放平臺(tái)必然涉及到客戶應(yīng)用的接入、API權(quán)限的管理、調(diào)用次數(shù)管理等,必然會(huì)有一個(gè)統(tǒng)一的入口進(jìn)行管理,這正是API網(wǎng)關(guān)可以發(fā)揮作用的時(shí)候。
    2. 微服務(wù)網(wǎng)關(guān)。微服務(wù)的概念最早在2012年提出,在Martin Fowler的大力推廣下,微服務(wù)在2014年后得到了大力發(fā)展。 在微服務(wù)架構(gòu)中,有一個(gè)組件可以說是必不可少的,那就是微服務(wù)網(wǎng)關(guān),微服務(wù)網(wǎng)關(guān)處理了負(fù)載均衡,緩存,路由,訪問控制,服務(wù)代理,監(jiān)控,日志等。API網(wǎng)關(guān)在微服務(wù)架構(gòu)中正是以微服務(wù)網(wǎng)關(guān)的身份存在。 
    3. API服務(wù)管理平臺(tái)。上述的微服務(wù)架構(gòu)對(duì)企業(yè)來說有可能實(shí)施上是困難的,企業(yè)有很多遺留系統(tǒng),要全部抽取為微服務(wù)器改動(dòng)太大,對(duì)企業(yè)來說成本太高。但是由于不同系統(tǒng)間存在大量的API服務(wù)互相調(diào)用,因此需要對(duì)系統(tǒng)間服務(wù)調(diào)用進(jìn)行管理,清晰地看到各系統(tǒng)調(diào)用關(guān)系,對(duì)系統(tǒng)間調(diào)用進(jìn)行監(jiān)控等。 API網(wǎng)關(guān)可以解決這些問題,我們可以認(rèn)為如果沒有大規(guī)模的實(shí)施微服務(wù)架構(gòu),那么對(duì)企業(yè)來說微服務(wù)網(wǎng)關(guān)就是企業(yè)的API服務(wù)管理平臺(tái)。

    二、API網(wǎng)關(guān)在企業(yè)整體架構(gòu)中的地位

    一個(gè)企業(yè)隨著信息系統(tǒng)復(fù)雜度的提高,必然出現(xiàn)外部合作伙伴應(yīng)用、企業(yè)自身的公網(wǎng)應(yīng)用、企業(yè)內(nèi)網(wǎng)應(yīng)用等,在架構(gòu)上應(yīng)該將這三種應(yīng)用區(qū)別開,三種應(yīng)用的安排級(jí)別、訪問方式也不一樣。 因此在我的設(shè)計(jì)中將這三種應(yīng)用分別用不同的網(wǎng)關(guān)進(jìn)行API管理,分別是:API網(wǎng)關(guān)(OpenAPI合伙伙伴應(yīng)用)、API網(wǎng)關(guān)(內(nèi)部應(yīng)用)、API網(wǎng)關(guān)(內(nèi)部公網(wǎng)應(yīng)用)。

     

    三、企業(yè)中在如何應(yīng)用API網(wǎng)關(guān)

    1、對(duì)于OpenAPI使用的API網(wǎng)關(guān)來說,一般合作伙伴要以應(yīng)用的形式接入到OpenAPI平臺(tái),合作伙伴需要到 OpenAPI平臺(tái)申請(qǐng)應(yīng)用。 因此在OpenAPI網(wǎng)關(guān)之外,需要有一個(gè)面向合作伙伴的使用的平臺(tái)用于合作伙伴,這就要求OpenAPI網(wǎng)關(guān)需要提供API給這個(gè)用戶平臺(tái)進(jìn)行訪問。 如下架構(gòu):

     

    當(dāng)然如果是在簡(jiǎn)單的場(chǎng)景下,可能并不需要提供一個(gè)面向合作伙伴的門戶,只需要由公司的運(yùn)營(yíng)人員直接添加合作伙伴應(yīng)用id/密鑰等,這種情況下也就不需要合作伙伴門戶子系統(tǒng)。 

    2、對(duì)于內(nèi)網(wǎng)的API網(wǎng)關(guān),在起到的作用上來說可以認(rèn)為是微服務(wù)網(wǎng)關(guān),也可以認(rèn)為是內(nèi)網(wǎng)的API服務(wù)治理平臺(tái)。 當(dāng)企業(yè)將所有的應(yīng)用使用微服務(wù)的架構(gòu)管理起來,那么API網(wǎng)關(guān)就起到了微服務(wù)網(wǎng)關(guān)的作用。 而當(dāng)企業(yè)只是將系統(tǒng)與系統(tǒng)之間的調(diào)用使用rest api的方式進(jìn)行訪問時(shí)使用API網(wǎng)關(guān)對(duì)調(diào)用進(jìn)行管理,那么API網(wǎng)關(guān)起到的就是API服務(wù)治理的作用。 架構(gòu)參考如下:

    3、對(duì)于公司內(nèi)部公網(wǎng)應(yīng)用(如APP、公司的網(wǎng)站),如果管理上比較細(xì)致,在架構(gòu)上是可能由獨(dú)立的API網(wǎng)關(guān)來處理這部分內(nèi)部公網(wǎng)應(yīng)用,如果想比較簡(jiǎn)單的處理,也可以是使用面向合作伙伴的API網(wǎng)關(guān)。 如果使用獨(dú)立的API網(wǎng)關(guān),有以下的好處:

    • 面向合作伙伴和面向公司主體業(yè)務(wù)的優(yōu)先級(jí)不一樣,不同的API網(wǎng)關(guān)可以做到業(yè)務(wù)影響的隔離。
    • 內(nèi)部API使用的管理流程和面向合作伙伴的管理流程可能不一樣。
    • 內(nèi)部的API在功能擴(kuò)展等方面的需求一般會(huì)大于OpenAPI對(duì)于功能的要求。

    基于以上的分析,如果公司有能力,那么還是建議分開使用合作伙伴OPEN API網(wǎng)關(guān)和內(nèi)部公網(wǎng)應(yīng)用網(wǎng)關(guān)。

    四、API網(wǎng)關(guān)有哪些競(jìng)爭(zhēng)方案

    1、對(duì)于Open API平臺(tái)的API網(wǎng)關(guān),我分析只能選擇API網(wǎng)關(guān)作為解決方案,業(yè)界沒有發(fā)現(xiàn)比較好的可以用來作為Open API平臺(tái)的入口的其他方案。 

    2、對(duì)于作為微服務(wù)網(wǎng)關(guān)的API網(wǎng)關(guān),業(yè)界的選擇可以選擇的解決方案比較多,也取決于微服務(wù)器的實(shí)現(xiàn)方案,有一些微服務(wù)架構(gòu)的實(shí)現(xiàn)方案是不需要微服務(wù)網(wǎng)關(guān)的。

    • Service Mesh,這是新興的基于無API網(wǎng)關(guān)的架構(gòu),通過在客戶端上的代理完成屏蔽網(wǎng)絡(luò)層的訪問,這樣達(dá)到對(duì)應(yīng)用層最小的改動(dòng),當(dāng)前Service Mesh的產(chǎn)品還正在開發(fā)中,并沒有非常成熟可直接應(yīng)用的產(chǎn)品。 發(fā)展最迅速的產(chǎn)品是Istio。 建議大家密切關(guān)注相關(guān)產(chǎn)品的研發(fā)、業(yè)務(wù)使用進(jìn)展。

    • 基于duboo架構(gòu),在這個(gè)架構(gòu)中通常是不需要網(wǎng)關(guān)的,是由客戶端直接訪問服務(wù)提供方,由注冊(cè)中心向客戶端返回服務(wù)方的地址。

    五、API網(wǎng)關(guān)解決方案

    私有云開源解決方案如下:

    • Kong kong是基于Nginx+Lua進(jìn)行二次開發(fā)的方案, https://konghq.com/
    • Netflix Zuul,zuul是spring cloud的一個(gè)推薦組件,https://github.com/Netflix/zuul
    • orange,這個(gè)開源程序是國(guó)人開發(fā)的, http://orange.sumory.com/

    公有云解決方案:

    • Amazon API Gateway,https://aws.amazon.com/cn/api-gateway/
    • 阿里云API網(wǎng)關(guān),https://www.aliyun.com/product/apigateway/
    • 騰訊云API網(wǎng)關(guān), https://cloud.tencent.com/product/apigateway

    自開發(fā)解決方案:

    • 基于Nginx+Lua+ OpenResty的方案,可以看到Kong,orange都是基于這個(gè)方案
    • 基于Netty、非阻塞IO模型。 通過網(wǎng)上搜索可以看到國(guó)內(nèi)的宜人貸等一些公司是基于這種方案,是一種成熟的方案。
    • 基于Node.js的方案。 這種方案是應(yīng)用了Node.js天生的非阻塞的特性。
    • 基于java Servlet的方案。 zuul基于的就是這種方案,這種方案的效率不高,這也是zuul總是被詬病的原因。

    六、企業(yè)怎么選擇API網(wǎng)關(guān)

    如果是要選擇一款已有的API網(wǎng)關(guān),那么需要從以下幾個(gè)方面去考慮。 

    1、性能與可用性
    如果一旦采用了API網(wǎng)關(guān),那么API網(wǎng)關(guān)就會(huì)作為企業(yè)應(yīng)用核心,因此性能和可用性是必須要求的。

    • 從性能上來說,需要讓網(wǎng)關(guān)增加的時(shí)間消耗越短越好,個(gè)人覺得需要10ms以下。 系統(tǒng)需要采用非阻塞的IO,如epoll,NIO等。網(wǎng)關(guān)和各種依賴的交互也需要是非阻塞的,這樣才能保證整體系統(tǒng)的高可用性,如:Node.js的響應(yīng)式編程和基于java體現(xiàn)的RxJava和Future。
    • 網(wǎng)關(guān)必須支持集群部署,任務(wù)一臺(tái)服務(wù)器的crash都應(yīng)該不影響整體系統(tǒng)的可用性。
    • 多套網(wǎng)關(guān)應(yīng)該支持同一管理平臺(tái)和同一監(jiān)控中心。 如: 一個(gè)企業(yè)的OpenAPI網(wǎng)關(guān)和內(nèi)部應(yīng)用的多個(gè)系統(tǒng)群的不同的微服務(wù)網(wǎng)關(guān)可以在同一監(jiān)控中心進(jìn)行監(jiān)控。

    2、可擴(kuò)展性、可維護(hù)性
    一款產(chǎn)品總有不能滿足生產(chǎn)需求的地方,因此需求思考產(chǎn)品在如何進(jìn)行二次開發(fā)和維護(hù),是否方便公司團(tuán)隊(duì)接手維護(hù)產(chǎn)品。 
    3、需求匹配度
    需要評(píng)估各API網(wǎng)關(guān)在需求上是否能滿足,如: 如果是OpenAPI平臺(tái)需要使用API網(wǎng)關(guān),那么需要看API網(wǎng)關(guān)在合作伙伴應(yīng)用接入、合作伙伴門戶集成、訪問次數(shù)限額等OpenAPI核心需求上去思考產(chǎn)品是否能滿足要求。 如果是微服務(wù)網(wǎng)關(guān),那么要從微服務(wù)的運(yùn)維、監(jiān)控、管理等方面去思考產(chǎn)品是否足夠強(qiáng)大。
    4、是否開源?公司是否有自開發(fā)的能力?
    現(xiàn)有的開源產(chǎn)品如kong,zuul,orange都有基礎(chǔ)的API網(wǎng)關(guān)的核心功能,這些開源產(chǎn)品大多離很好的使用有一定的距離,如:沒有提供管理功能的UI界面、監(jiān)控功能弱小,不支持OpenAPI平臺(tái),沒有公司運(yùn)營(yíng)與運(yùn)維的功能等。 當(dāng)然開源產(chǎn)品能獲取源代碼,如果公司有比較強(qiáng)的研發(fā)能力,能hold住這些開源產(chǎn)品,經(jīng)過二次開發(fā)kong、zuul應(yīng)該還是適應(yīng)一些公司,不過需求注意以下一些點(diǎn):

    • kong是基于ngnix+lua的,從公司的角度比較難于找到能去維護(hù)這種架構(gòu)產(chǎn)品的人。 需求評(píng)估當(dāng)前公司是否有這個(gè)能力去維護(hù)這個(gè)產(chǎn)品。
    • zuul因?yàn)榧軜?gòu)的原因在高并發(fā)的情況下性能不高,同時(shí)需要去基于研究整合開源的適配zuul的監(jiān)控和管理系統(tǒng)。
    • orange由于沒有被大量使用,同時(shí)是國(guó)內(nèi)個(gè)人在開源,在可持續(xù)性和社區(qū)資源上不夠豐富,出了問題后可能不容易找到人問。

    另外kong提供企業(yè)版本的API網(wǎng)關(guān),當(dāng)然也是基于ngnix+lua的,企業(yè)版本可以購買他們的技術(shù)支持、培訓(xùn)等服務(wù)、以及擁有界面的管理、監(jiān)控等功能。

    5、公有云還是私有云
    現(xiàn)在的亞馬遜、阿里、騰訊云都在提供基礎(chǔ)公有云的API網(wǎng)關(guān),當(dāng)然這些網(wǎng)關(guān)的基礎(chǔ)功能肯定是沒有問題,但是二次開發(fā),擴(kuò)展功能、監(jiān)控功能可能就不能滿足部分用戶的定制需求了。另外很多企業(yè)因?yàn)樽陨硇畔踩脑颍荒苁褂猛饩W(wǎng)公有網(wǎng)的API網(wǎng)關(guān)服務(wù),這樣就只有選擇私有云的方案了。 
    在需求上如果基于公有云的API網(wǎng)關(guān)只能做到由內(nèi)部人員為外網(wǎng)人員申請(qǐng)應(yīng)用,無法做到定制的合作伙伴門戶,這也不適合于部分企業(yè)的需求。 
    如果作為微服務(wù)網(wǎng)關(guān),大多數(shù)情況下是希望網(wǎng)關(guān)服務(wù)器和服務(wù)提供方服務(wù)器是要在內(nèi)網(wǎng)的,在這里情況下也只有私有云的API網(wǎng)關(guān)才能滿足需求。 

    綜合上面的分析,基礎(chǔ)公有云的API網(wǎng)關(guān)只有滿足一部分簡(jiǎn)單客戶的需求,對(duì)于很多企業(yè)來說私有云的API網(wǎng)關(guān)才是正確的選擇。


    文章作者介紹:
    來自于小豹科技的架構(gòu)師-專注于軟件研發(fā)基于平臺(tái)性軟件的研發(fā),目前我正在研發(fā)一款基于Netty、響應(yīng)式架構(gòu)的插件式的API網(wǎng)關(guān),希望能對(duì)行業(yè)帶來一些改變。 我希望與對(duì)OpenAPI、微服務(wù)、API網(wǎng)關(guān)、Service Mesh等感興趣的朋友多交流。 有興趣的朋友請(qǐng)加我的QQ群244054462。

    posted @ 2018-01-05 13:42 Coolfiry 閱讀(4699) | 評(píng)論 (0)編輯 收藏

    虞美人 李煜
    春花秋月何時(shí)了,往事知多少?小樓昨夜又東風(fēng),故國(guó)不堪回首月明中。雕欄玉砌應(yīng)猶在,只是朱顏改。問君能有幾多愁,恰似一江春水向東流。 

    posted @ 2009-01-19 10:49 Coolfiry 閱讀(265) | 評(píng)論 (0)編輯 收藏

    雨霖鈴 ·柳永


    寒蟬凄切。對(duì)長(zhǎng)亭晚,驟雨初歇。都門帳飲無緒,留戀處、蘭舟催發(fā)。執(zhí)手相看淚眼,竟無語凝噎。念去去、千里煙波,暮靄沉沉楚天闊。
    多情自古傷離別,更那堪冷落清秋節(jié)!今宵酒醒何處?楊柳岸、曉風(fēng)殘?jiān)隆4巳ソ?jīng)年,應(yīng)是良辰好景虛設(shè)。便縱有千種風(fēng)情,更與何人說?

    posted @ 2009-01-19 10:48 Coolfiry 閱讀(260) | 評(píng)論 (0)編輯 收藏

    1、python的入門級(jí)內(nèi)容。
    2、java mail的使用基本用法和注意事項(xiàng)。
    3、CXF中相關(guān)BUG的解決方法。
    4、UNIX 網(wǎng)絡(luò)編程步步提升系列。

    posted @ 2008-12-11 15:48 Coolfiry 閱讀(1072) | 評(píng)論 (5)編輯 收藏

    轉(zhuǎn)自:http://bbs.chinaunix.net/viewthread.php?tid=691982&extra=&page=1
    snoop 抓包
    solaris自帶snoop抓包工具,抓所有數(shù)據(jù)流

    # snoop
    Using device /dev/pcn0 (promiscuous mode)
    192.168.8.18 -> 192.168.255.255 NBT NS Query Request for WORKGROUP[1c], Success
    192.168.253.35 -> solaris      TELNET C port=1246
         solaris -> 192.168.253.35 TELNET R port=1246 Using device /dev/pc
         solaris -> 192.168.253.35 TELNET R port=1246 Using device /dev/pc
    192.168.4.150 -> (broadcast)  ARP C Who is 192.168.4.200, 192.168.4.200 ?
    192.168.4.200 -> (broadcast)  ARP C Who is 192.168.4.150, 192.168.4.150 ?
    #

    抓源地址或目的為 202.101.98.55的數(shù)據(jù)流:

    # snoop 202.101.98.55
    Using device /dev/pcn0 (promiscuous mode)
    192.168.253.35 -> dns.fz.fj.cn DNS C www.163.com. Internet Addr ?
    dns.fz.fj.cn -> 192.168.253.35 DNS R www.163.com. Internet CNAME www.cache.split.netease.com.

    #

    說明:internet cname 后的為解析www.163.com的名字時(shí),代表www.163.com回答的主機(jī)的域名。

    抓 192.168.253.35和202.101.98.55之間的數(shù)據(jù)流(雙向都抓)

    # snoop 192.168.253.35 202.101.98.55
    Using device /dev/pcn0 (promiscuous mode)
    192.168.253.35 -> dns.fz.fj.cn DNS C www.google.com. Internet Addr ?
    dns.fz.fj.cn -> 192.168.253.35 DNS R www.google.com. Internet CNAME www.l.google.com.
    #

    抓完存在當(dāng)前目錄下的cap文件中并查看

    # snoop -o cap1 -P      -P表示處在非混雜模式抓數(shù)據(jù),只抓廣播、主播、目的為本機(jī)的數(shù)據(jù)
    Using device /dev/pcn0 (non promiscuous)
    15 ^C                           15的含義是:顯示目前抓了多少個(gè)數(shù)據(jù)流
    #

    # snoop -i cap1
      1   0.00000 192.168.253.35 -> solaris      TELNET C port=1246
      2   0.18198 192.168.253.35 -> solaris      TELNET C port=1246
      3   0.37232 192.168.4.199 -> 192.168.255.255 NBT Datagram Service Type=17 Source=WB-200[20]
      4   0.00016            ? -> (multicast)  ETHER Type=EF08 (Unknown), size = 180bytes
      5   0.62546 192.168.253.35 -> solaris      TELNET C port=1246
      6   0.13822            ? -> (multicast)  ETHER Type=0000 (LLC/802.3), size = 52 bytes
      7   0.06283 192.168.253.35 -> solaris      TELNET C port=1246
      8   0.90301 192.168.253.35 -> solaris      TELNET C port=1246
      9   0.19781 192.168.253.35 -> solaris      TELNET C port=1246
    10   0.81493            ? -> (multicast)  ETHER Type=0000 (LLC/802.3), size = 52 bytes
    11   0.07018 192.168.253.35 -> solaris      TELNET C port=1246
    12   0.19939 192.168.253.35 -> solaris      TELNET C port=1246
    13   0.90151 192.168.253.35 -> solaris      TELNET C port=1246
    14   0.18904 192.168.253.35 -> solaris      TELNET C port=1246
    15   0.68422            ? -> (multicast)  ETHER Type=0000 (LLC/802.3), size = 52 bytes
    #snoop -i cap1 -p 10,12            只看10-12條記錄

    #snoop -i cap1 -p10                  只看第10條記錄

    # snoop -i cap1 -v -p101            查看第10條數(shù)據(jù)流的包頭的詳細(xì)內(nèi)容

    #snoop -i cap1 -v -x 0 -p101   查看第10條數(shù)據(jù)流的全部的詳細(xì)內(nèi)容

    抓主機(jī)192.168.253.35和202.101.98.55之間的tcp或者udp端口53的數(shù)據(jù)

    # snoop 192.168.253.35 and 202.101.98.55 and \(tcp or udp\) and port 53

    輸入(的時(shí)候要加轉(zhuǎn)義符號(hào)\


    snoop的詳細(xì)參數(shù)
    Snoop 是Solaris 系統(tǒng)中自帶的工具, 是一個(gè)用于顯示網(wǎng)絡(luò)通訊的程序, 它可捕獲IP 包并將其顯示或保存到指定文件. (限超級(jí)用戶使用snoop)
    Snoop 可將捕獲的包以一行的形式加以總結(jié)或用多行加以詳細(xì)的描述(有調(diào)用不同的參數(shù)–v -V來實(shí)現(xiàn)). 在總結(jié)方式下(-V ) , 將僅顯示最高層的相關(guān)協(xié)議, 例如一個(gè)NFS 包將僅顯示NFS 信息, 其低層的RPC, UDP, IP, Ethernet 幀信息將不會(huì)顯示, 但是當(dāng)加上相應(yīng)的參數(shù)(-v ), 這些信息都能被顯示出來.

    -C

    -D

    -N

    -P 在非混雜模式下抓包

    -S 抓包的時(shí)候顯示數(shù)據(jù)包的大小

    -V 半詳細(xì)的顯示抓的數(shù)據(jù)的信息

    -t [ r | a | d ] 顯示時(shí)間戳,-ta顯示當(dāng)前系統(tǒng)時(shí)間,精確到毫秒

    -v 最詳細(xì)的顯示數(shù)據(jù)的信息

    -x offset [ , length] 以16進(jìn)制或ACSII方式顯示某數(shù)據(jù)的部分內(nèi)容,比如 -x 0,10 只顯示0-10字節(jié)

    #snoop -i cap1 -v -x 0 -p101 查看被抓獲的第101個(gè)數(shù)據(jù)流的全部?jī)?nèi)容


    表達(dá)式:

    根據(jù)地址:

    #snoop x.x.x.x         IPV4的IP

    #snoop 0XX:XX:XX:XX    ETHERNET的MAC地址

    數(shù)據(jù)的方向:

    from x.x.x.x 或者 src x.x.x.x

    to x.x.x.x 或者 dst x.x.x.x

    可用的數(shù)據(jù)類型的關(guān)鍵詞:

    ip, ip6, arp, rarp, pppoed, pppoes,pppoe,broadcast,multicast,apple,decnet

    udp, tcp, icmp, icmp6, ah, esp

    greater length
          True if the packet is longer than length.

    less length
          True if the packet is shorter than length.

    net net

    # snoop from net 192.168.1.0 抓來自192.168.1.0/24的數(shù)據(jù)

    # snoop from net 192.168.0.0 抓來自192.168.0.0/16的數(shù)據(jù)

    port xx XX為TCP或者UDP的端口號(hào)或者 /etc/services里定義的名字

    #snoop to udp and port 53    抓到UDP53的數(shù)據(jù)

    posted @ 2008-10-21 21:30 Coolfiry 閱讀(723) | 評(píng)論 (0)編輯 收藏

    在項(xiàng)目使用CXF的過程中,遇到了有關(guān)List作為傳輸參數(shù)的時(shí)候,如果WebService端沒有明確給出List的泛型類型會(huì)報(bào)錯(cuò)。
    例如
    CXF的WebService端口接口的一個(gè)方法為為:
    1 public boolean updateMessageStatus(List batchIds);

    客戶端的的調(diào)用為:
    1 //預(yù)先初始化cxf對(duì)象cxfObj
    2 List<String> list=new ArrayList<String>();
    3 list.add("1");
    4 cxfObj.updateMessageStatus(list);


    在客戶端進(jìn)行調(diào)用WebService時(shí)會(huì)發(fā)生錯(cuò)誤,錯(cuò)誤為:unexpected element (uri:"", local:"arg0")等,據(jù)分析生成的wsdl,這是因?yàn)镃XF在進(jìn)行數(shù)據(jù)marshal時(shí)不知道要將要轉(zhuǎn)換的類型。

    解決辦法是:在WebService端的接口必須用List的泛型類型參數(shù),如:

    1 public boolean updateMessageStatus(List<String> batchIds);

    這樣就完全解決問題了。

    posted @ 2008-08-05 20:09 Coolfiry 閱讀(4956) | 評(píng)論 (1)編輯 收藏

    現(xiàn)在正在學(xué)習(xí)linux shell編程
    first.sh
    while read line
    do
            echo 
    "$line"
    done 
    <"$1"
    這是第一個(gè)shell程序小例子,就相當(dāng)于一個(gè)學(xué)習(xí)其他語言的hello world了吧。用法first.sh test,將test文件中的每一行輸出到stdout中。

    second.sh
    number=0;
    while [ "$number" -lt 100 ]
    do
            echo 
    "$number"
            number
    ='expr $number + 1'
    done
    echo
    這是第二個(gè)shell程序小例子,作用是輸出0到99的數(shù)字到stdout中。其中用到的expr的作用是使expr的參數(shù)轉(zhuǎn)化為數(shù)字并相加。兩個(gè)單引號(hào)的作用是引號(hào)所包圍的命令被命令的標(biāo)準(zhǔn)輸出替換,并輸出賦值給我number,得到了如同java中number=number+1的效果。


    posted @ 2008-07-20 20:34 Coolfiry 閱讀(587) | 評(píng)論 (2)編輯 收藏

    在項(xiàng)目開發(fā)過程中,遇到在本機(jī)和windows環(huán)境中部署用CXF框架開發(fā)的的webService沒有任何問題,但是當(dāng)將工程部署到solaris 的SUN ONE application上時(shí),再用本機(jī)的cxf Web服務(wù)客戶端訪問對(duì)應(yīng)的web服務(wù)時(shí),如果傳輸?shù)臄?shù)據(jù)量小于大約4K不會(huì)出問題,否則則會(huì)報(bào)一些數(shù)據(jù)綁定的異常如:
    Marshalling Error: Error writing request body to server。
    解決這個(gè)問題花了我足足兩天時(shí)間,原因是有關(guān)CXF的資料太少了,而且有關(guān)于這個(gè)錯(cuò)誤的解決都必須使用google才能search到,用baidu完全search不到相關(guān)的資料。
    解決方案:
    在客戶端的class-path中加上cxf.xml。cxf.xml的配置如下:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi
    ="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:http
    ="http://cxf.apache.org/transports/http/configuration"
        xmlns:jaxws
    ="http://cxf.apache.org/jaxws"
        xsi:schemaLocation
    ="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
     http://cxf.apache.org/transports/http/configuration
    http://cxf.apache.org/schemas/configuration/http-conf.xsd"
    >
        
    <http:conduit name="*.http-conduit">
            
    <http:client AutoRedirect="true" />
        
    </http:conduit>
    </beans>
    這個(gè)問題的解決方案是我在cxf的官網(wǎng)上找了很久才找到的,雖然問題解決了,但是我感到很迷惑。主要在windows tomcat環(huán)境下沒有問題,而到了SUN ONE的環(huán)境就有問題,經(jīng)過的思考和找了一資料,我認(rèn)為問題出于solaris對(duì)于HTTP數(shù)據(jù)傳輸?shù)哪承┫拗疲绻嬉ジ闱宄脑捒赡芤⒖碿xf的source code了,但是我不想花這個(gè)時(shí)間去研究這個(gè)問題了。

    我把這個(gè)解決方案寫出來,希望可以幫助到使用CXF的網(wǎng)友,也希望高手們能幫我解決我的迷惑。



    posted @ 2008-07-18 19:11 Coolfiry 閱讀(2568) | 評(píng)論 (0)編輯 收藏

    Internet的快速增長(zhǎng)使多媒體網(wǎng)絡(luò)服務(wù)器,特別是Web服務(wù)器,面對(duì)的訪問者數(shù)量快速增加,網(wǎng)絡(luò)服務(wù)器需要具備提供大量并發(fā)訪問服務(wù)的能力。 例如Yahoo每天會(huì)收到數(shù)百萬次的訪問請(qǐng)求,因此對(duì)于提供大負(fù)載Web服務(wù)的服務(wù)器來講,CPU、I/O處理能力很快會(huì)成為瓶頸。

    簡(jiǎn)單的 提高硬件性能并不能真正解決這個(gè)問題,因?yàn)閱闻_(tái)服務(wù)器的性能總是有限的,一般來講,一臺(tái)PC服務(wù)器所能提供的并發(fā)訪問處理能力大約為1000個(gè),更為高檔 的專用服務(wù)器能夠支持3000-5000個(gè)并發(fā)訪問,這樣的能力還是無法滿足負(fù)載較大的網(wǎng)站的要求。尤其是網(wǎng)絡(luò)請(qǐng)求具有突發(fā)性,當(dāng)某些重大事件發(fā)生時(shí),網(wǎng) 絡(luò)訪問就會(huì)急劇上升,從而造成網(wǎng)絡(luò)瓶頸,例如在網(wǎng)上發(fā)布的克林頓彈劾書就是很明顯的例子。必須采用多臺(tái)服務(wù)器提供網(wǎng)絡(luò)服務(wù),并將網(wǎng)絡(luò)請(qǐng)求分配給這些服務(wù)器 分擔(dān),才能提供處理大量并發(fā)服務(wù)的能力。

    當(dāng)使用多臺(tái)服務(wù)器來分擔(dān)負(fù)載的時(shí)候,最簡(jiǎn)單的辦法是將不同的服務(wù)器用在不同的方面。 按提供的內(nèi)容進(jìn)行分割時(shí),可以將一臺(tái)服務(wù)器用于提供新聞頁面,而另一臺(tái)用于提供游戲頁面;或者可以按服務(wù)器的功能進(jìn)行分割,將一臺(tái)服務(wù)器用于提供靜態(tài)頁面 訪問,而另一些用于提供CGI等需要大量消耗資源的動(dòng)態(tài)頁面訪問。然而由于網(wǎng)絡(luò)訪問的突發(fā)性,使得很難確定那些頁面造成的負(fù)載太大,如果將服務(wù)的頁面分割 的過細(xì)就會(huì)造成很大浪費(fèi)。事實(shí)上造成負(fù)載過大的頁面常常是在變化中的,如果要經(jīng)常按照負(fù)載變化來調(diào)整頁面所在的服務(wù)器,那么勢(shì)必對(duì)管理和維護(hù)造成極大的問 題。因此這種分割方法只能是大方向的調(diào)整,對(duì)于大負(fù)載的網(wǎng)站,根本的解決辦法還需要應(yīng)用負(fù)載均衡技術(shù)。

    負(fù)載均衡的思路下多臺(tái) 服務(wù)器為對(duì)稱方式,每臺(tái)服務(wù)器都具備等價(jià)的地位,都可以單獨(dú)對(duì)外提供服務(wù)而無須其他服務(wù)器的輔助。然后通過某種負(fù)載分擔(dān)技術(shù),將外部發(fā)送來的請(qǐng)求均勻分配 到對(duì)稱結(jié)構(gòu)中的某一臺(tái)服務(wù)器上,而接收到請(qǐng)求的服務(wù)器都獨(dú)立回應(yīng)客戶機(jī)的請(qǐng)求。由于建立內(nèi)容完全一致的Web服務(wù)器并不復(fù)雜,可以使用服務(wù)器同步更新或者 共享存儲(chǔ)空間等方法來完成,因此負(fù)載均衡技術(shù)就成為建立一個(gè)高負(fù)載Web站點(diǎn)的關(guān)鍵性技術(shù)。

    1. 基于特定服務(wù)器軟件的負(fù)載均衡

      很 多網(wǎng)絡(luò)協(xié)議都支持“重定向”功能,例如在HTTP協(xié)議中支持Location指令,接收到這個(gè)指令的瀏覽器將自動(dòng)重定向到Location指明的另一個(gè) URL上。由于發(fā)送Location指令比起執(zhí)行服務(wù)請(qǐng)求,對(duì)Web服務(wù)器的負(fù)載要小的多,因此可以根據(jù)這個(gè)功能來設(shè)計(jì)一種負(fù)載均衡的服務(wù)器。任何時(shí)候 Web服務(wù)器認(rèn)為自己負(fù)載較大的時(shí)候,它就不再直接發(fā)送回瀏覽器請(qǐng)求的網(wǎng)頁,而是送回一個(gè)Locaction指令,讓瀏覽器去服務(wù)器集群中的其他服務(wù)器上 獲得所需要的網(wǎng)頁。

      在這種方式下,服務(wù)器本身必須支持這種功能,然而具體實(shí)現(xiàn)起來卻有很多困難,例如一臺(tái)服務(wù)器如何能保證它重定向過的服務(wù) 器是比較空閑的,并且不會(huì)再次發(fā)送Location指令?Location指令和瀏覽器都沒有這方面的支持能力,這樣很容易在瀏覽器上形成一種死循環(huán)。因 此這種方式實(shí)際應(yīng)用當(dāng)中并不多見,使用這種方式實(shí)現(xiàn)的服務(wù)器集群軟件也較少。有些特定情況下可以使用CGI(包括使用FastCGI或mod_perl擴(kuò) 展來改善性能)來模擬這種方式去分擔(dān)負(fù)載,而Web服務(wù)器仍然保持簡(jiǎn)潔、高效的特性,此時(shí)避免Location循環(huán)的任務(wù)將由用戶的CGI程序來承擔(dān)。

    2. 基于DNS的負(fù)載均衡

      由 于基于服務(wù)器軟件的負(fù)載均衡需要改動(dòng)軟件,因此常常是得不償失,負(fù)載均衡最好是在服務(wù)器軟件之外來完成,這樣才能利用現(xiàn)有服務(wù)器軟件的種種優(yōu)勢(shì)。最早的負(fù) 載均衡技術(shù)是通過DNS服務(wù)中的隨機(jī)名字解析來實(shí)現(xiàn)的,在DNS服務(wù)器中,可以為多個(gè)不同的地址配置同一個(gè)名字,而最終查詢這個(gè)名字的客戶機(jī)將在解析這個(gè) 名字時(shí)得到其中的一個(gè)地址。因此,對(duì)于同一個(gè)名字,不同的客戶機(jī)會(huì)得到不同的地址,他們也就訪問不同地址上的Web服務(wù)器,從而達(dá)到負(fù)載均衡的目的。

      例如如果希望使用三個(gè)Web服務(wù)器來回應(yīng)對(duì)www.exampleorg.org.cn的HTTP請(qǐng)求,就可以設(shè)置該域的DNS服務(wù)器中關(guān)于該域的數(shù)據(jù)包括有與下面例子類似的結(jié)果:

      www1		IN		A 		192.168.1.1
      www2		IN		A 		192.168.1.2
      www3		IN		A 		192.168.1.3
      www		IN		CNAME		www1
      www		IN		CNAME		www2
      www		IN		CNAME		www3

      此后外部的客戶機(jī)就可能隨機(jī)的得到對(duì)應(yīng)www的不同地址,那么隨后的HTTP請(qǐng)求也就發(fā)送給不同地址了。

      DNS 負(fù)載均衡的優(yōu)點(diǎn)是簡(jiǎn)單、易行,并且服務(wù)器可以位于互聯(lián)網(wǎng)的任意位置上,當(dāng)前使用在包括Yahoo在內(nèi)的Web站點(diǎn)上。然而它也存在不少缺點(diǎn),一個(gè)缺點(diǎn)是為 了保證DNS數(shù)據(jù)及時(shí)更新,一般都要將DNS的刷新時(shí)間設(shè)置的較小,但太小就會(huì)造成太大的額外網(wǎng)絡(luò)流量,并且更改了DNS數(shù)據(jù)之后也不能立即生效;第二點(diǎn) 是DNS負(fù)載均衡無法得知服務(wù)器之間的差異,它不能做到為性能較好的服務(wù)器多分配請(qǐng)求,也不能了解到服務(wù)器的當(dāng)前狀態(tài),甚至?xí)霈F(xiàn)客戶請(qǐng)求集中在某一臺(tái)服 務(wù)器上的偶然情況。

    3. 反向代理負(fù)載均衡

      使用代理服務(wù)器可以將請(qǐng)求轉(zhuǎn)發(fā)給內(nèi)部的Web服務(wù)器,使用這種加速 模式顯然可以提升靜態(tài)網(wǎng)頁的訪問速度。因此也可以考慮使用這種技術(shù),讓代理服務(wù)器將請(qǐng)求均勻轉(zhuǎn)發(fā)給多臺(tái)內(nèi)部Web服務(wù)器之一上,從而達(dá)到負(fù)載均衡的目的。 這種代理方式與普通的代理方式有所不同,標(biāo)準(zhǔn)代理方式是客戶使用代理訪問多個(gè)外部Web服務(wù)器,而這種代理方式是多個(gè)客戶使用它訪問內(nèi)部Web服務(wù)器,因 此也被稱為反向代理模式。

      實(shí)現(xiàn)這個(gè)反向代理能力并不能算是一個(gè)特別復(fù)雜的任務(wù),但是在負(fù)載均衡中要求特別高的效率,這樣實(shí)現(xiàn)起來就不是十分 簡(jiǎn)單的了。每針對(duì)一次代理,代理服務(wù)器就必須打開兩個(gè)連接,一個(gè)為對(duì)外的連接,一個(gè)為對(duì)內(nèi)的連接,因此對(duì)于連接請(qǐng)求數(shù)量非常大的時(shí)候,代理服務(wù)器的負(fù)載也 就非常之大了,在最后反向代理服務(wù)器會(huì)成為服務(wù)的瓶頸。例如,使用Apache的mod_rproxy模塊來實(shí)現(xiàn)負(fù)載均衡功能時(shí),提供的并發(fā)連接數(shù)量受 Apache本身的并發(fā)連接數(shù)量的限制。一般來講,可以使用它來對(duì)連接數(shù)量不是特別大,但每次連接都需要消耗大量處理資源的站點(diǎn)進(jìn)行負(fù)載均衡,例如搜尋。

      使 用反向代理的好處是,可以將負(fù)載均衡和代理服務(wù)器的高速緩存技術(shù)結(jié)合在一起,提供有益的性能,具備額外的安全性,外部客戶不能直接訪問真實(shí)的服務(wù)器。并且 實(shí)現(xiàn)起來可以實(shí)現(xiàn)較好的負(fù)載均衡策略,將負(fù)載可以非常均衡的分給內(nèi)部服務(wù)器,不會(huì)出現(xiàn)負(fù)載集中到某個(gè)服務(wù)器的偶然現(xiàn)象。

    4. 基于NAT的負(fù)載均衡技術(shù)

      網(wǎng) 絡(luò)地址轉(zhuǎn)換為在內(nèi)部地址和外部地址之間進(jìn)行轉(zhuǎn)換,以便具備內(nèi)部地址的計(jì)算機(jī)能訪問外部網(wǎng)絡(luò),而當(dāng)外部網(wǎng)絡(luò)中的計(jì)算機(jī)訪問地址轉(zhuǎn)換網(wǎng)關(guān)擁有的某一外部地址 時(shí),地址轉(zhuǎn)換網(wǎng)關(guān)能將其轉(zhuǎn)發(fā)到一個(gè)映射的內(nèi)部地址上。因此如果地址轉(zhuǎn)換網(wǎng)關(guān)能將每個(gè)連接均勻轉(zhuǎn)換為不同的內(nèi)部服務(wù)器地址,此后外部網(wǎng)絡(luò)中的計(jì)算機(jī)就各自與 自己轉(zhuǎn)換得到的地址上服務(wù)器進(jìn)行通信,從而達(dá)到負(fù)載分擔(dān)的目的。

      地 址轉(zhuǎn)換可以通過軟件方式來實(shí)現(xiàn),也可以通過硬件方式來實(shí)現(xiàn)。使用硬件方式進(jìn)行操作一般稱為交換,而當(dāng)交換必須保存TCP連接信息的時(shí)候,這種針對(duì)OSI網(wǎng) 絡(luò)層的操作就被稱為第四層交換。支持負(fù)載均衡的網(wǎng)絡(luò)地址轉(zhuǎn)換為第四層交換機(jī)的一種重要功能,由于它基于定制的硬件芯片,因此其性能非常優(yōu)秀,很多交換機(jī)聲 稱具備400MB-800MB的第四層交換能力,然而也有一些資料表明,在如此快的速度下,大部分交換機(jī)就不再具備第四層交換能力了,而僅僅支持第三層甚 至第二層交換。

      然而對(duì)于大部分站點(diǎn)來講,當(dāng)前負(fù)載均衡主要是解決Web服務(wù)器處理能力瓶頸的,而非網(wǎng)絡(luò)傳輸能力,很多站點(diǎn)的互聯(lián)網(wǎng)連接帶寬總共也不過10MB,只有極少的站點(diǎn)能夠擁有較高速的網(wǎng)絡(luò)連接,因此一般沒有必要使用這些負(fù)載均衡器這樣的昂貴設(shè)備。

      使 用軟件方式來實(shí)現(xiàn)基于網(wǎng)絡(luò)地址轉(zhuǎn)換的負(fù)載均衡則要實(shí)際的多,除了一些廠商提供的解決方法之外,更有效的方法是使用免費(fèi)的自由軟件來完成這項(xiàng)任務(wù)。其中包括 Linux Virtual Server Project中的NAT實(shí)現(xiàn)方式,或者本文作者在FreeBSD下對(duì)natd的修訂版本。一般來講,使用這種軟件方式來實(shí)現(xiàn)地址轉(zhuǎn)換,中心負(fù)載均衡器存 在帶寬限制,在100MB的快速以太網(wǎng)條件下,能得到最快達(dá)80MB的帶寬,然而在實(shí)際應(yīng)用中,可能只有40MB-60MB的可用帶寬。

    5. 擴(kuò)展的負(fù)載均衡技術(shù)

    上 面使用網(wǎng)絡(luò)地址轉(zhuǎn)換來實(shí)現(xiàn)負(fù)載分擔(dān),毫無疑問所有的網(wǎng)絡(luò)連接都必須通過中心負(fù)載均衡器,那么如果負(fù)載特別大,以至于后臺(tái)的服務(wù)器數(shù)量不再在是幾臺(tái)、十幾 臺(tái),而是上百臺(tái)甚至更多,即便是使用性能優(yōu)秀的硬件交換機(jī)也回遇到瓶頸。此時(shí)問題將轉(zhuǎn)變?yōu)椋绾螌⒛敲炊嗯_(tái)服務(wù)器分布到各個(gè)互聯(lián)網(wǎng)的多個(gè)位置,分散網(wǎng)絡(luò)負(fù) 擔(dān)。當(dāng)然這可以通過綜合使用DNS和NAT兩種方法來實(shí)現(xiàn),然而更好的方式是使用一種半中心的負(fù)載均衡方式。

    在這種半中心的負(fù)載均衡方式下,即當(dāng)客戶請(qǐng)求發(fā)送給負(fù)載均衡器的時(shí)候,中心負(fù)載均衡器將請(qǐng)求打包并發(fā)送給某個(gè)服務(wù)器,而服務(wù)器的回應(yīng)請(qǐng)求不再返回給中心負(fù)載均衡器,而是直接返回給客戶,因此中心負(fù)載均衡器只負(fù)責(zé)接受并轉(zhuǎn)發(fā)請(qǐng)求,其網(wǎng)絡(luò)負(fù)擔(dān)就較小了。

    上圖來自Linux Virtual Server Project,為他們使用IP隧道實(shí)現(xiàn)的這種負(fù)載分擔(dān)能力的請(qǐng)求/回應(yīng)過程,此時(shí)每個(gè)后臺(tái)服務(wù)器都需要進(jìn)行特別的地址轉(zhuǎn)換,以欺騙瀏覽器客戶,認(rèn)為它的回應(yīng)為正確的回應(yīng)。

    同樣,這種方式的硬件實(shí)現(xiàn)方式也非常昂貴,但是會(huì)根據(jù)廠商的不同,具備不同的特殊功能,例如對(duì)SSL的支持等。

    由于這種方式比較復(fù)雜,因此實(shí)現(xiàn)起來比較困難,它的起點(diǎn)也很高,當(dāng)前情況下網(wǎng)站并不需要這么大的處理能力。

    比 較上面的負(fù)載均衡方式,DNS最容易,也最常用,能夠滿足一般的需求。但如果需要進(jìn)一步的管理和控制,可以選用反向代理方式或NAT方式,這兩種之間進(jìn)行 選擇主要依賴緩沖是不是很重要,最大的并發(fā)訪問數(shù)量是多少等條件。而如果網(wǎng)站上對(duì)負(fù)載影響很厲害的CGI程序是由網(wǎng)站自己開發(fā)的,也可以考慮在程序中自己 使用Locaction來支持負(fù)載均衡。半中心化的負(fù)載分擔(dān)方式至少在國(guó)內(nèi)當(dāng)前的情況下還不需要。
    http://galaxystar.javaeye.com/blog/50546

    posted @ 2008-07-18 14:23 Coolfiry 閱讀(255) | 評(píng)論 (0)編輯 收藏

    在Java版發(fā)表這篇文章,似乎有點(diǎn)把矛頭指向Java了。其實(shí)不是,GC是所有新一代語言共有的特征,
    Python, Eiffel,C#,Roby等無一例外地都使用了GC機(jī)制。但既然Java中的GC最為著名,所以天塌
    下來自然應(yīng)該抗著。

    這篇短文源于comp.lang.java.programmer跟comp.lang.c++上發(fā)生的一場(chǎng)大辯論,支持C++和Java
    的兩派不同勢(shì)力展開了新世紀(jì)第一場(chǎng)沖突,跟貼發(fā)言超過350,兩派都有名角壓陣。C++陣營(yíng)的擂主是
    Pete Becker,ACM會(huì)員,Dinkumware Ltd. 的技術(shù)副總監(jiān)。此君精通C++和Java,開發(fā)過兩種語言的
    核心類庫,但是卻對(duì)C++狂熱之極,而對(duì)于Java頗不以為然。平時(shí)談到Java的時(shí)候還好,一旦有人膽
    敢用Java來批判C++,立刻忍不住火爆脾氣跳將出來,以堅(jiān)韌不拔的毅力和大無畏精神與對(duì)手周旋,
    舌戰(zhàn)群儒,哪怕只剩下一個(gè)人也要血戰(zhàn)到底。這等奇人當(dāng)真少見!我真奇怪他整天泡在usenet上,
    不用工作么?他的老板P.J. Plauger如此寬宏大量?Java陣營(yíng)主角是一個(gè)網(wǎng)名Razzi的兄弟,另外有
    Sun公司大名鼎鼎的Peter van der Linden助陣,妙語連珠,寸土必爭(zhēng),加上人多勢(shì)眾,一度占據(jù)優(yōu)勢(shì)。
    C++陣營(yíng)里大拿雖然很多,但是大多數(shù)沒有Pete那么多閑工夫,例如Greg Comeau,Comeau公司老板,
    每次來個(gè)只言片語,實(shí)在幫不了Pete多大忙。但是自從C++陣營(yíng)中冒出一個(gè)無名小子,網(wǎng)名Courage(勇氣),
    發(fā)動(dòng)對(duì)Java GC機(jī)制的批判,形勢(shì)為之一變。C++陣營(yíng)眼下處于全攻之勢(shì),Java陣營(yíng)疲于防守,只能
    招架說:“你們沒有證據(jù),沒有統(tǒng)計(jì)資料”,形勢(shì)很被動(dòng)。

    垃圾收集(GC)不是一直被Java fans用來炫耀,引以為傲的優(yōu)點(diǎn)么?怎么成了弱點(diǎn)了?我大惑不解,定睛
    一看,才覺得此中頗有道理。

    首先,Java Swing庫存在大量資源泄漏問題,這一點(diǎn)SUN非常清楚,稱之為bugs,正在極力修正。但是看來
    這里的問題恐怕不僅是庫編寫者的疏忽,可能根源在于深層的機(jī)制,未必能夠輕易解決,搞不好要傷筋動(dòng)骨。
    不過這個(gè)問題不是那么根本,C++陣營(yíng)覺得如果抓住對(duì)方的弱點(diǎn)攻擊,就算是占了上風(fēng)也沒什么說服力。誰
    沒有缺點(diǎn)呢?于是反其道而行之,猛烈攻擊Java陣營(yíng)覺得最得意的東西,Java的GC機(jī)制本身。

    首先來想一想,memory leak到底意味著什么。在C++中,new出來的對(duì)象沒有delete,這就導(dǎo)致了memory
    leak。但是C++早就有了克服這一問題的辦法——smart pointer。通過使用標(biāo)準(zhǔn)庫里設(shè)計(jì)精致的auto_ptr
    以及各種STL容器,還有例如boost庫(差不多是個(gè)準(zhǔn)標(biāo)準(zhǔn)庫了)中的四個(gè)smart pointers,C++
    程序員只要
    花上一個(gè)星期的時(shí)間學(xué)習(xí)最新的資料,就可以拍著胸脯說:“我寫的
    程序沒有memory leak!”。

    相比之下,Java似乎更優(yōu)秀,因?yàn)閺囊婚_始你就不用考慮什么特殊的機(jī)制,大膽地往前new,自有GC替你
    收拾殘局。Java的GC實(shí)際上是
    JVM中的一個(gè)獨(dú)立線程,采用不同的算法策略來收集heap中那些不再有
    reference指向的垃圾對(duì)象所占用的內(nèi)存。但是,通常情況下,GC線程的優(yōu)先級(jí)比較低,只有在當(dāng)前
    程序
    空閑的時(shí)候才會(huì)被調(diào)度,收集垃圾。當(dāng)然,如果JVM感到內(nèi)存緊張了,JVM會(huì)主動(dòng)調(diào)用GC來收集垃圾,獲取
    更多的內(nèi)存。請(qǐng)注意,Java的GC工作的時(shí)機(jī)是:1. 當(dāng)前
    程序不忙,有空閑時(shí)間。2. 空閑內(nèi)存不足。
    現(xiàn)在我們考慮一種常見的情況,
    程序在緊張運(yùn)行之中,沒喲空閑時(shí)間給GC來運(yùn)行,同時(shí)機(jī)器內(nèi)存很大,
    JVM也沒有感到內(nèi)存不足,結(jié)果是什么?對(duì)了,GC形同虛設(shè),得不到調(diào)用。于是,內(nèi)存被不斷吞噬,而那些
    早已經(jīng)用不著的垃圾對(duì)象仍在在寶貴的內(nèi)存里睡大覺。例如:

    class BadGc {

        public void job1() {
            String garbage = "I am a garbage, and just sleeping in your precious memory, " +
                      "how do you think you can deal with me? Daydreaming! HAHA!!!";
            ....
        }

        public void job2() {...}

        ...
        ...

        public void job1000() {...}

        public static void main(String[] args) {
            bgc = new BadGc();
     bgc.job1();
     bgc.job2();
     ...
     bgc.job1000();
        }
    }

    運(yùn)行中,雖然garbage對(duì)象在離開job1()之后,就再也沒有用了。但是因?yàn)?/span>程序忙,內(nèi)存還夠用,所以GC得
    不到調(diào)度,garbage始終不會(huì)被回收,直到
    程序運(yùn)行到bgc.job1000()時(shí)還躺在內(nèi)存里嘲笑你。沒轍吧!

    好了,我承認(rèn)這段程序很傻。但是你不要以為這只是理論上的假設(shè),恰恰相反,大多數(shù)實(shí)用中的Java程序都有
    類似的效應(yīng)。這就是為什么Java
    程序狂耗內(nèi)存,而且好像給它多少內(nèi)存吃都不夠。你花上大筆的銀子把內(nèi)存
    從128升到256,再升到512,結(jié)果是,一旦執(zhí)行復(fù)雜任務(wù),內(nèi)存還是被輕易填滿,而且多出來的這些內(nèi)存只是
    用來裝垃圾,GC還是不給面子地千呼萬喚不出來。等到你的內(nèi)存終于心力交瘁,GC才姍姍來遲,收拾殘局。而
    且GC工作的方式也很不好評(píng)價(jià),一種方法是一旦有機(jī)會(huì)回收內(nèi)存,就把所有的垃圾都回收。你可以想象,這要
    花很長(zhǎng)時(shí)間(幾百M(fèi)的垃圾啊!),如果你這時(shí)侯正在壓下開炮的按鈕,GC卻叫了暫定,好了,你等死吧!另一
    種方法,得到機(jī)會(huì)之后,回收一些內(nèi)存,讓JVM感到內(nèi)存不那么緊張時(shí)就收手。結(jié)果呢,內(nèi)存里始終有大批垃
    圾,
    程序始終在半死不活的蕩著。最后,GC可以每隔一段時(shí)間就運(yùn)行一次,每次只回收一部分垃圾,這是現(xiàn)在
    大部分JVM的方式,結(jié)果是內(nèi)存也浪費(fèi)了,還動(dòng)不動(dòng)暫停幾百毫秒。難啊!

    反過來看看C++利用smart pointer達(dá)成的效果,一旦某對(duì)象不再被引用,系統(tǒng)刻不容緩,立刻回收內(nèi)存。這
    通常發(fā)生在關(guān)鍵任務(wù)完成后的清理(cleanup)時(shí)期,不會(huì)影響關(guān)鍵任務(wù)的實(shí)時(shí)性,同時(shí),內(nèi)存里所有的對(duì)象
    都是有用的,絕對(duì)沒有垃圾空占內(nèi)存。怎么樣?傳統(tǒng)、樸素的C++是不是更勝一籌?

    據(jù)統(tǒng)計(jì),目前的Java程序運(yùn)行期間占用的內(nèi)存通常為對(duì)應(yīng)C++程序的4-20倍。除了其它的原因,上面所說的是一個(gè)
    非常主要的因素。我們對(duì)memory leak如此憤恨,不就是因?yàn)樗鼘?dǎo)致大量的內(nèi)存垃圾得不到清除嗎?如果有了
    GC之后,垃圾比以前還來勢(shì)洶洶,那么GC又有什么好處呢?

    當(dāng)然,C++的smart pointer現(xiàn)在會(huì)使用的人不多,所以現(xiàn)在的C++程序普遍存在更嚴(yán)重的memory leak問題。
    但是,如果我奶奶跟舒馬赫比賽車輸?shù)袅耍隳軌蚵裨鼓禽v車子么?
    http://www.594k.com/java/html/y2007m1/12051/

    posted @ 2007-10-12 10:43 Coolfiry 閱讀(642) | 評(píng)論 (1)編輯 收藏

    從LiveJournal后臺(tái)發(fā)展看大規(guī)模網(wǎng)站性能優(yōu)化方法

    一、LiveJournal發(fā)展歷程

    LiveJournal是99年始于校園中的項(xiàng)目,幾個(gè)人出于愛好做了這樣一個(gè)應(yīng)用,以實(shí)現(xiàn)以下功能:

    • 博客,論壇
    • 社會(huì)性網(wǎng)絡(luò),找到朋友
    • 聚合,把朋友的文章聚合在一起

    LiveJournal采用了大量的開源軟件,甚至它本身也是一個(gè)開源軟件。

    在上線后,LiveJournal實(shí)現(xiàn)了非常快速的增長(zhǎng):

    • 2004年4月份:280萬注冊(cè)用戶。
    • 2005年4月份:680萬注冊(cè)用戶。
    • 2005年8月份:790萬注冊(cè)用戶。
    • 達(dá)到了每秒鐘上千次的頁面請(qǐng)求及處理。
    • 使用了大量MySQL服務(wù)器。
    • 使用了大量通用組件。

    二、LiveJournal架構(gòu)現(xiàn)狀概況

    livejournal_backend.png

    三、從LiveJournal發(fā)展中學(xué)習(xí)

     

    LiveJournal從1臺(tái)服務(wù)器發(fā)展到100臺(tái)服務(wù)器,這其中經(jīng)歷了無數(shù)的傷痛,但同時(shí)也摸索出了解決這些問題的方法,通過對(duì)LiveJournal的學(xué)習(xí),可以讓我們避免LJ曾經(jīng)犯過的錯(cuò)誤,并且從一開始就對(duì)系統(tǒng)進(jìn)行良好的設(shè)計(jì),以避免后期的痛苦。

    下面我們一步一步看LJ發(fā)展的腳步。

    1、一臺(tái)服務(wù)器

    一 臺(tái)別人捐助的服務(wù)器,LJ最初就跑在上面,就像Google開始時(shí)候用的破服務(wù)器一樣,值得我們尊敬。這個(gè)階段,LJ的人以驚人的速度熟悉的Unix的操 作管理,服務(wù)器性能出現(xiàn)過問題,不過還好,可以通過一些小修小改應(yīng)付過去。在這個(gè)階段里L(fēng)J把CGI升級(jí)到了FastCGI。

    最終問題出現(xiàn)了,網(wǎng)站越來越慢,已經(jīng)無法通過優(yōu)過化來解決的地步,需要更多的服務(wù)器,這時(shí)LJ開始提供付費(fèi)服務(wù),可能是想通過這些錢來購買新的服務(wù)器,以解決當(dāng)時(shí)的困境。
    毫無疑問,當(dāng)時(shí)LJ存在巨大的單點(diǎn)問題,所有的東西都在那臺(tái)服務(wù)器的鐵皮盒子里裝著。

    LJ-backend-7.png

    2、兩臺(tái)服務(wù)器

    用付費(fèi)服務(wù)賺來的錢LJ買了兩臺(tái)服務(wù)器:一臺(tái)叫做Kenny的Dell 6U機(jī)器用于提供Web服務(wù),一臺(tái)叫做Cartman的Dell 6U服務(wù)器用于提供數(shù)據(jù)庫服務(wù)。

    LJ-backend-8.png

    LJ有了更大的磁盤,更多的計(jì)算資源。但同時(shí)網(wǎng)絡(luò)結(jié)構(gòu)還是非常簡(jiǎn)單,每臺(tái)機(jī)器兩塊網(wǎng)卡,Cartman通過內(nèi)網(wǎng)為Kenny提供MySQL數(shù)據(jù)庫服務(wù)。

    暫時(shí)解決了負(fù)載的問題,新的問題又出現(xiàn)了:

    • 原來的一個(gè)單點(diǎn)變成了兩個(gè)單點(diǎn)。
    • 沒有冷備份或熱備份。
    • 網(wǎng)站速度慢的問題又開始出現(xiàn)了,沒辦法,增長(zhǎng)太快了。
    • Web服務(wù)器上CPU達(dá)到上限,需要更多的Web服務(wù)器。

    3、四臺(tái)服務(wù)器

    又買了兩臺(tái),Kyle和Stan,這次都是1U的,都用于提供Web服務(wù)。目前LJ一共有3臺(tái)Web服務(wù)器和一臺(tái)數(shù)據(jù)庫服務(wù)器。這時(shí)需要在3臺(tái)Web服務(wù)器上進(jìn)行負(fù)載均橫。

    LJ-backend-9.png

    LJ把Kenny用于外部的網(wǎng)關(guān),使用mod_backhand進(jìn)行負(fù)載均橫。

    然后問題又出現(xiàn)了:

    • 單點(diǎn)故障。數(shù)據(jù)庫和用于做網(wǎng)關(guān)的Web服務(wù)器都是單點(diǎn),一旦任何一臺(tái)機(jī)器出現(xiàn)問題將導(dǎo)致所有服務(wù)不可用。雖然用于做網(wǎng)關(guān)的Web服務(wù)器可以通過保持心跳同步迅速切換,但還是無法解決數(shù)據(jù)庫的單點(diǎn),LJ當(dāng)時(shí)也沒做這個(gè)。
    • 網(wǎng)站又變慢了,這次是因?yàn)镮O和數(shù)據(jù)庫的問題,問題是怎么往應(yīng)用里面添加數(shù)據(jù)庫呢?

    4、五臺(tái)服務(wù)器

    又買了一臺(tái)數(shù)據(jù)庫服務(wù)器。在兩臺(tái)數(shù)據(jù)庫服務(wù)器上使用了數(shù)據(jù)庫同步(Mysql支持的Master-Slave模式),寫操作全部針對(duì)主數(shù)據(jù)庫(通過Binlog,主服務(wù)器上的寫操作可以迅速同步到從服務(wù)器上),讀操作在兩個(gè)數(shù)據(jù)庫上同時(shí)進(jìn)行(也算是負(fù)載均橫的一種吧)。

    LJ-backend-10.png

    實(shí)現(xiàn)同步時(shí)要注意幾個(gè)事項(xiàng):

    • 讀操作數(shù)據(jù)庫選擇算法處理,要選一個(gè)當(dāng)前負(fù)載輕一點(diǎn)的數(shù)據(jù)庫。
    • 在從數(shù)據(jù)庫服務(wù)器上只能進(jìn)行讀操作
    • 準(zhǔn)備好應(yīng)對(duì)同步過程中的延遲,處理不好可能會(huì)導(dǎo)致數(shù)據(jù)庫同步的中斷。只需要對(duì)寫操作進(jìn)行判斷即可,讀操作不存在同步問題。

    5、更多服務(wù)器

    有錢了,當(dāng)然要多買些服務(wù)器。部署后快了沒多久,又開始慢了。這次有更多的Web服務(wù)器,更多的數(shù)據(jù)庫服務(wù)器,存在 IO與CPU爭(zhēng)用。于是采用了BIG-IP作為負(fù)載均衡解決方案。

    LJ-backend-11.png

    6、現(xiàn)在我們?cè)谀睦铮?/h2>

    LJ-backend-1.png

    現(xiàn)在服務(wù)器基本上夠了,但性能還是有問題,原因出在架構(gòu)上。

    數(shù)據(jù)庫的架構(gòu)是最大的問題。由于增加的數(shù)據(jù)庫都是以Slave模式添加到應(yīng)用內(nèi),這樣唯一的好處就是將讀操作分布到了多臺(tái)機(jī)器,但這樣帶來的后果就是寫操作被大量分發(fā),每臺(tái)機(jī)器都要執(zhí)行,服務(wù)器越多,浪費(fèi)就越大,隨著寫操作的增加,用于服務(wù)讀操作的資源越來越少。

    LJ-backend-2.png

    由一臺(tái)分布到兩臺(tái)

    LJ-backend-3.png

    最終效果

    現(xiàn)在我們發(fā)現(xiàn),我們并不需要把這些數(shù)據(jù)在如此多的服務(wù)器上都保留一份。服務(wù)器上已經(jīng)做了RAID,數(shù)據(jù)庫也進(jìn)行了備份,這么多的備份完全是對(duì)資源的浪費(fèi),屬于冗余極端過度。那為什么不把數(shù)據(jù)分布存儲(chǔ)呢?

    問題發(fā)現(xiàn)了,開始考慮如何解決。現(xiàn)在要做的就是把不同用戶的數(shù)據(jù)分布到不同的服務(wù)器上進(jìn)行存儲(chǔ),以實(shí)現(xiàn)數(shù)據(jù)的分布式存儲(chǔ),讓每臺(tái)機(jī)器只為相對(duì)固定的用戶服務(wù),以實(shí)現(xiàn)平行的架構(gòu)和良好的可擴(kuò)展性。

    為 了實(shí)現(xiàn)用戶分組,我們需要為每一個(gè)用戶分配一個(gè)組標(biāo)記,用于標(biāo)記此用戶的數(shù)據(jù)存放在哪一組數(shù)據(jù)庫服務(wù)器中。每組數(shù)據(jù)庫由一個(gè)master及幾個(gè)slave 組成,并且slave的數(shù)量在2-3臺(tái),以實(shí)現(xiàn)系統(tǒng)資源的最合理分配,既保證數(shù)據(jù)讀操作分布,又避免數(shù)據(jù)過度冗余以及同步操作對(duì)系統(tǒng)資源的過度消耗。

    LJ-backend-4.png

    由一臺(tái)(一組)中心服務(wù)器提供用戶分組控制。所有用戶的分組信息都存儲(chǔ)在這臺(tái)機(jī)器上,所有針對(duì)用戶的操作需要先查詢這臺(tái)機(jī)器得到用戶的組號(hào),然后再到相應(yīng)的數(shù)據(jù)庫組中獲取數(shù)據(jù)。

    這樣的用戶架構(gòu)與目前LJ的架構(gòu)已經(jīng)很相像了。

    在具體的實(shí)現(xiàn)時(shí)需要注意幾個(gè)問題:

    • 在數(shù)據(jù)庫組內(nèi)不要使用自增ID,以便于以后在數(shù)據(jù)庫組之間遷移用戶,以實(shí)現(xiàn)更合理的I/O,磁盤空間及負(fù)載分布。
    • 將userid,postid存儲(chǔ)在全局服務(wù)器上,可以使用自增,數(shù)據(jù)庫組中的相應(yīng)值必須以全局服務(wù)器上的值為準(zhǔn)。全局服務(wù)器上使用事務(wù)型數(shù)據(jù)庫InnoDB。
    • 在數(shù)據(jù)庫組之間遷移用戶時(shí)要萬分小心,當(dāng)遷移時(shí)用戶不能有寫操作。

    7、現(xiàn)在我們?cè)谀睦?/h2>

    LJ-backend-5.png

    問題:

    • 一個(gè)全局主服務(wù)器,掛掉的話所有用戶注冊(cè)及寫操作就掛掉。
    • 每個(gè)數(shù)據(jù)庫組一個(gè)主服務(wù)器,掛掉的話這組用戶的寫操作就掛掉。
    • 數(shù)據(jù)庫組從服務(wù)器掛掉的話會(huì)導(dǎo)致其它服務(wù)器負(fù)載過大。

    對(duì)于Master-Slave模式的單點(diǎn)問題,LJ采取了Master-Master模式來解決。所謂Master-Master實(shí)際上是人工實(shí)現(xiàn)的,并不是由MySQL直接提供的,實(shí)際上也就是兩臺(tái)機(jī)器同時(shí)是Master,也同時(shí)是Slave,互相同步。

    Master-Master實(shí)現(xiàn)時(shí)需要注意:

    • 一個(gè)Master出錯(cuò)后恢復(fù)同步,最好由服務(wù)器自動(dòng)完成。
    • 數(shù)字分配,由于同時(shí)在兩臺(tái)機(jī)器上寫,有些ID可能會(huì)沖突。

    解決方案:

    • 奇偶數(shù)分配ID,一臺(tái)機(jī)器上寫奇數(shù),一臺(tái)機(jī)器上寫偶數(shù)
    • 通過全局服務(wù)器進(jìn)行分配(LJ采用的做法)。

     

    Master-Master模式還有一種用法,這種方法與前一種相比,仍然保持兩臺(tái)機(jī)器的同步,但只有一臺(tái)機(jī)器提供服務(wù)(讀和寫),在每天晚上的時(shí)候進(jìn)行輪換,或者出現(xiàn)問題的時(shí)候進(jìn)行切換。

    8、現(xiàn)在我們?cè)谀睦?/h2>

    LJ-backend-6.png

    現(xiàn)在插播一條廣告,MyISAM VS InnoDB。

    使用InnoDB:

    • 支持事務(wù)
    • 需要做更多的配置,不過值得,可以更安全的存儲(chǔ)數(shù)據(jù),以及得到更快的速度。

    使用MyISAM:

    • 記錄日志(LJ用它來記網(wǎng)絡(luò)訪問日志)
    • 存儲(chǔ)只讀靜態(tài)數(shù)據(jù),足夠快。
    • 并發(fā)性很差,無法同時(shí)讀寫數(shù)據(jù)(添加數(shù)據(jù)可以)
    • MySQL非正常關(guān)閉或死機(jī)時(shí)會(huì)導(dǎo)致索引錯(cuò)誤,需要使用myisamchk修復(fù),而且當(dāng)訪問量大時(shí)出現(xiàn)非常頻繁。

    9、緩存

    去年我寫過一篇文章介紹memcached,它就是由LJ的團(tuán)隊(duì)開發(fā)的一款緩存工具,以key-value的方式將數(shù)據(jù)存儲(chǔ)到分布的內(nèi)存中。LJ緩存的數(shù)據(jù):

    • 12臺(tái)獨(dú)立服務(wù)器(不是捐贈(zèng)的)
    • 28個(gè)實(shí)例
    • 30GB總?cè)萘?
    • 90-93%的命中率(用過squid的人可能知道,squid內(nèi)存加磁盤的命中率大概在70-80%)

    如何建立緩存策略?

    想緩存所有的東西?那是不可能的,我們只需要緩存已經(jīng)或者可能導(dǎo)致系統(tǒng)瓶頸的地方,最大程度的提交系統(tǒng)運(yùn)行效率。通過對(duì)MySQL的日志的分析我們可以找到緩存的對(duì)象。

    緩存的缺點(diǎn)?

    • 沒有完美的事物,緩存也有缺點(diǎn):
    • 增大開發(fā)量,需要針對(duì)緩存處理編寫特殊的代碼。
    • 管理難度增加,需要更多人參與系統(tǒng)維護(hù)。
    • 當(dāng)然大內(nèi)存也需要錢。

    10、Web訪問負(fù)載均衡

    在數(shù)據(jù)包級(jí)別使用BIG-IP,但BIG-IP并不知道我們內(nèi)部的處理機(jī)制,無法判斷由哪臺(tái)服務(wù)器對(duì)這些請(qǐng)求進(jìn)行處理。反向代理并不能很好的起到作用,不是已經(jīng)夠快了,就是達(dá)不到我們想要的效果。

    所以,LJ又開發(fā)了Perlbal。特點(diǎn):

    • 快,小,可管理的http web 服務(wù)器/代理
    • 可以在內(nèi)部進(jìn)行轉(zhuǎn)發(fā)
    • 使用Perl開發(fā)
    • 單線程,異步,基于事件,使用epoll , kqueue
    • 支持Console管理與http遠(yuǎn)程管理,支持動(dòng)態(tài)配置加載
    • 多種模式:web服務(wù)器,反向代理,插件
    • 支持插件:GIF/PNG互換?

    11、MogileFS

    LJ使用開源的MogileFS作為分布式文件存儲(chǔ)系統(tǒng)。MogileFS使用非常簡(jiǎn)單,它的主要設(shè)計(jì)思想是:

    • 文件屬于類(類是最小的復(fù)制單位)
    • 跟蹤文件存儲(chǔ)位置
    • 在不同主機(jī)上存儲(chǔ)
    • 使用MySQL集群統(tǒng)一存儲(chǔ)分布信息
    • 大容易廉價(jià)磁盤

    到目前為止就這么多了,更多文檔可以在http://www.danga.com/words/找到。Danga.comLiveJournal.com的 同學(xué)們拿這個(gè)文檔參加了兩次MySQL Con,兩次OS Con,以及眾多的其它會(huì)議,無私的把他們的經(jīng)驗(yàn)分享出來,值得我們學(xué)習(xí)。在web2.0時(shí)代快速開發(fā)得到大家越來越多的重視,但良好的設(shè)計(jì)仍是每一個(gè)應(yīng) 用的基礎(chǔ),希望web2.0們?cè)诔砷L(zhǎng)為Top500網(wǎng)站的路上,不要因?yàn)榧軜?gòu)阻礙了網(wǎng)站的發(fā)展。

     http://blog.csdn.net/xmr_gxcfe/archive/2007/09/14/1785292.aspx

     

    posted @ 2007-09-29 21:26 Coolfiry 閱讀(550) | 評(píng)論 (0)編輯 收藏

    posted @ 2007-09-25 14:30 Coolfiry 閱讀(356) | 評(píng)論 (0)編輯 收藏

    UML類圖的各種標(biāo)識(shí)法
    關(guān)鍵字:   UML    
    ·------>虛線箭頭表示依賴關(guān)系(dependency),一個(gè)類需要與另外一個(gè)類一起工作,是它一種最弱的關(guān)聯(lián)關(guān)系,常見于各種工具類之間的關(guān)系
    ·——實(shí)線表示聯(lián)合關(guān)系(association),一個(gè)類包含對(duì)另外一個(gè)類對(duì)象的引用,這個(gè)通常是使用屬性來實(shí)現(xiàn)的,為了表明之間的包含關(guān)系,有時(shí)候會(huì)在實(shí)線的一端加上箭頭(navigability arrow)來表示導(dǎo)航關(guān)系,如果關(guān)聯(lián)的雙方又都和第三個(gè)類有關(guān)聯(lián)關(guān)系,那么可以在實(shí)線的中間加一個(gè)虛線和第三個(gè)類關(guān)聯(lián)來表示這種association classes關(guān)系
    ·◇——空心菱形加實(shí)線表示聚合關(guān)系(aggregation),它是一種更強(qiáng)的關(guān)聯(lián)關(guān)系,表示一個(gè)類可以擁有或者享有一個(gè)類的實(shí)例對(duì)象,在java代碼表現(xiàn)上跟聯(lián)合是一樣的。
    ·◆——實(shí)心菱形加實(shí)線表示組合關(guān)系(composition),它的關(guān)聯(lián)性比聚合更強(qiáng),被組合的對(duì)象是組合對(duì)象的一部分,沒法跟其他的對(duì)象共享,而且如果組合對(duì)象銷毀的話,被組合的對(duì)象也會(huì)同時(shí)被銷毀,其表現(xiàn)形式跟聯(lián)合一樣
    ·空心箭頭加實(shí)線,表示泛化generalization(繼承inheritance)關(guān)系,這個(gè)很簡(jiǎn)單
    ·在rose中要建立enumeration,只需要在建立的class中將其stereotype設(shè)置為enumeration即可。stereotype只是用來做一個(gè)標(biāo)記,并不包含別的意義

    posted @ 2007-06-10 18:03 Coolfiry 閱讀(480) | 評(píng)論 (0)編輯 收藏

    明天18號(hào),要從沈陽回成都了

    posted @ 2007-05-17 09:46 Coolfiry 閱讀(212) | 評(píng)論 (0)編輯 收藏

    PO BO VO DTO POJO DAO概念及其作用(附轉(zhuǎn)換圖)

       J2EE開發(fā)中大量的專業(yè)縮略語很是讓人迷惑,尤其是跟一些高手討論問題的時(shí)候,三分鐘就被人家滿口的專業(yè)術(shù)語噴暈了,PO VO BO DTO POJO DAO,一大堆的就來了(聽過老羅對(duì)這種現(xiàn)象的批判的朋友會(huì)會(huì)心一笑)。

        首先聲明偶也不是什么高手,以下總結(jié)都是自己的體會(huì)。不對(duì)之處請(qǐng)您多指教。

    PO:
    persistant object持久對(duì)象

    最形象的理解就是一個(gè)PO就是數(shù)據(jù)庫中的一條記錄。
    好處是可以把一條記錄作為一個(gè)對(duì)象處理,可以方便的轉(zhuǎn)為其它對(duì)象。

     



    BO:
    business object業(yè)務(wù)對(duì)象

    主要作用是把業(yè)務(wù)邏輯封裝為一個(gè)對(duì)象。這個(gè)對(duì)象可以包括一個(gè)或多個(gè)其它的對(duì)象。
    比如一個(gè)簡(jiǎn)歷,有教育經(jīng)歷、工作經(jīng)歷、社會(huì)關(guān)系等等。
    我們可以把教育經(jīng)歷對(duì)應(yīng)一個(gè)PO,工作經(jīng)歷對(duì)應(yīng)一個(gè)PO,社會(huì)關(guān)系對(duì)應(yīng)一個(gè)PO。
    建立一個(gè)對(duì)應(yīng)簡(jiǎn)歷的BO對(duì)象處理簡(jiǎn)歷,每個(gè)BO包含這些PO。
    這樣處理業(yè)務(wù)邏輯時(shí),我們就可以針對(duì)BO去處理。

     



    VO :
    value object值對(duì)象
    ViewObject表現(xiàn)層對(duì)象

    主要對(duì)應(yīng)界面顯示的數(shù)據(jù)對(duì)象。對(duì)于一個(gè)WEB頁面,或者SWT、SWING的一個(gè)界面,用一個(gè)VO對(duì)象對(duì)應(yīng)整個(gè)界面的值。

     



    DTO :
    Data Transfer Object數(shù)據(jù)傳輸對(duì)象
    主要用于遠(yuǎn)程調(diào)用等需要大量傳輸對(duì)象的地方。
    比如我們一張表有100個(gè)字段,那么對(duì)應(yīng)的PO就有100個(gè)屬性。
    但是我們界面上只要顯示10個(gè)字段,
    客戶端用WEB service來獲取數(shù)據(jù),沒有必要把整個(gè)PO對(duì)象傳遞到客戶端,
    這時(shí)我們就可以用只有這10個(gè)屬性的DTO來傳遞結(jié)果到客戶端,這樣也不會(huì)暴露服務(wù)端表結(jié)構(gòu).到達(dá)客戶端以后,如果用這個(gè)對(duì)象來對(duì)應(yīng)界面顯示,那此時(shí)它的身份就轉(zhuǎn)為VO

     



    POJO :
    plain ordinary java object 簡(jiǎn)單java對(duì)象
    個(gè)人感覺POJO是最常見最多變的對(duì)象,是一個(gè)中間對(duì)象,也是我們最常打交道的對(duì)象。

    一個(gè)POJO持久化以后就是PO
    直接用它傳遞、傳遞過程中就是DTO
    直接用來對(duì)應(yīng)表示層就是VO

     


    DAO:
    data access object數(shù)據(jù)訪問對(duì)象
    這個(gè)大家最熟悉,和上面幾個(gè)O區(qū)別最大,基本沒有互相轉(zhuǎn)化的可能性和必要.
    主要用來封裝對(duì)數(shù)據(jù)庫的訪問。通過它可以把POJO持久化為PO,用PO組裝出來VO、DTO


          總結(jié)下我認(rèn)為一個(gè)對(duì)象究竟是什么O要看具體環(huán)境,在不同的層、不同的應(yīng)用場(chǎng)合,對(duì)象的身份也不一樣,而且對(duì)象身份的轉(zhuǎn)化也是很自然的。就像你對(duì)老婆來說就是老公,對(duì)父母來說就是子女。設(shè)計(jì)這些概念的初衷不是為了唬人而是為了更好的理解和處理各種邏輯,讓大家能更好的去用面向?qū)ο?/font>的方式處理問題.

          大家千萬不要陷入過度設(shè)計(jì),大可不必為了設(shè)計(jì)而設(shè)計(jì)一定要在代碼中區(qū)分各個(gè)對(duì)象。一句話技術(shù)是為應(yīng)用服務(wù)的。

    歡迎指正。



    畫了個(gè)圖,感覺沒有完全表達(dá)出自己的意思。。。。。誰幫忙完善下,最好能體現(xiàn)各個(gè)O在MVC中的位置
    snap20070108.jpg 


    轉(zhuǎn)自:http://www.tkk7.com/vip01/archive/2007/01/08/92430.html

    posted @ 2007-05-17 09:44 Coolfiry 閱讀(336) | 評(píng)論 (0)編輯 收藏

    I love English from then on.I study English hard form then on.I love it.It is very lovely.

    posted @ 2006-11-26 14:13 Coolfiry 閱讀(269) | 評(píng)論 (0)編輯 收藏

    一、引言

      隨著Internet的飛速發(fā)展,人們?cè)絹碓揭揽烤W(wǎng)絡(luò)來 查找他們所需要的信息,但是,由于網(wǎng)上的信息源多不勝數(shù),也就是我們經(jīng)常所說的"Rich Data, Poor Information"。所以如何有效的去發(fā)現(xiàn)我們所需要的信息,就成了一個(gè)很關(guān)鍵的問題。為了解決這個(gè)問題,搜索引擎就隨之誕生。

       現(xiàn)在在網(wǎng)上的搜索引擎也已經(jīng)有很多,比較著名的有AltaVista, Yahoo, InfoSeek, Metacrawler, SavvySearch等等。國(guó)內(nèi)也建立了很多的搜索引擎,比如:搜狐、新浪、北極星等等,當(dāng)然由于它們建立的時(shí)間不長(zhǎng),在信息搜索的取全率和取準(zhǔn)率上都 有待于改進(jìn)和提高。

      Alta Vista是一個(gè)速度很快的搜索引擎,由于它強(qiáng)大的硬件配置,使它能夠做及其復(fù)雜的查詢。它主要是基于關(guān)鍵字進(jìn)行查詢,它漫游的領(lǐng)域有Web和 Usenet。支持布爾查詢的"AND","OR"和"NOT",同時(shí)還加上最相近定位"NEAR",允許通配符和"向后"搜索(比如:你可以查找鏈接到 某一頁的所有Web站點(diǎn))。你可以決定是否對(duì)搜索的短語加上權(quán)值,在文檔的什么部位去查找它們。能夠進(jìn)行短語查詢而不是簡(jiǎn)單的單詞查詢的優(yōu)點(diǎn)是很明顯的, 比如,我們想要查找一個(gè)短語"to be or not to be",如果只是把它們分解成單詞的話,這些單詞都是屬于Stop Word,這樣這個(gè)查詢就不會(huì)有任何結(jié)果,但是把它當(dāng)作一個(gè)整體來查詢,就很容易返回一些結(jié)果,比如關(guān)于哈姆雷特或者是莎士比亞等等的信息。系統(tǒng)對(duì)查詢結(jié) 果所得到的網(wǎng)頁的打分是根據(jù)在網(wǎng)頁中所包含的你的搜索短語的多少,它們?cè)谖臋n的什么位置以及搜索短語在文檔內(nèi)部之間的距離來決定的。同時(shí)可以把得到的搜索 結(jié)果翻譯成其他的語言。

      Exite是稱為具有"智能"的搜索引擎,因?yàn)樗⒘艘粋€(gè)基于概念的索引。當(dāng)然,它所謂的"智能"是基 于對(duì)概率統(tǒng)計(jì)的靈活應(yīng)用。它能夠同時(shí)進(jìn)行基于概念和關(guān)鍵字的索引。它能夠索引Web,Usenet和分類的廣告。支持"AND","OR","NOT"等 布爾操作,同時(shí)也可以使用符號(hào)"+"和"-"。缺點(diǎn)是在返回的查詢結(jié)果中沒有指定網(wǎng)頁的尺寸和格式。

      InfoSeek是一個(gè)簡(jiǎn)單 但是功能強(qiáng)大的索引,它的一個(gè)優(yōu)點(diǎn)是有一個(gè)面向主題搜索的可擴(kuò)展的分類。你可以把你的搜索短語和相似的分類目錄的主題短語相互參照,而那些主題短語會(huì)自動(dòng) 加到你的查詢中去。使你的搜索有更好的主題相關(guān)性。同時(shí)它也支持對(duì)圖象的查詢。它能夠漫游Web,Usenet,Usenet FAQs等等。不支持布爾操作,但是可以使用符號(hào)"+"和"-"(相當(dāng)于"AND"和"NOT")

      Yahoo實(shí)際上不能稱為是一 個(gè)搜索引擎站點(diǎn),但是它提供了一個(gè)分層的主題索引,使你能夠從一個(gè)通常的主題進(jìn)入到一個(gè)特定的主題,Yahoo對(duì)Web進(jìn)行了有效的組織和分類。比如你想 要建立一個(gè)網(wǎng)頁,但是你不知道如何操作,為了在Yahoo上找到關(guān)于建立網(wǎng)頁的信息,你可以先在Yahoo上選擇一個(gè)主題:計(jì)算機(jī)和Internet,然 后在這個(gè)主題下,你可以發(fā)現(xiàn)一些子主題,比如:Web網(wǎng)頁制作,CGI編程,JAVA,HTML,網(wǎng)頁設(shè)計(jì)等,選擇一個(gè)和你要找的相關(guān)的子主題,最終你就 可以得到和該子主題相關(guān)的所有的網(wǎng)頁的鏈接。也就是說,如果你對(duì)要查找的內(nèi)容屬于哪個(gè)主題十分清楚的話,通過目錄查詢的方法要比一般的使用搜索引擎有更好 的準(zhǔn)確率。你可以搜索Yahoo的索引,但是事實(shí)上,你并沒有在搜索整個(gè)Web。但是Yahoo提供了選項(xiàng)使你可以同時(shí)搜索其他的搜索引擎,比如: Alta Vista。但是要注意的是Yahoo實(shí)際上只是對(duì)Web的一小部分進(jìn)行了分類和組織,而且它的實(shí)效性也不是很好。

      搜索引擎的基本原理是通過網(wǎng)絡(luò)機(jī)器人定期在web網(wǎng)頁上爬行,然后發(fā)現(xiàn)新的網(wǎng)頁,把它們?nèi)』貋矸诺奖镜氐臄?shù)據(jù)庫中,用戶的查詢請(qǐng)求可以通過查詢本地的數(shù)據(jù)庫來得到。如yahoo每天會(huì)找到大約500萬個(gè)新的網(wǎng)頁。

       搜索引擎的實(shí)現(xiàn)機(jī)制一般有兩種,一種是通過手工方式對(duì)網(wǎng)頁進(jìn)行索引,比如yahoo的網(wǎng)頁是通過手工分類的方式實(shí)現(xiàn)的,它的缺點(diǎn)是Web的覆蓋率比較 低,同時(shí)不能保證最新的信息。查詢匹配是通過用戶寫入的關(guān)鍵字和網(wǎng)頁的描述和標(biāo)題來進(jìn)行匹配,而不是通過全文的匹配進(jìn)行的。第二種是對(duì)網(wǎng)頁進(jìn)行自動(dòng)的索 引,象AltaVista則是完全通過自動(dòng)索引實(shí)現(xiàn)的。這種能實(shí)現(xiàn)自動(dòng)的文檔分類,實(shí)際上采用了信息提取的技術(shù)。但是在分類準(zhǔn)確性上可能不如手工分類。

      搜索引擎一般都有一個(gè)Robot定期的訪問一些站點(diǎn),來檢查這些站點(diǎn)的變化,同時(shí)查找新的站點(diǎn)。一般站點(diǎn)有一個(gè)robot.txt文 件用來說明服務(wù)器不希望Robot訪問的區(qū)域,Robot 都必須遵守這個(gè)規(guī)定。如果是自動(dòng)索引的話,Robot在得到頁面以后,需要對(duì)該頁面根據(jù)其內(nèi)容進(jìn)行索引,根據(jù)它的關(guān)鍵字的情況把它歸到某一類中。頁面的信 息是通過元數(shù)據(jù)的形式保存的,典型的元數(shù)據(jù)包括標(biāo)題、IP地址、一個(gè)該頁面的簡(jiǎn)要的介紹,關(guān)鍵字或者是索引短語、文件的大小和最后的更新的日期。盡管元數(shù) 據(jù)有一定的標(biāo)準(zhǔn),但是很多站點(diǎn)都采用自己的模板。文檔提取機(jī)制和索引策略對(duì)Web搜索引擎的有效性有很大的關(guān)系。高級(jí)的搜索選項(xiàng)一般包括:布爾方法或者是 短語匹配和自然語言處理。一個(gè)查詢所產(chǎn)生的結(jié)果按照提取機(jī)制被分成不同的等級(jí)提交給用戶。最相關(guān)的放在最前面。每一個(gè)提取出來的文檔的元數(shù)據(jù)被顯示給用 戶。同時(shí)包括該文檔所在的URL地址。

      另外有一些關(guān)于某一個(gè)主題的專門的引擎,它們只對(duì)某一個(gè)主題的內(nèi)容進(jìn)行搜索和處理,這樣信息的取全率和精度相對(duì)就比較高。

       同時(shí),有一類搜索引擎,它本身不用Robot去定期的采集網(wǎng)頁。象SavvySearch 和 MetaCrawler是通過向多個(gè)搜索引擎同時(shí)發(fā)出詢問并對(duì)結(jié)果進(jìn)行綜合返回給用戶實(shí)現(xiàn)搜索功能。當(dāng)然實(shí)際上象SavvySearch能夠?qū)Ω鱾€(gè)搜索引 擎的功能進(jìn)行分析和比較,根據(jù)不同的用戶查詢提交給不同的搜索引擎進(jìn)行處理,當(dāng)然用戶自己也可以指定利用哪一個(gè)搜索引擎。

      一個(gè)優(yōu)秀的搜索引擎必須處理以下幾個(gè)問題:1 網(wǎng)頁的分類2 自然語言的處理3 搜索策略的調(diào)度和協(xié)作 4 面向特定用戶的搜索。所以很多搜索引擎不同程度的使用了一些人工智能的技術(shù)來解決這些方面的問題。

      二、網(wǎng)絡(luò)Spider的實(shí)現(xiàn)描述

       現(xiàn)在有很多文章對(duì)Web引擎做了大量的介紹和分析,但是很少有對(duì)它們的實(shí)現(xiàn)做一個(gè)詳細(xì)的描述,這里我們主要來介紹一個(gè)具有基本功能的Web引擎的實(shí)現(xiàn)。 本文,我們以類C++語言的形式來描述Web引擎如何采集網(wǎng)頁并存放到數(shù)據(jù)庫中的過程。同時(shí)描述了如何根據(jù)用戶輸入的關(guān)鍵字查詢數(shù)據(jù)庫并得到相關(guān)網(wǎng)頁的過 程。

      2.1數(shù)據(jù)庫結(jié)構(gòu)

      首先,我們要建立一個(gè)數(shù)據(jù)庫表用來存放我們得到的網(wǎng)頁。這里一般需要建立如下的表:

      1.字典表的建立,事實(shí)上這里是用文檔中有意義的單詞和它們的出現(xiàn)頻率來代表一個(gè)文檔。

      該表(WordDictionaryTbl)主要要包括三個(gè)字段,主要是用來存放和一個(gè)網(wǎng)頁相關(guān)的單詞的情況

    ????url_id? ? 對(duì)每一個(gè)URL的唯一的ID號(hào)
    ? ? word? ? ? 該URL中的經(jīng)過stem的單詞
    ? ? intag? ? 該單詞在該網(wǎng)頁中的出現(xiàn)的次數(shù)

      2.存儲(chǔ)每一個(gè)URL信息的表

      該表(URLTbl)中主要的關(guān)鍵字段有:

    ? rec_id? ? ? ? 每一條記錄的唯一的ID號(hào)
    ? status? ? 得到該URL內(nèi)容的狀態(tài),比如HTTP_STATUS_TIMEOUT表示
    ? ? ? ? ? ? 下載網(wǎng)頁的最大允許超時(shí)
    ? url? ? ? ? URL的字符串名稱
    ? content_type? ? ? 內(nèi)容的類型
    ? last_modified? ? 最新的更改時(shí)間
    ? title? ? ? ? ? ? 該URL的標(biāo)題
    ? docsize? ? ? ? ? 該URL的文件的尺寸
    ? last_index_time? 最近一次索引的時(shí)間
    ? next_index_time? 下一次索引的時(shí)間
    ? tag? ? 對(duì)于網(wǎng)頁,用來表示它的類型,比如:是text,或者是html,
    ? ? ? ? ? ? ? ? ? ? 或者是圖片等等
    ? hops? ? ? ? ? ? ? 得到文件時(shí)候的曾經(jīng)失敗的次數(shù)
    ? keywords? ? ? ? ? 對(duì)于網(wǎng)頁,和該網(wǎng)頁相關(guān)的關(guān)鍵字
    ? description? ? ? 對(duì)于網(wǎng)頁,指網(wǎng)頁的內(nèi)容的描述
    ? lang? ? ? ? ? ? ? 文檔所使用的語言

       3.因?yàn)榫W(wǎng)頁中有很多單詞是一些介詞和語氣助詞或者是非常常用的常用詞,它們本身沒有多少意義。比如:英語中的about,in,at,we,this 等等。中文中的如"和","一起","關(guān)于"等等。我們統(tǒng)一的把它們稱為停止詞(stop word)。所以我們要建立一個(gè)表,來包括所有這些停止詞。該表(StopWordTbl)主要有兩個(gè)字段。
    word char(32)? ? 表示那些停止詞
    lang char(2)? ? ? 表示所使用的語言

      4.我們要建立一個(gè)關(guān)于robot的表,我們?cè)谇懊嬲f過,所有的網(wǎng)站一般都有一個(gè)robot.txt文件用來表示網(wǎng)絡(luò)上的robot可以訪問的權(quán)限。該表(RobotTbl)主要有以下字段。
    ? ? hostinfo? ? ? ? ? Web站點(diǎn)主機(jī)的信息
    ? ? path? ? ? ? ? ? ? 不允許robot訪問的目錄

      5.建立我們需要屏蔽的那些網(wǎng)頁(比如一些內(nèi)容不健康的或者沒有必要去搜索的站點(diǎn))的一張表(ForbiddenWWWTbl),主要的字段就是網(wǎng)頁的URL。

       6.另外我們需要建立一個(gè)我們所要得到的文件類型的表(FileTypeTbl),比如,對(duì)于一個(gè)簡(jiǎn)單的Web搜索引擎,我們可能只需要得到后綴為. html,htm,.shtml和txt的類型文件。其他的我們只是簡(jiǎn)單的忽略它們。主要的字段就是文件的類型和說明。

      其中關(guān)于停止詞的表的內(nèi)容是我們要實(shí)現(xiàn)要根據(jù)各種語言的統(tǒng)計(jì)結(jié)果,把那些意義不大的單詞放進(jìn)去。關(guān)于文檔單詞、URL和Robot的表的內(nèi)容都是在獲取Web網(wǎng)頁的時(shí)候動(dòng)態(tài)增加記錄的。

      2.2 具體網(wǎng)頁獲取算法描述

      具體的網(wǎng)頁的獲取步驟是這樣的:

       我們可以設(shè)定我們的搜索程序最大可以開的線程的數(shù)目,然后這些線程可以同時(shí)在網(wǎng)上進(jìn)行搜索,它們根據(jù)數(shù)據(jù)庫中已有的關(guān)于網(wǎng)頁的信息,找出那些需要更新的 網(wǎng)頁(如何判斷哪些網(wǎng)頁需要更新是一個(gè)值得研究的過程,現(xiàn)在有很多啟發(fā)式和智能的算法,基本上是基于統(tǒng)計(jì)規(guī)律進(jìn)行建模。最簡(jiǎn)單的當(dāng)然是設(shè)定一個(gè)時(shí)間范圍, 在某個(gè)時(shí)間范圍以前的網(wǎng)頁被重新去搜索一遍),然后判斷那些網(wǎng)頁是否在屏蔽表中,如果是的話,就從關(guān)于URL的表中刪除該條記錄。否則,我們就到相應(yīng)的 WWW站點(diǎn)去得到URL指定的文件(這里需要注意的是根據(jù)不同的URL的特點(diǎn),需要使用不同的協(xié)議,比如對(duì)于FTP站點(diǎn)要采用FTP協(xié)議,對(duì)于HTTP站 點(diǎn)要采用HTTP協(xié)議,新聞?wù)军c(diǎn)要采用NNTP協(xié)議等等)事實(shí)上,我們先得到關(guān)于該網(wǎng)頁的頭信息,如果該網(wǎng)頁的最新修改時(shí)間和我們最近提取的時(shí)間是一樣的 話,表示該網(wǎng)頁內(nèi)容沒有任何更新,則我們就不必去得到它的內(nèi)容,只需要修改最近一次更新它的時(shí)間為當(dāng)前的時(shí)間就可以了。如果該網(wǎng)頁最近做了修改,我們就要 得到該網(wǎng)頁,并對(duì)它的內(nèi)容進(jìn)行分析,主要要包括和它相關(guān)的鏈接,把它們加到相應(yīng)的數(shù)據(jù)庫中,同時(shí)判斷網(wǎng)頁所包含的各種其他的文件,如文本文件、圖形文件、 聲音文件和其他多媒體文件是否是我們所需要的文件,如果是的話,就把它加到我們響應(yīng)的數(shù)據(jù)庫中。同時(shí)要根據(jù)網(wǎng)頁的內(nèi)容提取所有的有意義的單詞和它們的出現(xiàn) 的次數(shù),放到相應(yīng)的數(shù)據(jù)庫中。為了更好的描述這個(gè)過程,我們來看跟這個(gè)過程相關(guān)的主要的幾個(gè)對(duì)象和數(shù)據(jù)結(jié)構(gòu)。對(duì)象主要是針對(duì)三個(gè)層次來講的。第一層是針對(duì) WWW服務(wù)器,第二層是針對(duì)每一個(gè)頁面,第三層是針對(duì)每一個(gè)頁面的全文的索引。

      2.3 和實(shí)現(xiàn)相關(guān)的主要類對(duì)象和功能描述下面的結(jié)構(gòu)是針對(duì)一個(gè)站點(diǎn)來說的。

    ? ? Class? CServer {
    ? ? 主要的屬性有:
    ????char *url;? ? ? ? ? ? //WWW站點(diǎn)的URL名稱
    ????char *proxy;? ? ? ? ? //使用的代理的名稱
    ????char *basic_auth;? ? ? //進(jìn)行基本的HTTP認(rèn)證
    ????int? proxy_port;? ? ? //代理的端口號(hào)
    ????int? period;? ? ? ? ? //再次索引的周期
    ????int? net_errors;? ? ? //網(wǎng)絡(luò)連接不通的次數(shù)
    ????int? max_net_errors;? //可以允許的最大的網(wǎng)絡(luò)錯(cuò)誤
    ????int? read_timeout;? ? //下載文件允許的最大的延遲
    ????int? maxhops;? ? ? ? ? //表示URL可以最大跳轉(zhuǎn)的深度
    ????int? userobots;? ? ? ? //是否遵守robot.txt中的約定
    ????int? bodyweight;? // 在< body >....< /body >之間的單詞的權(quán)重
    ????int? titleweight; // 在< title >....< /title >之間的單詞的權(quán)重
    ????int? urlweight;? // 在文檔的URL中的單詞的權(quán)重
    ????int descweight;//在? ? < META
    NAME="Description"? ? ? ? Content="..." >之間單詞的權(quán)重
    ????int? keywordweight; //在< META NAME="Keywords" Content="..." >
    ? 之間的單詞的權(quán)重

      主要方法有:
    FindServer();//用來查找該服務(wù)器是否存在并可以連接
    FillDefaultAttribute() //用來針對(duì)所有的WWW服務(wù)器填寫默認(rèn)的屬};

    以上的對(duì)象中的成員變量是和一個(gè)站點(diǎn)相關(guān)的參數(shù)的設(shè)置,我們對(duì)所有的站點(diǎn)有一個(gè)默認(rèn)的設(shè)置,但是可以對(duì)某些站點(diǎn)做一些特殊的設(shè)置。這些設(shè)置可以在配置文件中設(shè)定。
      下面是關(guān)于文檔的結(jié)構(gòu)的主要的數(shù)據(jù)成員:

    Class CNetDocument
    ? ? 主要屬性有:
    ? ? int????url_id; //該URL的ID號(hào)
    ? ? int????status;? //獲取該文檔時(shí)候的狀態(tài)
    ? ? int????size;? //文檔的尺寸
    int????tag;? //和該文檔相關(guān)的標(biāo)簽,表示該文檔是
    HTML,TEXT或者是其他類型
    ? ? int????hops;? ? //URL跳轉(zhuǎn)的次數(shù)
    ? ? char????*url; //和該文檔相關(guān)的URL的名稱
    ? ? char????*content_type;? ? ? //該內(nèi)容的類型
    ? ? char????*last_modified;? ? //最近一次的更新時(shí)間
    ? ? char????*title;? ? ? ? ? ? //該文檔的標(biāo)題
    ? ? char????*last_index_time;? //上次索引的時(shí)間
    ? ? char????*next_index_time;? //下次索引的時(shí)間
    ? ? char????*keywords;? ? ? ? ? //該文檔中的關(guān)鍵字
    ? ? char????*description;? ? ? //該文檔的描述

    ? 主要方法有:
    ? FillDocInfo(…) //根據(jù)數(shù)據(jù)庫,得到該文檔相關(guān)信息
    ? AddHerf(…)? ? //加入網(wǎng)頁中存在的新的鏈接的網(wǎng)址
    ? DeleteURL(…)? //刪除一個(gè)存在的網(wǎng)址
    ? CanGetThisURL(…) //根據(jù)配置決定是否去得到該網(wǎng)頁
    ? //下面三個(gè)方法是根據(jù)不同的URL,用不同的協(xié)議去獲得文檔
    ? NNTPGet(…)? ? ?
    ? FTPGet(….)
    ? HTTPGet(….)
    ? ParseHead(…)? //如果是HTTP協(xié)議得到的話,分析頭信息
    ? ParseMainBody(…)? ? //對(duì)獲得的文檔的主體進(jìn)行分析
    ? ServerResponseType (….)? //得到服務(wù)器端的響應(yīng)消息
    ? UpdateURLDB(….)? //更新的數(shù)據(jù)入庫
    } ;

      事實(shí)上,我們?cè)谝崛∫粋€(gè)網(wǎng)頁的時(shí)候,都要建立一個(gè)CNetDocument對(duì)象,然后再對(duì)這個(gè)網(wǎng)頁進(jìn)行分析的時(shí)候,把相關(guān)的內(nèi)容放到這個(gè)CNetDocument的成員變量里面。下面是關(guān)于頁面全文索引的結(jié)構(gòu)的主要數(shù)據(jù)成員:
    Class CIndexer {
    主要屬性有:
    ? char????*url;? ? ? //我們要處理的文檔相關(guān)的URL的名稱
    ? int mwords;????? //? 我們事先設(shè)定的一個(gè)網(wǎng)頁的最大的單詞數(shù)目
    ????int nwords;????????? // 實(shí)際的得到的單詞的數(shù)目
    ????int swords;????????? // 我們已經(jīng)排序的單詞的數(shù)目
    ????WORD *Word;????? //所有單詞的內(nèi)容
    ????char *buf;? ? ? //我們?yōu)槲臋n所分配的空間
    主要方法有:
    ? InitIndexer(…)? ? //進(jìn)行初始設(shè)置和分配
    ? ParseGetFile(…)? //對(duì)得到的網(wǎng)頁進(jìn)行全文索引
    ? AddWord(…)? ? //把網(wǎng)頁的可以索引的單詞加到Word數(shù)組中去
    ? InToDB(….)? ? //關(guān)于網(wǎng)頁全文索引的信息入庫
    };

      進(jìn)行網(wǎng)頁提取前,我們要建立一個(gè)CIndexer對(duì)象,它主要是用來對(duì)網(wǎng)頁進(jìn)行全文的索引。一般來說我們只對(duì)兩種類型的URL進(jìn)行全文索引,一個(gè)是text/html,另外一個(gè)是text/plain。其中WORD的數(shù)據(jù)結(jié)構(gòu)如下:
    ? ? ? ? typedef struct word_struct {
    ????int count;? //該單詞出現(xiàn)的次數(shù)
    ????int code;? //該單詞的正常的形式,
    比如單詞可能為 encouraging,它的正常的形式應(yīng)該為
    encourage,這其實(shí)是一種對(duì)單詞的stem。
    即我們只取單詞的主干部分。
    ????char *word;? //該單詞的內(nèi)容
    } WORD;

      以下的結(jié)構(gòu)是和網(wǎng)頁中的一些鏈接的對(duì)象相關(guān)的一個(gè)數(shù)據(jù)結(jié)構(gòu)
    ? ? typedef struct href_struct {
    ????char *href;? ? //該鏈接的名稱
    ????int hops;? ? ? //發(fā)生的跳轉(zhuǎn)次數(shù)
    ????int stored;? ? //是否已經(jīng)存儲(chǔ)到數(shù)據(jù)庫中
    } HREF;
    ?

      所有需要更新的和新產(chǎn)生的URL都被放到這個(gè)結(jié)構(gòu)中,當(dāng)它的數(shù)量超過一定的范圍以后,被一次性的存入數(shù)據(jù)庫。
      關(guān)于URL的一個(gè)數(shù)據(jù)結(jié)構(gòu)如下:

    typedef struct url {
    char *schema; //表示該URL是通過什么協(xié)議得到的,比如HTTP,
    ? ? ? ? ? ? ? FTP,NNTP等。
    char *specific;? ? //主機(jī)的名稱加上路徑
    char *hostinfo;? ? //主機(jī)的名稱加上相關(guān)的協(xié)議端口
    char *hostname;? ? //主機(jī)的名稱
    char *path;? ? ? ? //在主機(jī)的具體的路徑
    char *filename;? ? //文件的名稱
    char *anchor;? ? ? //相關(guān)的anchor
    int? port;? ? ? ? //協(xié)議相關(guān)的端口
    } URL;

      這是針對(duì)URL的一些相關(guān)的屬性的描述的一個(gè)數(shù)據(jù)結(jié)構(gòu)。事實(shí)上在數(shù)據(jù)庫中,我們存儲(chǔ)的只是對(duì)網(wǎng)頁的描述和對(duì)一些文本和HTML頁面的關(guān)鍵詞的索引信息。我們并不存儲(chǔ)網(wǎng)頁的實(shí)際的內(nèi)容。

      三、用戶查詢實(shí)現(xiàn)描述

      關(guān)于對(duì)用戶提交的查詢請(qǐng)求的實(shí)現(xiàn)分析:

      用戶想要查詢某一方面的信息一般都是通過提供和該領(lǐng)域相關(guān)的幾個(gè)關(guān)鍵字來進(jìn)行的。

      我們來看一下關(guān)于用戶查詢的相關(guān)的數(shù)據(jù)結(jié)構(gòu)和類:

      下面是一個(gè)關(guān)于單詞和它的權(quán)值的基本結(jié)構(gòu):

    ? typedef struct word_weight_pair
    ? ? {
    ? ? ? char word[WORD_LEN];
    ? ? ? int weight;
    ? ? }word_weight_pair;
    ? ?

      下面的類主要是用來對(duì)用戶的查詢進(jìn)行處理和分析:
    ? ? Class CUserQuery
    ? ? {
    char m_UserQuery[MAX_QUERYLEN];? //用戶的查詢表達(dá)式
    CPtrArray word_weight_col;
    //是關(guān)于結(jié)構(gòu)word_weight_pair的動(dòng)態(tài)數(shù)組
    int m_maxReturnSum;? //用戶希望返回的最多的網(wǎng)頁數(shù)
    int search_mode;
    CObArray m_returnDoc;? //是關(guān)于CNetDocument對(duì)象的一個(gè)動(dòng)態(tài)數(shù)組
    NormalizeWord(char* OneWord);? //對(duì)單詞進(jìn)行歸整化,即Stem.
    Find(char* odbcName);? //進(jìn)行數(shù)據(jù)庫查找和匹配
    };

      系統(tǒng)實(shí)現(xiàn)的基本的步驟如下:

      1.對(duì)用戶輸入的查詢表達(dá)式進(jìn)行分析。事實(shí)上,我們?cè)谇懊娴腟pider搜索過程中對(duì)文檔的表示是通過關(guān)鍵字形式描述的,每一個(gè)文檔可以表示為這樣的一個(gè)集合

    ? ? 其中 ::=< 單詞或短語名稱 >< 單詞或短語的權(quán)值 >

      實(shí)際上就是采用矢量空間的表示方法來表示的文檔。

       我們對(duì)用戶輸入的查詢表達(dá)式也采用矢量空間的表示方法。我們認(rèn)為用戶輸入的關(guān)鍵字的順序代表了它的重要性的程度,所以對(duì)于位置靠前的單詞有相對(duì)比較高的 優(yōu)先級(jí),同時(shí)我們對(duì)所有的內(nèi)容以短語或者是單詞為最小原子,進(jìn)行Stem操作,即象前面所提到的:比如單詞Encouraging就轉(zhuǎn)化成 Encourage的格式。然后去掉那些Stop Word,比如is ,as等等的單詞,這些單詞存放在StopWordTbl表中。 然后把所有歸整化后的內(nèi)容放入動(dòng)態(tài)數(shù)組word_weight_col中去。

      2.對(duì)于動(dòng)態(tài)數(shù)組word_weight_col中 的每一個(gè)元素,即結(jié)構(gòu)word_weight_pair(包括單詞和該單詞的權(quán)重),我們從表WordDictionaryTbl中可以找到和這些單詞相 關(guān)的記錄,這些記錄應(yīng)該是包括了所有的在word_weight_col中的單詞。

      進(jìn)行網(wǎng)頁是否和查詢相匹配的計(jì)算。匹配計(jì)算的 過程如下:首先我們對(duì)所有的記錄按URL地址進(jìn)行排序。因?yàn)榭赡芎脦讞l記錄對(duì)應(yīng)的是一個(gè)URL,然后對(duì)每一個(gè)網(wǎng)頁進(jìn)行打分,每一條記錄的單詞權(quán)值為 INITSCORE*WEIGHT+(TOTALTIMES-1)*WEIGHT* INCREMENT。其中INITSCORE為每一個(gè)單詞的基準(zhǔn)分?jǐn)?shù),TOTALTIMES為該單詞在網(wǎng)頁中的出現(xiàn)的次數(shù),WEIGHT是該單詞在不同的 內(nèi)容段出現(xiàn)有不同的權(quán)值(比如在KEYWORD段,或者是標(biāo)題段,或者是內(nèi)容段等等)。INCREMENT是該單詞每多出現(xiàn)一次所增加的分?jǐn)?shù)。

      3.根據(jù)用戶指定的m_maxReturnSum,顯示匹配程度最高的前m_maxReturnSum頁。

      四、結(jié)束語

       我們利用上面所討論的機(jī)制,在WINDOWS NT操作系統(tǒng)下,用VC++和SQL SERVER實(shí)現(xiàn)了一個(gè)Web搜索引擎的網(wǎng)頁搜集過程。在建立了一個(gè)基本的搜索引擎的框架以后,我們可以基于這個(gè)框架,實(shí)現(xiàn)一些我們自己設(shè)計(jì)的算法,比如 如何更好的進(jìn)行Spider的調(diào)度,如何更好的進(jìn)行文檔的歸類,如何更好的理解用戶的查詢,用來使Web搜索引擎具有更好的智能性和個(gè)性化的特點(diǎn)。

    posted @ 2006-11-11 21:37 Coolfiry 閱讀(471) | 評(píng)論 (0)編輯 收藏

         摘要: 1.?? 目標(biāo) 使用 apache 和 tomcat 配置一個(gè)可以應(yīng)用的 web 網(wǎng)站,要達(dá)到以下要求: 1、? Apache 做為 HttpServer ,后面連接多個(gè) tomcat...  閱讀全文

    posted @ 2006-11-06 17:20 Coolfiry 閱讀(724) | 評(píng)論 (0)編輯 收藏

    JDBC學(xué)習(xí)筆記
    2004-9-13?????星期一?????小雨

    l.?連接到數(shù)據(jù)庫的方法
    答:1)?ODBC(Open?Database?Connectivity)
    ???????一個(gè)以C語言為基礎(chǔ)訪問SQL為基礎(chǔ)數(shù)據(jù)庫引擎的接口,它提供了一致的接口用于和數(shù)據(jù)庫溝通以及訪問數(shù)據(jù)。
    ????2)?JDBC
    ???????Java版本的ODBC

    2.?JDBC應(yīng)用編程接口
    答:JDBC應(yīng)用編程接口是:
    ????1)?標(biāo)準(zhǔn)的數(shù)據(jù)訪問接口,可以連到不同的數(shù)據(jù)庫;
    ????2)?JAVA編程語言的一組類和接口。
    ????JDBC應(yīng)用編程接口能夠:
    ????1)?連接到數(shù)據(jù)庫;
    ????2)?發(fā)SQL查詢字符串到數(shù)據(jù)庫;
    ????3)?處理結(jié)果。
    ????JDBC應(yīng)用編程接口有二個(gè)主要的部分:
    ????1)?JAVA應(yīng)用程序開發(fā)接口面向JAVA應(yīng)用程序開發(fā)者;
    ????2)?JDBC驅(qū)動(dòng)程序開發(fā)接口
    ????
    3.?JDBC?Driver
    答:1)?一大堆實(shí)現(xiàn)了JDBC類和接口的類;
    ????2)?提供了一個(gè)實(shí)現(xiàn)java.sql.Driver接口的類。

    4.?JDBC?Driver的四種類型
    答:1)?JDBC-ODBC橋
    ????由ODBC驅(qū)動(dòng)提供JDBC訪問
    ????2)?本地API
    ????部分Java?driver把JDBC調(diào)用轉(zhuǎn)化成本地的客戶端API
    ????3)?JDBC-net
    ????純的Java?driver,將JDBC調(diào)用轉(zhuǎn)入DBMS,與網(wǎng)絡(luò)協(xié)議無關(guān)。然后通過服務(wù)器將調(diào)用轉(zhuǎn)為DBMS協(xié)議。
    ????4)?本地協(xié)議
    ????純的java?driver,將JDBC調(diào)用直接轉(zhuǎn)為DBMS使用的網(wǎng)絡(luò)協(xié)議

    5.?JDBC開發(fā)者接口
    答:1)?java.sql--java?2平臺(tái)下JDBC的主要功能,標(biāo)準(zhǔn)版(J2SE)
    ????2)?javax.sql--java?2平臺(tái)下JDBC增強(qiáng)功能,企業(yè)版(J2EE)

    6.?使用URL確認(rèn)數(shù)據(jù)庫
    答:我們使用URL來確定一個(gè)數(shù)據(jù)庫(正確的Driver,正確的主機(jī),正確的協(xié)議,正確的協(xié)議,正確的用戶名和密碼);
    ????語法:protocol:subprotocol:subname
    ????范例:jdbc:db2:MyTest
    ??????????jdbc:db2://localhost:6789/MyTest

    7.?javax.sql包JDBC2.0的增強(qiáng)功能
    答:1)?數(shù)據(jù)源接口;
    ????2)?連接池;
    ????3)?分布式交易;
    ????4)?行集;

    8.?創(chuàng)建一個(gè)基本的JDBC應(yīng)用
    答:1)?步驟一:注冊(cè)一個(gè)driver;
    ????2)?步驟二:建立一個(gè)到數(shù)據(jù)庫的連接;
    ????3)?步驟三:創(chuàng)建一個(gè)statement;
    ????4)?步驟四:執(zhí)行SQL語句;
    ????5)?步驟五:處理結(jié)果;
    ????6)?步驟六:關(guān)閉JDBC對(duì)象

    9.?注冊(cè)一個(gè)Driver(步驟一)
    答:1)?driver被用于連接到數(shù)據(jù)庫;
    ????2)?JDBC應(yīng)用編程接口使用第一個(gè)能成功連接到給定URL的driver;
    ????3)?在同一時(shí)間可以裝載多個(gè)driver

    10.注冊(cè)一個(gè)driver的方法:
    答:1)?使用類loader(裝載;實(shí)例化;注冊(cè)入DriverManager)
    ???????a.?Class.forName("Com.ibm.db2.jdbc.app.DB2Driver");
    ???????b.?Class.forName("Com.ibm.db2.jdbc.net.DB2Driver");
    ???????c.?Class.forName("Com.microsoft.jdbc.sqlServer.SQLServerDriver);
    ???????d.?Class.forName("oracl.jdbc.driver.OracleDriver");
    ???????e.?Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
    ????2)?實(shí)例化一個(gè)Driver
    ???????a.?Driver?drv?=?new?COM.cloudscape.core.RmiJdbcDriver();

    2004-9-14?????星期二?????陰

    1.?建立一個(gè)到數(shù)據(jù)庫的連接(步驟二)
    答:DriverManager調(diào)用getConnection(urlString)方法,實(shí)際上調(diào)用的是driver的connect(urlString)方法;
    ????1)?當(dāng)一個(gè)driver肯定地對(duì)應(yīng)到一個(gè)數(shù)據(jù)庫URL,DriverManager建立一個(gè)連接;
    ????2)?當(dāng)沒有driver匹配,返回null然后下一個(gè)driver被檢驗(yàn);
    ????3)?假如沒有建立連接,拋出一個(gè)SQLExcepiton異常

    2.?經(jīng)常使用的一些JDBC?URL
    答:1)?JDBC-ODBC:?jdbc:odbc:<DB>
    ????2)?Oracle:?jdbc:oracle:oci:@<sid>?or?jdbc:oracle:thin:@<SID>
    ????3)?Weblogic?MS-SQL:?jdbc:weblogic:mssqlserver4:<DB>@<HOST>:<PORT>
    ????4)?DB2:?jdbc:db2:MyTest?or?jdbc.db2://localhost:6789/MyTest(需要用戶名和密碼)

    3.?Driver連接方法
    答:1)?創(chuàng)建一個(gè)到指定Driver實(shí)例的直接調(diào)用;
    ????2)?避免一般訪問的問題
    ???????Driver?drv?=?new?COM.ibm.db2.jdbc.app.DB2Driver();
    ???????Connection?con?=?null;
    ???????try?{con?=?drv.connect("jdbc:db2:MyTest",new?Properties())}
    ???????catch(SQLException?e){}

    4.?創(chuàng)建一個(gè)Statement(步驟三)
    答:1)?Statement的三個(gè)接口:
    ???????a.?Statement;
    ???????b.?PreparedStatement(繼承自Statement);
    ???????c.?CallableStatement(繼承自PreparedStatement);
    ????2)?使用方法Connection.createStatement()得到一個(gè)Statement對(duì)象

    5.?PreparedStatement對(duì)象
    答:1)?調(diào)用ProparedStatement比statement更為高效;
    ????2)?繼承自Statement;
    ????3)?語法:PreparedStatement?pstm?=?connection.prepareStatement(sqlString);

    6.?CallableStatement對(duì)象
    答:1)?通過CallableStatement調(diào)用數(shù)據(jù)庫中的存儲(chǔ)過程;
    ????2)?繼承自PreparedStatement;
    ????3)?CallableStatement?cstm?=?connection.prepareCall("{call?return_student[?,?]}");
    ???????cstm.setString(1,"8623034");
    ???????cstm.registerOutparameter(2,?Types.REAL);
    ???????cstm.execute();
    ???????float?gpa?=?cstm.getFloat(2);

    7.?Statement接口的比較
    答:?????????????|?Statement???????????|?PreparedStatement?????????|??CallableStatement
    ????------------------------------------------------------------------------------
    ????寫代碼位置???|???客戶端????????????|?客戶端????????????????????|??服務(wù)器端
    ????------------------------------------------------------------------------------
    ????寫代碼位置???|???客戶端????????????|?服務(wù)器端??????????????????|??服務(wù)器端
    ????------------------------------------------------------------------------------
    ????編寫代碼技術(shù)?|Java,SQL操作????????|Java,SQL操作??????????????|??數(shù)據(jù)庫的程序語言,如PL/SQL
    ????------------------------------------------------------------------------------
    ????可配置性?????|???高????????????????|第一次高,以后低???????????|??低
    ????------------------------------------------------------------------------------
    ????可移植性?????|???高????????????????|假設(shè)支持PreparedStatement的話高????
    ????------------------------------------------------------------------------------
    ????傳輸效率?????|???低????????????????|第一次低,以后高???????????|??高

    8.?執(zhí)行SQL?Statement(步驟四)
    答:通過接口方法將SQL語句傳輸至?認(rèn)的數(shù)據(jù)庫連接,返回結(jié)果可能是一個(gè)數(shù)據(jù)表,可以通過java.sql.ResultSet訪問。
    ????1)?Statement的接口方法:
    ????a.?executeQuery(sqlString):?執(zhí)行給定的SQL聲明,返回一個(gè)結(jié)果集(ResultSet)對(duì)象;
    ????b.?executeUpdate(sqlString):?執(zhí)行給定的SQL聲明,可以是INSERT、UPDATE或DELETE聲明,也可以是SQL?DDL聲明;
    ????c.?execute(sqlString):?執(zhí)行給定的SQL聲明。

    9.?處理結(jié)果(步驟五)
    答:1)?使用結(jié)果集(ResultSet)對(duì)象的訪問方法獲取數(shù)據(jù);
    ???????a.?next():下一個(gè)記錄
    ???????b.?first():第一個(gè)記錄
    ???????c.?last():最后一個(gè)記錄
    ???????d.?previous():上一個(gè)記錄
    ????2)?通過字段名或索引取得數(shù)據(jù)
    ????3)?結(jié)果集保持了一個(gè)指向了當(dāng)前行的指針,初始化位置為第一個(gè)記錄前。

    10.?關(guān)閉JDBC對(duì)象(步驟六)
    答:1)?首先關(guān)閉記錄集;
    ????2)?其次關(guān)閉聲明;
    ????3)?最后關(guān)閉連接對(duì)象。

    11.?數(shù)據(jù)表和類對(duì)應(yīng)的三種關(guān)系:
    答:1)?一個(gè)表對(duì)應(yīng)一個(gè)類;
    ????2)?一個(gè)表對(duì)應(yīng)相關(guān)類;
    ????3)?一個(gè)表對(duì)應(yīng)整個(gè)類關(guān)系層

    12.?類間關(guān)系的幾種表設(shè)計(jì):
    答:1)?多對(duì)一,
    ????2)?一對(duì)一:?
    ????3)?一對(duì)多:
    ????4)?多對(duì)多:

    13.?SQL數(shù)據(jù)類型及其相應(yīng)的Java數(shù)據(jù)類型
    答:SQL數(shù)據(jù)類型?????????????????????Java數(shù)據(jù)類型??????????????說明
    ????------------------------------------------------------------------
    ????INTEGER或者INT??????????????????int?????????????????????通常是個(gè)32位整數(shù)
    ????SMALLINT????????????????????????short???????????????????通常是個(gè)16位整數(shù)
    ????NUMBER(m,n)?DECIMAL(m,n)????????Java.sql.Numeric????????合計(jì)位數(shù)是m的定點(diǎn)十進(jìn)制數(shù),小數(shù)后面有n位數(shù)
    ????DEC(m,n)????????????????????????Java.sql.Numeric????????合計(jì)位數(shù)是m的定點(diǎn)十進(jìn)制數(shù),小數(shù)后面有n位數(shù)
    ????FLOAT(n)????????????????????????double??????????????????運(yùn)算精度為n位二進(jìn)制數(shù)的浮點(diǎn)數(shù)
    ????REAL????????????????????????????float???????????????????通常是32位浮點(diǎn)數(shù)
    ????DOUBLE??????????????????????????double??????????????????通常是64位浮點(diǎn)數(shù)
    ????CHARACTER(n)或CHAR(n)???????????String??????????????????長(zhǎng)度為n的固定長(zhǎng)度字符串
    ????VARCHAR(n)??????????????????????String??????????????????最大長(zhǎng)度為n的可變長(zhǎng)度字符串
    ????BOOLEAN?????????????????????????boolean?????????????????布爾值
    ????DATE????????????????????????????Java.sql.Date???????????根據(jù)具體設(shè)備而實(shí)現(xiàn)的日歷日期
    ????TIME????????????????????????????Java.sql.Time???????????根據(jù)具體設(shè)備而實(shí)現(xiàn)的時(shí)戳
    ????TIMESTAMP???????????????????????Java.sql.Timestamp??????根據(jù)具體設(shè)備而實(shí)現(xiàn)的當(dāng)日日期和時(shí)間
    ????BLOB????????????????????????????Java.sql.Blob???????????二進(jìn)制大型對(duì)象
    ????CLOB????????????????????????????Java.sql.Clob???????????字符大型對(duì)象
    ????ARRAY???????????????????????????Java.sql.Array
    ????

    2004-9-15?????星期三??????陰

    1.?元數(shù)據(jù)
    答:關(guān)于數(shù)據(jù)的信息,例如類型或者容量。通過JDBC?API可以訪問:
    ????1)?數(shù)據(jù)庫元數(shù)據(jù);
    ???????a.?使用connection.getMetadata方法返回DataMetaData引用
    ???????b.?能夠使用isReadOnly此類方法獲取信息
    ????2)?結(jié)果集元數(shù)據(jù);
    ???????a.?使用ResultSet.getMetadata方法返回ResultSetMetaData引用
    ???????b.?能夠使用getColumnCount此類方法獲取信息

    2.?事務(wù)處理
    答:1)?一系列的動(dòng)作作為一個(gè)不可分的操作;
    ????2)?JDBC?API中使用事務(wù)處理步驟:
    ???????a.?用false作為參數(shù)調(diào)用setAutoCommit方法;
    ???????b.?執(zhí)行一或多個(gè)關(guān)于數(shù)據(jù)庫的操作;
    ???????c.?調(diào)用commit方法完成改變;
    ???????d.?恢復(fù)上次提交后的改變,調(diào)用rollback方法.

    ???????try
    ???????{
    ??????????con.setAutoCommit(false);
    ??????????Statement?stm?=?con.createStatement();
    ??????????stm.executeUpdate("insert?into?student(name,?age,?gpa)?values('gzhu',?30,?4.8)");
    ??????????stm.commit();
    ???????}
    ???????catch(SQLException?e)
    ???????{
    ??????????try
    ??????????{
    ?????????????con.rollback();
    ??????????}
    ??????????catch(Exception?e)
    ??????????{
    ??????????}
    ???????}

    3.?并發(fā)控制
    答:1)?設(shè)置隔離級(jí)別方法:setTransactionIsolation
    ????2)?隔離級(jí)別靜態(tài)變量
    ???????a.?TRANSACTION_NONE:只讀的數(shù)據(jù)字典;
    ???????b.?TRANSACTION_READ_UNCOMMITTED:只讀未提交數(shù)據(jù);
    ???????c.?TRANSACTION_READ_COMMITTED:只讀未提交數(shù)據(jù);
    ???????d.?TRANSACTION_REPEATABLE_READ:重復(fù)讀取數(shù)據(jù);
    ???????e.?TRANSACTION_SERIALIZABLE:無論做什么操作都不許別人動(dòng)。
    ????3)?示例:con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);

    4.?JDBC?2.0?應(yīng)用程序編程接口增強(qiáng)功能
    答:1)?ResultSet增強(qiáng):
    ???????a.?可以回卷;
    ???????b.?可以修改;
    ???????設(shè)置示例:Statement?stm?=?con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
    ????2)?Statement增強(qiáng)了批量修改能力(batch?updates);
    ????3)?更高級(jí)的數(shù)據(jù)類型(例:Struct)。

    5.?JDBC?2.0標(biāo)準(zhǔn)擴(kuò)展
    答:1)?JNDI(Java?Naming?and?Directory?Interface):?解決離散狀態(tài)下Object的查找;
    ????2)?連接池:在內(nèi)存中保存了一個(gè)數(shù)據(jù)庫連接,不需要注冊(cè)驅(qū)動(dòng)器,提高性能的重要方法。

    posted @ 2006-11-03 10:14 Coolfiry 閱讀(237) | 評(píng)論 (0)編輯 收藏

    問題引入:
    在實(shí)習(xí)過程中發(fā)現(xiàn)了一個(gè)以前一直默認(rèn)的錯(cuò)誤,同樣char *c = "abc"和char c[]="abc",前者改變其內(nèi)

    容程序是會(huì)崩潰的,而后者完全正確。
    程序演示:
    測(cè)試環(huán)境Devc++
    代碼
    #include <iostream>
    using namespace std;

    main()
    {
    ?? char *c1 = "abc";
    ?? char c2[] = "abc";
    ?? char *c3 = ( char* )malloc(3);
    ?? c3 = "abc";
    ?? printf("%d %d %s\n",&c1,c1,c1);
    ?? printf("%d %d %s\n",&c2,c2,c2);
    ?? printf("%d %d %s\n",&c3,c3,c3);
    ?? getchar();
    }??
    運(yùn)行結(jié)果
    2293628 4199056 abc
    2293624 2293624 abc
    2293620 4199056 abc

    參考資料:
    首先要搞清楚編譯程序占用的內(nèi)存的分區(qū)形式:
    一、預(yù)備知識(shí)—程序的內(nèi)存分配
    一個(gè)由c/C++編譯的程序占用的內(nèi)存分為以下幾個(gè)部分
    1、棧區(qū)(stack)—由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于

    數(shù)據(jù)結(jié)構(gòu)中的棧。
    2、堆區(qū)(heap)—一般由程序員分配釋放,若程序員不釋放,程序結(jié)束時(shí)可能由OS回收。注意它與數(shù)據(jù)

    結(jié)構(gòu)中的堆是兩回事,分配方式倒是類似于鏈表,呵呵。
    3、全局區(qū)(靜態(tài)區(qū))(static)—全局變量和靜態(tài)變量的存儲(chǔ)是放在一塊的,初始化的全局變量和靜態(tài)

    變量在一塊區(qū)域,未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域。程序結(jié)束后由系統(tǒng)

    釋放。
    4、文字常量區(qū)—常量字符串就是放在這里的。程序結(jié)束后由系統(tǒng)釋放。
    5、程序代碼區(qū)
    這是一個(gè)前輩寫的,非常詳細(xì)
    //main.cpp
    ? int a=0;??? //全局初始化區(qū)
    ? char *p1;?? //全局未初始化區(qū)
    ? main()
    ? {
    ?? int b;棧
    ?? char s[]="abc";?? //棧
    ?? char *p2;???????? //棧
    ?? char *p3="123456";?? //123456\0在常量區(qū),p3在棧上。
    ?? static int c=0;?? //全局(靜態(tài))初始化區(qū)
    ?? p1 = (char*)malloc(10);
    ?? p2 = (char*)malloc(20);?? //分配得來得10和20字節(jié)的區(qū)域就在堆區(qū)。
    ?? strcpy(p1,"123456");?? //123456\0放在常量區(qū),編譯器可能會(huì)將它與p3所向"123456"優(yōu)化成一個(gè)

    地方。
    }
    二、堆和棧的理論知識(shí)
    2.1申請(qǐng)方式
    stack:
    由系統(tǒng)自動(dòng)分配。例如,聲明在函數(shù)中一個(gè)局部變量int b;系統(tǒng)自動(dòng)在棧中為b開辟空間
    heap:
    需要程序員自己申請(qǐng),并指明大小,在c中malloc函數(shù)
    如p1=(char*)malloc(10);
    在C++中用new運(yùn)算符
    如p2=(char*)malloc(10);
    但是注意p1、p2本身是在棧中的。
    2.2
    申請(qǐng)后系統(tǒng)的響應(yīng)
    棧:只要棧的剩余空間大于所申請(qǐng)空間,系統(tǒng)將為程序提供內(nèi)存,否則將報(bào)異常提示棧溢出。
    堆:首先應(yīng)該知道操作系統(tǒng)有一個(gè)記錄空閑內(nèi)存地址的鏈表,當(dāng)系統(tǒng)收到程序的申請(qǐng)時(shí),
    會(huì)遍歷該鏈表,尋找第一個(gè)空間大于所申請(qǐng)空間的堆結(jié)點(diǎn),然后將該結(jié)點(diǎn)從空閑結(jié)點(diǎn)鏈表中刪除,并將

    該結(jié)點(diǎn)的空間分配給程序,另外,對(duì)于大多數(shù)系統(tǒng),會(huì)在這塊內(nèi)存空間中的首地址處記錄本次分配的大

    小,這樣,代碼中的delete語句才能正確的釋放本內(nèi)存空間。另外,由于找到的堆結(jié)點(diǎn)的大小不一定正

    好等于申請(qǐng)的大小,系統(tǒng)會(huì)自動(dòng)的將多余的那部分重新放入空閑鏈表中。
    2.3申請(qǐng)大小的限制
    棧:在Windows下,棧是向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存的區(qū)域。這句話的意思是棧頂?shù)牡?/p>

    址和棧的最大容量是系統(tǒng)預(yù)先規(guī)定好的,在WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個(gè)編譯

    時(shí)就確定的常數(shù)),如果申請(qǐng)的空間超過棧的剩余空間時(shí),將提示overflow。因此,能從棧獲得的空間

    較小。
    堆:堆是向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域。這是由于系統(tǒng)是用鏈表來存儲(chǔ)的空閑內(nèi)存地

    址的,自然是不連續(xù)的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計(jì)算機(jī)系統(tǒng)中有效的

    虛擬內(nèi)存。由此可見,堆獲得的空間比較靈活,也比較大。
    2.4申請(qǐng)效率的比較:
    棧:由系統(tǒng)自動(dòng)分配,速度較快。但程序員是無法控制的。
    堆:是由new分配的內(nèi)存,一般速度比較慢,而且容易產(chǎn)生內(nèi)存碎片,不過用起來最方便.
    另外,在WINDOWS下,最好的方式是用Virtual Alloc分配內(nèi)存,他不是在堆,也不是在棧,而是直接在進(jìn)

    程的地址空間中保留一塊內(nèi)存,雖然用起來最不方便。但是速度快,也最靈活。
    2.5堆和棧中的存儲(chǔ)內(nèi)容
    棧:在函數(shù)調(diào)用時(shí),第一個(gè)進(jìn)棧的是主函數(shù)中后的下一條指令(函數(shù)調(diào)用語句的下一條可執(zhí)行語句)的

    地址,然后是函數(shù)的各個(gè)參數(shù),在大多數(shù)的C編譯器中,參數(shù)是由右往左入棧的,然后是函數(shù)中的局部變

    量。注意靜態(tài)變量是不入棧的。
    當(dāng)本次函數(shù)調(diào)用結(jié)束后,局部變量先出棧,然后是參數(shù),最后棧頂指針指向最開始存的地址,也就是主

    函數(shù)中的下一條指令,程序由該點(diǎn)繼續(xù)運(yùn)行。
    堆:一般是在堆的頭部用一個(gè)字節(jié)存放堆的大小。堆中的具體內(nèi)容由程序員安排。
    2.6存取效率的比較
    char s1[]="aaaaaaaaaaaaaaa";
    char *s2="bbbbbbbbbbbbbbbbb";
    aaaaaaaaaaa是在運(yùn)行時(shí)刻賦值的;
    而bbbbbbbbbbb是在編譯時(shí)就確定的;
    但是,在以后的存取中,在棧上的數(shù)組比指針?biāo)赶虻淖址?例如堆)快。
    比如:
    #include
    voidmain()
    {
    char a=1;
    char c[]="1234567890";
    char *p="1234567890";
    a = c[1];
    a = p[1];
    return;
    }
    對(duì)應(yīng)的匯編代碼
    10:a=c[1];
    004010678A4DF1movcl,byteptr[ebp-0Fh]
    0040106A884DFCmovbyteptr[ebp-4],cl
    11:a=p[1];
    0040106D8B55ECmovedx,dwordptr[ebp-14h]
    004010708A4201moval,byteptr[edx+1]
    004010738845FCmovbyteptr[ebp-4],al
    第一種在讀取時(shí)直接就把字符串中的元素讀到寄存器cl中,而第二種則要先把指針值讀到edx中,在根據(jù)

    edx讀取字符,顯然慢了。
    2.7小結(jié):
    堆和棧的區(qū)別可以用如下的比喻來看出:
    使用棧就象我們?nèi)ワ堭^里吃飯,只管點(diǎn)菜(發(fā)出申請(qǐng))、付錢、和吃(使用),吃飽了就走,不必理會(huì)

    切菜、洗菜等準(zhǔn)備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自由度小。
    使用堆就象是自己動(dòng)手做喜歡吃的菜肴,比較麻煩,但是比較符合自己的口味,而且自由度大。

    自我總結(jié):
    char *c1 = "abc";實(shí)際上先是在文字常量區(qū)分配了一塊內(nèi)存放"abc",然后在棧上分配一地址給c1并指向

    這塊地址,然后改變常量"abc"自然會(huì)崩潰

    然而char c2[] = "abc",實(shí)際上abc分配內(nèi)存的地方和上者并不一樣,可以從
    4199056
    2293624 看出,完全是兩塊地方,推斷4199056處于常量區(qū),而2293624處于棧區(qū)

    2293628
    2293624
    2293620 這段輸出看出三個(gè)指針分配的區(qū)域?yàn)闂^(qū),而且是從高地址到低地址

    2293620 4199056 abc 看出編譯器將c3優(yōu)化指向常量區(qū)的"abc"


    繼續(xù)思考:
    代碼:
    #include <iostream>
    using namespace std;

    main()
    {
    ?? char *c1 = "abc";
    ?? char c2[] = "abc";
    ?? char *c3 = ( char* )malloc(3);
    ?? //? *c3 = "abc" //error
    ?? strcpy(c3,"abc");
    ?? c3[0] = 'g';
    ?? printf("%d %d %s\n",&c1,c1,c1);
    ?? printf("%d %d %s\n",&c2,c2,c2);
    ?? printf("%d %d %s\n",&c3,c3,c3);
    ?? getchar();
    }??
    輸出:
    2293628 4199056 abc
    2293624 2293624 abc
    2293620 4012976 gbc
    寫成注釋那樣,后面改動(dòng)就會(huì)崩潰
    可見strcpy(c3,"abc");abc是另一塊地方分配的,而且可以改變,和上面的參考文檔說法有些不一定,

    而且我不能斷定4012976是哪個(gè)區(qū)的,可能要通過算區(qū)的長(zhǎng)度,希望高人繼續(xù)深入解釋,謝謝
    ?

    posted @ 2006-10-16 19:06 Coolfiry 閱讀(1147) | 評(píng)論 (2)編輯 收藏

    ?和?'f'標(biāo)志指定的相同順序。

    示例1:將兩個(gè)class文件存檔到一個(gè)名為?'classes.jar'?的存檔文件中:
    ?& nbsp;?????jar?cvf& nbsp;classes.jar?Foo.class?Bar.class
    示例2:用一個(gè)存在的清單(manifest)文件?'mymanifest'?將?foo/& nbsp;目錄下的所有
    ????? ??????文件存檔到一個(gè)名為 ?'classes.jar'?的存檔文件中:
    ?? ?????jar?cvfm? classes.jar?mymanifest?-C?foo/?.

    來個(gè)小例子試試看:
    我們只有一個(gè)HelloWorld,如下:
    public& nbsp;?class??HelloWorld{
    ?public& nbsp;static?void?main(String[]?args){
    ?System.out.println(“Hi,?Hello?World!”);
    }
    }
    我將這個(gè)java文件存到C盤跟目錄下,ok,接下來,
    在先前打開的命令提示符下(跳轉(zhuǎn)到C盤提示符下),我們輸入javac?HelloWorld.java,然后繼續(xù)輸入:jar?& nbsp;cvf??hello.jar??HelloWorld.class,回車后去你的C盤看看,多了什么,沒錯(cuò)?hello.jar?。
    基本的步驟我們現(xiàn)在都知道了,你可以自己去嘗試一下隨著jar后面的參數(shù)的不同,結(jié)果有什么變化。
    緊接著我們看看如何運(yùn)行我們的jar包。
    在進(jìn)入正題之前,你要先打開我們剛剛做好的jar包看看,多了什么呢,META-INF目錄?再看看里面是什么,還有一個(gè)MANIFEST.MF文件是不是?用文本編輯器(我這里是UltraEdit)打開它看看:
    Manifest-Version:? 1.0
    Created-By:?1.4.2?(Sun?Microsystems& nbsp;Inc.)
    就是這樣。這里我們對(duì)它進(jìn)行修改,加一句:Main-Class:? HelloWorld?(在第三行)。這個(gè)就是我們之前寫的那個(gè)類,也就是我們的入口類。也即,
    Manifest -Version:?1.0
    Created-By:?1.4.2?(Sun& nbsp;Microsystems?Inc.)
    Main-Class:?HelloWorld< BR>接下來,我們?cè)诿钐崾痉飯?zhí)行:
    jar?umf? MANIFEST.MF?app.jar
    這樣我們使用了我們自己的MANIFEST.MF文件對(duì)原來默認(rèn)的進(jìn)行了更新。你不妨可以再進(jìn)去看看是不是添上了Main-Class:?HelloWorld這一句。
    Ok,這個(gè)最后的一步了,來驗(yàn)證我們做的一切,在命令提示符中輸入:
    java?-jar?hello.jar (執(zhí)行)
    出現(xiàn)了什么,――Hi,?Hello?World!
    我們?cè)賮砜纯?jar文件在tomcat中發(fā)布,注意:在tomcat中我們就不能再用jar這種格式,而改war格式,它是專門用于web應(yīng)用的,其實(shí)整個(gè)過程下來基本上和jar是類似的:
    先準(zhǔn)備我們要打包的資源。
    找到存放tomcat的webapps目錄,進(jìn)到其中,新建一個(gè)文件夾,這里命名為hello,再進(jìn)去新建WEB-INF文件夾,再進(jìn)去新建classes文件夾,此時(shí)我們也將我們唯一的servlet, HelloWorld.java放到這里,在與classes目錄同級(jí)下建立一文件web.xml。Ok,目前我們初步建立了一個(gè)簡(jiǎn)單的web應(yīng)用。
    這是HelloWorld.java:
    import?java.io.*;< BR>import?javax.servlet.*;
    import?javax.servlet.http.*;
    public?class?HelloWorld?extends& nbsp;HttpServlet?{
    ?public?void? doGet(HttpServletRequest?req,?HttpServletResponse? res)
    ?????? ???????& nbsp;??????? ???????& nbsp;?throws?ServletException,?IOException& nbsp;{
    ??res.setContentType("text/html");
    ??PrintWriter?out?=?res.getWriter ();
    ??out.println("<HTML>");< BR>??out.println("<HEAD><TITLE& gt;Hello,?World!</TITLE></HEAD>");< BR>??out.println("<BODY>");
    & nbsp;?out.println("Hello,?World!");
    ? ?out.println("</BODY></HTML>");
    ?}
    }//end?here!
    對(duì)它編譯。下面是web.xml:< BR><?xml?version="1.0"?encoding="ISO-8859-1"?>
    <!DOCTYPE?web-app?PUBLIC
    ??'-//Sun?Microsystems,?Inc.//DTD?Web?Application?2.3//EN'
    ??'http://java.sun.com/j2ee/dtds/web-app_2_3.dtd&< /FONT>#39;>
    <web-app>
    ??<servlet>
    ?? ??<servlet-name>hello</servlet-name& gt;
    ????<servlet-class& gt;HelloWorld</servlet-class>
    ?? </servlet>
    ??<servlet-mapping& gt;
    ?<servlet-name>hello</servlet- name>
    ?<url-pattern>/HelloWorld& lt;/url-pattern>
    ??</servlet-mapping& gt;
    </web-app>
    開始?jí)嚎s,形成war檔:
    在命令提示符下進(jìn)到先前創(chuàng)制的hello目錄下,執(zhí)行?jar??cvf? ?hello.war??*?,我們便得到hello.war。將它拷貝至 webapps目錄下,ok,來看最后一步,打開tomcat的目錄conf中的server.xml,加入:
    ? ?<Context?path="/hello"?docBase="hello.war"& nbsp;debug="0"
    ????reloadable ="true"/>
    大功告成!運(yùn)行它,啟動(dòng)tomcat,后在瀏覽器中輸入http://localhost:8080/hello/HelloWorld,有了嗎?
    最后,如果你想用ant來完成以上的打包活動(dòng),下面就告訴你:
    對(duì)于jar來說。在build.xml 中,
    ?<target?name="jar">< BR>??<jar?destfile="${app_home}/hello.jar"& gt;
    ???<fileset?dir=" ${dest}"?includes="**"/>
    ??& nbsp;???<!--fileset?dir="${dest} "?includes="**/action.properties"/-->
    ? ???</jar>
    ?& lt;/target>

    對(duì)于war,
    <war& nbsp;warfile="hello.war"?webxml="./WEB-INF/web.xml">
    ????<fileset?dir="html"/& gt;
    ????<lib? dir="lib/">
    ????& nbsp;???<exclude?name="oracle*.jar"/& gt;
    ????</lib>
    ????<classes? dir="build/servlets">
    ???& nbsp;?????<include& nbsp;name="**/*.class"/>
    ??</classes& gt;
    </war>?
    好了,就這么多,希望對(duì)你有點(diǎn)幫助。:)
    我上傳了上面打過的兩個(gè)包,hello.jar和hello.war。『 點(diǎn)擊下載』
    『 點(diǎn)擊下載』
    第一rar文件對(duì)應(yīng)的是hello.jar,下載后將其名改為 hello.jar
    第二rar文件對(duì)應(yīng)hello.war,下載后改為hello.war。
    這是由于上傳不了 jar格式和war格式的文件,你只好照我上面說的去做了?:)

    補(bǔ)充:
    ############
    jar基本操作:
    ############
    1.& nbsp;創(chuàng)建jar文件
    ??jar?cf?jar- file?input-file(s)
    c---want?to?Create& nbsp;a?JAR?file.
    f---want?the? output?to?go?to?a?file? rather?than?to?stdout.
    eg:?1) jar?cf?myjar.jar?query_maintain_insert.htm< BR>????2)jar?cvf? myjar.jar?query_maintain_insert.htm
    ?? ????v---Produces?verbose(詳細(xì)的)?output.
    ????3)jar& nbsp;cvf?myjar.jar?query_maintain_insert.htm?mydirectory< BR>????4)jar?cv0f? myjar.jar?query_maintain_insert.htm?mydirectory
    ??????0---don't& nbsp;want?the?JAR?file?to?be& nbsp;compressed.
    ????5)jar& nbsp;cmf?MANIFEST.MF?myjar.jar?yahh.txt
    ??????m---Used& nbsp;to?include?manifest?information? from?an?existing?manifest?file.
    ????6)jar?cMf?MANIFEST.MF& nbsp;myjar.jar?yahh.txt
    ???& nbsp;??M---the?default?manifest? file?should?not?be?produced.
    ????7)jar?cvf?myjar.jar& nbsp;*
    ?????? *---create?all?contents?in?current& nbsp;directory.
    2.?察看jar文件
    ?& nbsp;jar?tf?jar-file
    t---want?to& nbsp;view?the?Table?of?contents? of?the?JAR?file.
    eg:?1)jar& nbsp;vft?yahh.jar
    ???? ??v---Produces?verbose(詳細(xì)的)? output.
    3.?提取jar文件
    ?? jar?xf?jar-file?[archived-file(s)]
    x- --want?to?extract?files?from? the?JAR?archive.
    eg:?1)jar?xf& nbsp;yahh.jar?yahh.txt(僅提取文件yahh.txt)
    ?& nbsp;??2)jar?xf?yahh.jar?alex/yahhalex.txt (僅提取目錄alex下的文件yahhalex.txt)
    ???& nbsp;3)jar?xf?yahh.jar(提取該jar包中的所有文件或目錄)
    4.?修改Manifest文件
    ??jar? cmf?manifest-addition?jar-file?input-file(s)< BR>m---Used?to?include?manifest?information& nbsp;from?an?existing?manifest?file.< BR>5.?更新jar文件
    ??jar? uf?jar-file?input-file(s)
    u---want?to?update?a

    posted @ 2006-10-12 18:40 Coolfiry 閱讀(347) | 評(píng)論 (0)編輯 收藏

    發(fā)布Java應(yīng)用程序時(shí)你會(huì)感到困難?好在Java提供了一系列打包和發(fā)布工具,可以顯著的簡(jiǎn)化發(fā)布過程
      
      該文章提供了打包Java code的幾種方法,我們將會(huì)探討Java manifest 文件,給出用于管理JAR文件所依賴文件、估計(jì)跨平臺(tái)發(fā)布所需的CLasspath的合適方法.我也會(huì)解釋如何使用manifest包版本特性來確認(rèn)包的兼容性...
      
      什么是JAR文件?
      
      在開發(fā)過程中,我們可以直接使用Java class文件來運(yùn)行程序,但這并不是一個(gè)好方式,好在Java 提供了 JAR(Java Archive)文件來提供發(fā)布和運(yùn)行。
      
      jar 文件實(shí)際上是class 文件的ZIP壓縮存檔,這種格式被廣泛使用,因此易與使用,有很多中工具可以操作這種格式的文件。也正是因?yàn)檫@個(gè)原因,jar文件本身并不能表達(dá)所包含應(yīng)用程序的標(biāo)簽信息。
      
      Manifest 因此得以出現(xiàn)
      
       為了要提供存檔的標(biāo)簽信息,jar 文件指定了一個(gè)特定目錄來存放標(biāo)簽信息:META-INF 目錄,其中我們來關(guān)注該目錄中的MANIFEST.MF文件,他就是JAR的manifest文件,他包含了JAR文件的內(nèi)容描述,并在運(yùn)行時(shí)向JVM提 供應(yīng)用程序的信息,大多數(shù)JAR文件含有一個(gè)默認(rèn)生成的manifest 文件,執(zhí)行JAR命令或使用zip工具,都可以產(chǎn)生它
      
      如果是由jar命令產(chǎn)生的 manifest 文件,形如:
      Manifest-Version: 1.0
      Created-By:1.4.0-beta
      (Sun Microsystems Inc.)
      
       這些信息沒甚么用,僅僅告訴我們使用的是1.0的manifest文件,第一行定義manifest的格式,第二行說明使用 SUN 的JDK1.4的jar工具生成該文件,如果manifest文件是由其他 (如ant) 創(chuàng)建的,那將會(huì)出現(xiàn) “Created-By: Ant 1.2” 之類的內(nèi)容,如果你是自己創(chuàng)建manifest文件,你可以加入自己的一些相關(guān)信息.
      
      基礎(chǔ)格式
      
      manifest 文件的格式 是很簡(jiǎn)單的,每一行都是 名-值 對(duì)應(yīng)的:屬性名開頭,接著是 ":" ,然后是屬性值,每行最多72個(gè)字符,如果需要增加,你可以在下一行續(xù)行,續(xù)行以空格開頭,以空格開頭的行都會(huì)被視為前一行的續(xù)行。
      
      所有在開頭的屬性都是全局的,你也可以定義特定class 或package的屬性,稍后將介紹這種
      
      把manifest文件插入JAR文件
      
      使用 m 選項(xiàng),把指定文件名的manifest文件 傳入,例如
      jar cvfm myapplication.jar myapplication.mf -C classdir
      
      如果你使用ant來創(chuàng)建時(shí),在ant 的build.xml 加入如下條目
      <target name="jar">
      <jar jarfile ="myapplication.jar"
      manifest="myapplication.mf">
      <fileset dir="classdir"
      includes="**/*.class"/>
      </jar>
      </target>
      
      運(yùn)行Java程序
      
      現(xiàn)在我們來體驗(yàn)一下manifest文件的作用,如果現(xiàn)在我們有一個(gè)Java 應(yīng)用程序打包在myapplication.jar中, main class為 com.example.myapp.MyAppMain ,那么我們可以用以下的命令來運(yùn)行
      java -classpath myapplication.jar com.example.myapp.MyAppMain
      
      這顯然太麻煩了,現(xiàn)在我們來創(chuàng)建自己的manifest文件,如下:
      Manifest-Version: 1.0
      Created-By: JDJ example
      Main-Class: com.example.myapp.MyAppMain
      
      這樣我們就可以使用如下的命令來運(yùn)行程序了:(明顯簡(jiǎn)單多了,也不會(huì)造成無謂的拼寫錯(cuò)誤)
      java -jar myapplication.jar
      
      管理JAR的依賴資源
      
       很少Java應(yīng)用會(huì)僅僅只有一個(gè)jar文件,一般還需要 其他類庫。比如我的應(yīng)用程序用到了Sun 的 Javamail classes ,在classpath中我需要包含activation.jar 和 mail.jar,這樣在運(yùn)行程序時(shí),相比上面的例子,我們要增加一些:
      java -classpath mail.jar:activation.jar -jar myapplication.jar
      
      在不同的操作系統(tǒng)中,jar包間的分隔符也不一樣,在UNIX用“:”,在window中使用 “;”,這樣也不方便
      
      同樣,我們改寫我們的manifest文件,如下
      Manifest-Version: 1.0
      Created-By: JDJ example
      Main-Class: com.example.myapp.MyAppMain
      Class-Path: mail.jar activation.jar
      
      (加入了Class-Path: mail.jar activation.jar,用空格分隔兩個(gè)jar包)
      
      這樣我們?nèi)匀豢梢允褂煤蜕侠邢嗤拿顏韴?zhí)行該程序:
      java -jar myapplication.jar
      
       Class-Path屬性中包含了用空格分隔的jar文件,在這些jar文件名中要對(duì)特定的字符使用逃逸符,比如空格,要表示成"%20",在路徑的表 示中,都采用“/”來分隔目錄,無論是在什么操作系統(tǒng)中,(即使在window中),而且這里用的是相對(duì)路徑(相對(duì)于本身的JAR文件):
      Manifest-Version: 1.0
      Created-By: JDJ example
      Main-Class: com.example.myapp.MyAppMain
      Class-Path: ext/mail.jar ext/activation.jar
      Multiple Main Classes(多主類)
      
       還有一種Multiple Main Classes情況,如果你的應(yīng)用程序可能有命令行版本 和GUI版本,或者一些不同的應(yīng)用卻共享很多相同的代碼,這時(shí)你可能有多個(gè)Main Class,我們建議你采取這樣的策略:把共享的類打成lib包,然后把不同的應(yīng)用打成不同的包,分別標(biāo)志主類:如下
      Manifest for myapplicationlib.jar:
      Manifest-Version: 1.0
      Created-By: JDJ example
      Class-Path: mail.jar activation.jar
      Manifest for myappconsole.jar:
      Manifest-Version: 1.0
      Created-By: JDJ example
      Class-Path: myapplicationlib.jar
      Main-Class: com.example.myapp.MyAppMain
      Manifest for myappadmin.jar:
      Manifest-Version: 1.0
      Created-By: JDJ example
      Class-Path: myapplicationlib.jar
      Main-Class: com.example.myapp.MyAdminTool
      在myappconsole.jar 和 myappadmin.jar的manifest文件中分別注明各自的 Main Class
      Package Versioning
      
      完成發(fā)布后,如果使用者想了解 ,哪些代碼是誰的?目前是什么版本?使用什么版本的類庫?解決的方法很多 ,manifest提供了一個(gè)較好的方法,你可以在manifest文件中描述每一個(gè)包的信息。
      
       Java 秉承了實(shí)現(xiàn)說明與描述分離的原則,package 的描述 定義了package 是什么,實(shí)現(xiàn)說明 定義了誰提供了描述的實(shí)現(xiàn),描述和實(shí)現(xiàn)包含 名、版本號(hào)和提供者。要得到這些信息,可以查看JVM的系統(tǒng)屬性(使用 java.lang.System.getProperty() )
      
      在manifest文件中,我可以為每個(gè)package定義描述和實(shí)現(xiàn)版本,聲明名字,并加入描述屬性和實(shí)現(xiàn)屬性,這些屬性是
      
      Specification-Title
      Specification-Version
      Specification-Vendor
      Implementation-Title
      Implementation-Version
      Implementation-Vendor
      
      當(dāng)要提供一個(gè)類庫或編程接口時(shí),描述信息顯得是很重要,見以下范例:
      
      Manifest-Version: 1.0
      Created-By: JDJ example
      Class-Path: mail.jar activation.jar
      Name: com/example/myapp/
      Specification-Title: MyApp
      Specification-Version: 2.4
      Specification-Vendor: example.com
      Implementation-Title: com.example.myapp
      Implementation-Version: 2002-03-05-A
      Implementation-Vendor: example.com
      
      Package Version 查詢
      
      在manifest文件中加入package描述后,就可以使用Java提供的java.lang.Package class進(jìn)行Package 的信息查詢,這里列舉3個(gè)最基本的獲取package object的方法
      
      1.Package.getPackages():返回系統(tǒng)中所有定義的package列表
      
      2.Package.getPackage(String packagename):按名返回package
      
      3.Class.getPackage():返回給定class所在的package
      
      使用者這方法就可以動(dòng)態(tài)的獲取package信息.
      
      需要注意的是如果給定的package中沒有class被加載,則也無法獲得package 對(duì)象
      
      Manifest 技巧
      
      總是以Manifest-Version屬性開頭
      
      每行最長(zhǎng)72個(gè)字符,如果超過的化,采用續(xù)行
      
      確認(rèn)每行都以回車結(jié)束,否則改行將會(huì)被忽略
      
      如果Class-Path 中的存在路徑,使用"/"分隔目錄,與平臺(tái)無關(guān)
      
      使用空行分隔主屬性和package屬性
      
      使用"/"而不是"."來分隔package 和class ,比如 com/example/myapp/
      
      class 要以.class結(jié)尾,package 要以 / 結(jié)尾

    posted @ 2006-10-12 18:38 Coolfiry 閱讀(293) | 評(píng)論 (0)編輯 收藏

    下面就來看看什么是 JAR 文件包吧:

    1. JAR 文件包

    JAR 文件就是 Java Archive File,顧名思意,它的應(yīng)用是與 Java 息息相關(guān)的,是 Java 的一種文檔格式。JAR 文件非常類似 ZIP 文件——準(zhǔn)確的說,它就是 ZIP 文件,所以叫它文件包。JAR 文件與 ZIP 文件唯一的區(qū)別就是在 JAR 文件的內(nèi)容中,包含了一個(gè) META-INF/MANIFEST.MF 文件,這個(gè)文件是在生成 JAR 文件的時(shí)候自動(dòng)創(chuàng)建的。舉個(gè)例子,如果我們具有如下目錄結(jié)構(gòu)的一些文件:

      ==

      `-- test

        `-- Test.class

    把它壓縮成 ZIP 文件 test.zip,則這個(gè) ZIP 文件的內(nèi)部目錄結(jié)構(gòu)為:

      test.zip

      `-- test

        `-- Test.class

    如果我們使用 JDK 的 jar 命令把它打成 JAR 文件包 test.jar,則這個(gè) JAR 文件的內(nèi)部目錄結(jié)構(gòu)為:

      test.jar

      |-- META-INF

      |  `-- MANIFEST.MF

      `-- test

        `--Test.class

    2. 創(chuàng)建可執(zhí)行的 JAR 文件包

    制作一個(gè)可執(zhí)行的 JAR 文件包來發(fā)布你的程序是 JAR 文件包最典型的用法。

    Java 程序是由若干個(gè) .class 文件組成的。這些 .class 文件必須根據(jù)它們所屬的包不同而分級(jí)分目錄存放;運(yùn)行前需要把所有用到的包的根目錄指定給 CLASSPATH 環(huán)境變量或者 java 命令的 -cp 參數(shù);運(yùn)行時(shí)還要到控制臺(tái)下去使用 java 命令來運(yùn)行,如果需要直接雙擊運(yùn)行必須寫 Windows 的批處理文件 (.bat) 或者 Linux 的 Shell 程序。因此,許多人說,Java 是一種方便開發(fā)者苦了用戶的程序設(shè)計(jì)語言。

    其實(shí)不然,如果開發(fā)者能夠制作一個(gè)可執(zhí)行的 JAR 文件包交給用戶,那么用戶使用起來就方便了。在 Windows 下安裝 JRE (Java Runtime Environment) 的時(shí)候,安裝文件會(huì)將 .jar 文件映射給 javaw.exe 打開。那么,對(duì)于一個(gè)可執(zhí)行的 JAR 文件包,用戶只需要雙擊它就可以運(yùn)行程序了,和閱讀 .chm 文檔一樣方便 (.chm 文檔默認(rèn)是由 hh.exe 打開的)。那么,現(xiàn)在的關(guān)鍵,就是如何來創(chuàng)建這個(gè)可執(zhí)行的 JAR 文件包。

    創(chuàng)建可執(zhí)行的 JAR 文件包,需要使用帶 cvfm 參數(shù)的 jar 命令,同樣以上述 test 目錄為例,命令如下:

    jar cvfm test.jar manifest.mf test

    這里 test.jar 和 manifest.mf 兩個(gè)文件,分別是對(duì)應(yīng)的參數(shù) f 和 m,其重頭戲在 manifest.mf。因?yàn)橐獎(jiǎng)?chuàng)建可執(zhí)行的 JAR 文件包,光靠指定一個(gè) manifest.mf 文件是不夠的,因?yàn)?MANIFEST 是 JAR 文件包的特征,可執(zhí)行的 JAR 文件包和不可執(zhí)行的 JAR 文件包都包含 MANIFEST。關(guān)鍵在于可執(zhí)行 JAR 文件包的 MANIFEST,其內(nèi)容包含了 Main-Class 一項(xiàng)。這在 MANIFEST 中書寫格式如下:

    Main-Class: 可執(zhí)行主類全名(包含包名)

    例如,假設(shè)上例中的 Test.class 是屬于 test 包的,而且是可執(zhí)行的類 (定義了 public static void main(String[]) 方法),那么這個(gè) manifest.mf 可以編輯如下:

    Main-Class: test.Test <回車>

    這個(gè) manifest.mf 可以放在任何位置,也可以是其它的文件名,只需要有 Main-Class: test.Test 一行,且該行以一個(gè)回車符結(jié)束即可。創(chuàng)建了 manifest.mf 文件之后,我們的目錄結(jié)構(gòu)變?yōu)椋?

      ==

      |-- test

      |  `-- Test.class

      `-- manifest.mf

    這時(shí)候,需要到 test 目錄的上級(jí)目錄中去使用 jar 命令來創(chuàng)建 JAR 文件包。也就是在目錄樹中使用“==”表示的那個(gè)目錄中,使用如下命令:

    jar cvfm test.jar manifest.mf test

    之后在“==”目錄中創(chuàng)建了 test.jar,這個(gè) test.jar 就是執(zhí)行的 JAR 文件包。運(yùn)行時(shí)只需要使用 java -jar test.jar 命令即可。

    需要注意的是,創(chuàng)建的 JAR 文件包中需要包含完整的、與 Java 程序的包結(jié)構(gòu)對(duì)應(yīng)的目錄結(jié)構(gòu),就像上例一樣。而 Main-Class 指定的類,也必須是完整的、包含包路徑的類名,如上例的 test.Test;而且在沒有打成 JAR 文件包之前可以使用 java <類名> 來運(yùn)行這個(gè)類,即在上例中 java test.Test 是可以正確運(yùn)行的 (當(dāng)然要在 CLASSPATH 正確的情況下)。

    3. jar 命令詳解

    jar 是隨 JDK 安裝的,在 JDK 安裝目錄下的 bin 目錄中,Windows 下文件名為 jar.exe,Linux 下文件名為 jar。它的運(yùn)行需要用到 JDK 安裝目錄下 lib 目錄中的 tools.jar 文件。不過我們除了安裝 JDK 什么也不需要做,因?yàn)?SUN 已經(jīng)幫我們做好了。我們甚至不需要將 tools.jar 放到 CLASSPATH 中。

    使用不帶任何的 jar 命令我們可以看到 jar 命令的用法如下:

    jar {ctxu}[vfm0M] [jar-文件] [manifest-文件] [-C 目錄] 文件名 ...

    其中 {ctxu} 是 jar 命令的子命令,每次 jar 命令只能包含 ctxu 中的一個(gè),它們分別表示:

    -c 創(chuàng)建新的 JAR 文件包

    -t 列出 JAR 文件包的內(nèi)容列表

    -x 展開 JAR 文件包的指定文件或者所有文件

    -u 更新已存在的 JAR 文件包 (添加文件到 JAR 文件包中)

    [vfm0M] 中的選項(xiàng)可以任選,也可以不選,它們是 jar 命令的選項(xiàng)參數(shù)

    -v 生成詳細(xì)報(bào)告并打印到標(biāo)準(zhǔn)輸出

    -f 指定 JAR 文件名,通常這個(gè)參數(shù)是必須的

    -m 指定需要包含的 MANIFEST 清單文件

    -0 只存儲(chǔ),不壓縮,這樣產(chǎn)生的 JAR 文件包會(huì)比不用該參數(shù)產(chǎn)生的體積大,但速度更快

    -M 不產(chǎn)生所有項(xiàng)的清單(MANIFEST〕文件,此參數(shù)會(huì)忽略 -m 參數(shù)

    [jar-文件] 即需要生成、查看、更新或者解開的 JAR 文件包,它是 -f 參數(shù)的附屬參數(shù)

    [manifest-文件] 即 MANIFEST 清單文件,它是 -m 參數(shù)的附屬參數(shù)

    [-C 目錄] 表示轉(zhuǎn)到指定目錄下去執(zhí)行這個(gè) jar 命令的操作。它相當(dāng)于先使用 cd 命令轉(zhuǎn)該目錄下再執(zhí)行不帶 -C 參數(shù)的 jar 命令,它只能在創(chuàng)建和更新 JAR 文件包的時(shí)候可用。  

    文件名 ... 指定一個(gè)文件/目錄列表,這些文件/目錄就是要添加到 JAR 文件包中的文件/目錄。如果指定了目錄,那么 jar 命令打包的時(shí)候會(huì)自動(dòng)把該目錄中的所有文件和子目錄打入包中。

    下面舉一些例子來說明 jar 命令的用法:

    1) jar cf test.jar test

    該命令沒有執(zhí)行過程的顯示,執(zhí)行結(jié)果是在當(dāng)前目錄生成了 test.jar 文件。如果當(dāng)前目錄已經(jīng)存在 test.jar,那么該文件將被覆蓋。

    2) jar cvf test.jar test

    該命令與上例中的結(jié)果相同,但是由于 v 參數(shù)的作用,顯示出了打包過程,如下:

    標(biāo)明清單(manifest)

    增加:test/(讀入= 0) (寫出= 0)(存儲(chǔ)了 0%)

    增加:test/Test.class(讀入= 7) (寫出= 6)(壓縮了 14%)

    3) jar cvfM test.jar test

    該命令與 2) 結(jié)果類似,但在生成的 test.jar 中沒有包含 META-INF/MANIFEST 文件,打包過程的信息也略有差別:

    增加:test/(讀入= 0) (寫出= 0)(存儲(chǔ)了 0%)

    增加:test/Test.class(讀入= 7) (寫出= 6)(壓縮了 14%)

    4) jar cvfm test.jar manifest.mf test

    運(yùn)行結(jié)果與 2) 相似,顯示信息也相同,只是生成 JAR 包中的 META-INF/MANIFEST 內(nèi)容不同,是包含了 manifest.mf 的內(nèi)容

    5) jar tf test.jar

    在 test.jar 已經(jīng)存在的情況下,可以查看 test.jar 中的內(nèi)容,如對(duì)于 2) 和 3) 生成的 test.jar 分別應(yīng)該此命令,結(jié)果如下;

    對(duì)于 2)

    META-INF/

    META-INF/MANIFEST.MF

    test/

    test/Test.class

    對(duì)于 3)

    test/

    test/Test.class

    6) jar tvf test.jar

    除顯示 5) 中顯示的內(nèi)容外,還包括包內(nèi)文件的詳細(xì)信息,如:

    0 Wed Jun 19 15:39:06 GMT 2002 META-INF/

    86 Wed Jun 19 15:39:06 GMT 2002 META-INF/MANIFEST.MF

    0 Wed Jun 19 15:33:04 GMT 2002 test/

    7 Wed Jun 19 15:33:04 GMT 2002 test/Test.class

    7) jar xf test.jar

    解開 test.jar 到當(dāng)前目錄,不顯示任何信息,對(duì)于 2) 生成的 test.jar,解開后的目錄結(jié)構(gòu)如下:

      ==

      |-- META-INF

      |  `-- MANIFEST

      `-- test

        `--Test.class

    .net/forum/images/smiles/icon_cool.gif border=0> jar xvf test.jar

    運(yùn)行結(jié)果與 7) 相同,對(duì)于解壓過程有詳細(xì)信息顯示,如:

    創(chuàng)建:META-INF/

    展開:META-INF/MANIFEST.MF

    創(chuàng)建:test/

    展開:test/Test.class

    9) jar uf test.jar manifest.mf

    在 test.jar 中添加了文件 manifest.mf,此使用 jar tf 來查看 test.jar 可以發(fā)現(xiàn) test.jar 中比原來多了一個(gè) manifest。這里順便提一下,如果使用 -m 參數(shù)并指定 manifest.mf 文件,那么 manifest.mf 是作為清單文件 MANIFEST 來使用的,它的內(nèi)容會(huì)被添加到 MANIFEST 中;但是,如果作為一般文件添加到 JAR 文件包中,它跟一般文件無異。

    10) jar uvf test.jar manifest.mf

    與 9) 結(jié)果相同,同時(shí)有詳細(xì)信息顯示,如:

    增加:manifest.mf(讀入= 17) (寫出= 19)(壓縮了 -11%)

    4. 關(guān)于 JAR 文件包的一些技巧

    1) 使用 unzip 來解壓 JAR 文件

    在介紹 JAR 文件的時(shí)候就已經(jīng)說過了,JAR 文件實(shí)際上就是 ZIP 文件,所以可以使用常見的一些解壓 ZIP 文件的工具來解壓 JAR 文件,如 Windows 下的 WinZip、WinRAR 等和 Linux 下的 unzip 等。使用 WinZip 和 WinRAR 等來解壓是因?yàn)樗鼈兘鈮罕容^直觀,方便。而使用 unzip,則是因?yàn)樗鈮簳r(shí)可以使用 -d 參數(shù)指定目標(biāo)目錄。

    在解壓一個(gè) JAR 文件的時(shí)候是不能使用 jar 的 -C 參數(shù)來指定解壓的目標(biāo)的,因?yàn)?-C 參數(shù)只在創(chuàng)建或者更新包的時(shí)候可用。那么需要將文件解壓到某個(gè)指定目錄下的時(shí)候就需要先將這具 JAR 文件拷貝到目標(biāo)目錄下,再進(jìn)行解壓,比較麻煩。如果使用 unzip,就不需要這么麻煩了,只需要指定一個(gè) -d 參數(shù)即可。如:

    unzip test.jar -d dest/

    2) 使用 WinZip 或者 WinRAR 等工具創(chuàng)建 JAR 文件

    上面提到 JAR 文件就是包含了 META-INF/MANIFEST 的 ZIP 文件,所以,只需要使用 WinZip、WinRAR 等工具創(chuàng)建所需要 ZIP 壓縮包,再往這個(gè) ZIP 壓縮包中添加一個(gè)包含 MANIFEST 文件的 META-INF 目錄即可。對(duì)于使用 jar 命令的 -m 參數(shù)指定清單文件的情況,只需要將這個(gè) MANIFEST 按需要修改即可。

    3) 使用 jar 命令創(chuàng)建 ZIP 文件

    有些 Linux 下提供了 unzip 命令,但沒有 zip 命令,所以需要可以對(duì) ZIP 文件進(jìn)行解壓,即不能創(chuàng)建 ZIP 文件。如要?jiǎng)?chuàng)建一個(gè) ZIP 文件,使用帶 -M 參數(shù)的 jar 命令即可,因?yàn)? -M 參數(shù)表示制作 JAR 包的時(shí)候不添加 MANIFEST 清單,那么只需要在指定目標(biāo) JAR 文件的地方將 .jar 擴(kuò)展名改為 .zip 擴(kuò)展名,創(chuàng)建的就是一個(gè)不折不扣的 ZIP 文件了,如將上一節(jié)的第 3) 個(gè)例子略作改動(dòng):

    jar cvfM test.zip test

    posted @ 2006-10-12 15:54 Coolfiry 閱讀(355) | 評(píng)論 (0)編輯 收藏

         摘要: 周 登朋 (zhoudengpeng@yahoo.com.cn), 軟件工程師, 上海交通大學(xué) 2006 年 9 月 06 日? 在本篇文章中,你會(huì)學(xué)習(xí)到如何利用 Lucene 實(shí)現(xiàn)高級(jí)搜索功能以及如何利用 Lucene 來創(chuàng)建 Web 搜索應(yīng)用程序。通過這些學(xué)習(xí),你就可以利用 Lucene 來創(chuàng)建自己的搜索應(yīng)用程序。 ...  閱讀全文

    posted @ 2006-10-03 20:11 Coolfiry 閱讀(365) | 評(píng)論 (1)編輯 收藏

    一、閑聊

      今天要談的話題是COM,稍微深入一點(diǎn),不知道大家用過C++Test或者Visual Assistant之類的軟件沒有,它們都有個(gè)非常引人注目的功能,那就是把它們自身嵌入到VC開發(fā)環(huán)境中去。這個(gè)功能讓我癡迷不已,原因只有一個(gè):我想做一個(gè)可以嵌入VC開發(fā)環(huán)境的VC工程解析器,這樣用戶在VC開發(fā)環(huán)境中就可以直接對(duì)當(dāng)前或所有工程進(jìn)行各種分析,統(tǒng)計(jì)。那么實(shí)現(xiàn)它簡(jiǎn)單嗎?簡(jiǎn)單,Next和Copy即可輕松完成;僅僅這些嗎?不是,它的背后還有博大精深的COM做支撐。不管困難與否,還是讓我們先試為快。

      二、效果圖

    ?

      三、實(shí)現(xiàn)步驟:

      <3.1>新建一個(gè)<DevStudio Add-in Wizard>類型工程,輸入工程名稱"CodeAnalyser".

      <3.2>進(jìn)入第二個(gè)畫面,系統(tǒng)要求用戶輸入插件的名稱和描述信息。并且要求用戶選擇是否需要生成工具欄以及是否自動(dòng)添加VC事件響應(yīng)代碼。


      <3.3>點(diǎn)擊"Finish"結(jié)束向?qū)ВM(jìn)入代碼編輯窗口。

      在這里我們要說的一點(diǎn)是:該工程引用了ICommands接口,并從該接口上派生出 CCommands類。該類完成了所有用戶自定義函數(shù)接口,VC應(yīng)用程序消息響應(yīng)和VC調(diào)試動(dòng)作的消息響應(yīng)工作。當(dāng)我們真正為CCommands類添加成員函數(shù)之前我們必須先為ICommands接口添加相應(yīng)的函數(shù)接口聲明。在本工程中我總共為ICommands接口添加了兩個(gè)函數(shù)接口,它們名字分別為:GetCurDirCommandMethod和QuitCommandMethod聲明如下:(在CodeAnalyer.odl文件中)

    interface ICommands : IDispatch
    {
     // methods
     [id(1)] //在Vtable中的函數(shù)索引號(hào)
     HRESULT GetCurDirCommandMethod(); //得到VC當(dāng)前工作目錄

     [id(2)] //在Vtable中的函數(shù)索引號(hào)
     HRESULT QuitCommandMethod (); //退出VC編輯器
    };

      在接口ICommands添加接口函數(shù),那么相應(yīng)的我們也要在類CCommands中聲明和實(shí)現(xiàn)ICommands接口函數(shù),函數(shù)的內(nèi)部代碼和普通工程代碼沒什么區(qū)別。

    //Implement(CCommands類內(nèi)部接口函數(shù)的聲明)
    public:
    STDMETHOD(GetCurDirCommandMethod)(THIS);
    STDMETHOD(QuitCommandMethod)(THIS);

    //Function Code(Ccommands類內(nèi)部接口函數(shù)的實(shí)現(xiàn))
    //得到當(dāng)前VC開發(fā)環(huán)境的工作目錄[您也可以讓它成為你想要實(shí)現(xiàn)的功能代碼]
    STDMETHODIMP CCommands::GetCurDirCommandMethod()
    {
     AFX_MANAGE_STATE(AfxGetStaticModuleState());
     VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));
     BSTR bstrCurDir;
     m_pApplication->get_CurrentDirectory(&bstrCurDir);
     CString str(bstrCurDir);
     ::MessageBox(NULL, str, "VC工作目錄", MB_OK | MB_ICONINFORMATION);
     VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
     return S_OK;
    }

    //退出VC開發(fā)環(huán)境

    STDMETHODIMP CCommands::QuitCommandMethod()
    {
     AFX_MANAGE_STATE(AfxGetStaticModuleState());
     VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));
     if(::MessageBox(NULL,"您想退出VC++編輯器嗎(Y/N)?","詢問信息...", MB_YESNO | MB_ICONQUESTION) == IDYES)
      m_pApplication->Quit();
      VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
     return S_OK;
    }

      <3.4> 創(chuàng)建工具欄,連接工具欄按鈕事件

      所有的幕后工作已經(jīng)準(zhǔn)備就緒,只差個(gè)工具欄界面就一切OK了。打開類CDSAddIn,它里面有三個(gè)成員函數(shù),其中OnConnection和OnDisconnection成員函數(shù)的意義非常重要。它們的意義如下:

      <1>OnConnection:插件的初始化任務(wù)都在這里完成。如COM服務(wù)的啟動(dòng),工具欄/菜單欄的創(chuàng)建,工具欄按鈕/菜單項(xiàng)的添加與修改等等。

      <2>OnDisconnection:插件的卸載工作都在這里完成。如COM服務(wù)的卸載,工具欄/菜單欄的銷毀,釋放等等。

      了解了它們各自的用途之后我們就可以在相應(yīng)的消息事件中添加代碼了。很顯然工具欄的初始化應(yīng)該在OnConnection事件中完成。

      在OnConnection事件中系統(tǒng)首先獲得了VC應(yīng)用程序接口,然后調(diào)用一個(gè)接口函數(shù):AddCommand來為插件添加命令和命令影射函數(shù)。然后再使用另外一個(gè)接口函數(shù)AddCommandBarButton向工具欄中添加工具欄按鈕,其中每個(gè)工具欄按鈕會(huì)和一個(gè)命令標(biāo)志符號(hào)相連接,這樣就能實(shí)現(xiàn)按鈕和命令(消息)之間的一一對(duì)應(yīng)。下面是添加一個(gè)命令和一個(gè)工具欄按鈕的代碼(如果你要添加多個(gè)工具欄按鈕只要重復(fù)此步驟即可):

    LPCTSTR szCommand = _T("GetCurDirCommand");
    VARIANT_BOOL bRet;
    CString strCmdString;
    strCmdString.LoadString(IDS_CMD_STRING);
    strCmdString = szCommand + strCmdString;
    CComBSTR bszCmdString(strCmdString);
    CComBSTR bszMethod(_T("GetCurDirCommandMethod"));

    CComBSTR bszCmdName(szCommand); //和下面添加工具欄按鈕對(duì)應(yīng)

    VERIFY_OK(pApplication->AddCommand(bszCmdString,bszMethod,0,dwCookie,&bRet));
    //AddCommand 參數(shù)含義:
    //bszCmdString:命令字符串。
    //bszMethod:Icommands接口函數(shù)名。
    //第三個(gè)參數(shù)代表位圖偏移量。
    //第四和第五個(gè)參數(shù)分貝為系統(tǒng)參數(shù)和返回值(參照MSDN的IApplication介紹)

    if (bRet == VARIANT_FALSE)
    {
     *OnConnection = VARIANT_FALSE;
     return S_OK;
    }

    //添加工具欄按鈕
    if (bFirstTime == VARIANT_TRUE)
    {
     VERIFY_OK(pApplication->AddCommandBarButton(dsGlyph, bszCmdName, m_dwCookie));
    }

      <3.5> 編譯,連接及在VC中引入插件

      以上就是我們所有的代碼工作,接下來趕快Build以下吧。編譯通過的話,在你的工程Debug目錄下會(huì)有個(gè)dll文件。然后打開VC編輯器,在VC任何一個(gè)工具欄上點(diǎn)擊鼠標(biāo)右鍵,彈出如下圖所示菜單。然后選擇”Customize”子菜單,打開如下圖所示的工具欄定制窗口:


      接著選擇該窗口的最后一頁"Add-Ins and Macro Files"出現(xiàn)下圖所示窗口。


      然后點(diǎn)擊”Browse...”按鈕,這時(shí)打開你工程下的Debug目錄中的DLL文件,這樣你就可以看到你制作的工具欄了。同樣你再次打開上面的菜單,這次可以看到多了一個(gè)工具欄,并且名字亂七八糟的,怎么改變工具欄的名字呢?方法很簡(jiǎn)單:打開上面窗口中的”Toolbars”選項(xiàng)頁,在工具欄列表框中找到你的工具欄,然后在”Toolbar name”編輯框中輸入你想要的名字即可。再打開上面的菜單看看名字是不是變了,哈哈!


      OK,今天的話題就聊到這里。

    posted @ 2006-09-30 22:58 Coolfiry 閱讀(278) | 評(píng)論 (0)編輯 收藏

      插件式設(shè)計(jì)近年來非常流行,其中eclipse起了推波助瀾的作用,提到插件式就會(huì)不由自主的想到eclipse。其實(shí)插件式設(shè)計(jì)并不是什么新事物,早在幾十年前就有了。像X Server就是基于插件式設(shè)計(jì)的,除了核心功能外,它所有的擴(kuò)展功能和設(shè)備驅(qū)動(dòng)都是以插件方式加入進(jìn)來的。

      基于插件的設(shè)計(jì)好處很多:把擴(kuò)展功能從框架中剝離出來,降低了框架的復(fù)雜度,讓框架更容易實(shí)現(xiàn)。擴(kuò)展功能與框架以一種很松的方式耦合,兩者在保持接口不變的情況下,可以獨(dú)立變化和發(fā)布。公開插件接口,讓第三方有機(jī)會(huì)擴(kuò)展應(yīng)用程序的功能,有財(cái)大家一起發(fā)。另外,還可以讓開源與閉源共存于一套軟件,你的插件是開源還是閉源,完全由你自己決定。

      基于插件設(shè)計(jì)并不神秘,相反它比起一團(tuán)泥的設(shè)計(jì)更簡(jiǎn)單,更容易理解。各種基于插件設(shè)計(jì)的架構(gòu)都有自己的特色,但從總體架構(gòu)上看,其模型都大同小異。這里我們介紹一個(gè)簡(jiǎn)單的模型,并給出幾個(gè)實(shí)例,希望對(duì)新手有所啟發(fā)。

      1. 基本架構(gòu)

    plugin.jpg

      插件式設(shè)計(jì)的應(yīng)用程序,基本上可以用上圖來表示。當(dāng)然,此圖是一種較高層次的表示,實(shí)際的設(shè)計(jì)會(huì)更復(fù)雜一些。我們?cè)谶@里為了闡述方便,不用故意搞得那么復(fù)雜。

      應(yīng)用程序由應(yīng)用程序框架、插件接口、插件和公共函數(shù)庫四部分組成。

      應(yīng)用程序框架負(fù)責(zé)應(yīng)用程序的整體運(yùn)作,它清楚程序整個(gè)流程,但并不知道每個(gè)過程具體要做什么。它在適當(dāng)?shù)臅r(shí)候調(diào)用一些插件,來完成真正的功能。

      插件接口是一個(gè)協(xié)議,可能用IDL描述,可能是頭文件,也可能一段文字說明。插件按照這個(gè)協(xié)議實(shí)現(xiàn)出來,就可以加入到應(yīng)用程序中來。當(dāng)然,對(duì)于復(fù)雜的系統(tǒng),插件接口可能有多個(gè),各自具有獨(dú)立的功能。

      插件是完成實(shí)際功能的實(shí)體,實(shí)現(xiàn)了要求的插件接口。盡管實(shí)現(xiàn)什么以及怎么實(shí)現(xiàn),完全是插件自己的自由。在實(shí)際情況來,一般還是有些限制,因?yàn)椴寮涌诒旧砜赡芫褪且粋€(gè)限制。如,實(shí)現(xiàn)編譯功能的插件,自然不能實(shí)現(xiàn)成一個(gè)聊天功能的插件。

      公共函數(shù)庫是一組函數(shù)或者類,應(yīng)用程序框架和插件都可以調(diào)用。它通常是一個(gè)獨(dú)立的動(dòng)態(tài)庫(DLL)。應(yīng)用程序框架本身是公用的,是代碼復(fù)用的一種方式。但并不是所有可復(fù)用代碼都可以放在框架中,特別是插件會(huì)用到的公共代碼,那會(huì)造成插件對(duì)框架的依賴。把這些公共代碼提取到一個(gè)獨(dú)立的庫中,是一種好的方法。

      另外,值得補(bǔ)充說明一下的是插件接口。插件接口通常有兩種:

      通用插件接口:這一類插件接口是通用的,你無法從接口函數(shù)看出這個(gè)插件的功能。它的接口函數(shù)通常有這些函數(shù):

      init : 用于初始化插件,通常在插件被加載時(shí)調(diào)用。

      deinit:用于反初始化插件,通常在插件被卸載時(shí)調(diào)用。

      run:讓插件起動(dòng)。

      stop:讓插件停止。

      至于插件要完成什么功能,要插到哪里,在init函數(shù)里決定,它調(diào)用公共函數(shù)庫里的函數(shù)把自己注冊(cè)到框架中某個(gè)位置。

      專用插件接口:這一類插件接口是專用的,看到它的接口函數(shù)說明,你就可以大致了解它的功能了。

      加入插件的方式通常采用配置信息來實(shí)現(xiàn),配置信息可以是注冊(cè)表,也可以配置文件。也可以動(dòng)態(tài)注冊(cè)進(jìn)來,或者把插件放到指定的位置。

      下面我們來看幾個(gè)實(shí)例:

      2. 桌面設(shè)計(jì)

      最近一段時(shí)間完成了桌面模塊的設(shè)計(jì)和實(shí)現(xiàn)。按照以往的經(jīng)驗(yàn),桌面模塊通常是變化最多的一個(gè)模塊,SPEC總是在不斷的調(diào)整的效果,不同客戶要求實(shí)現(xiàn)具有個(gè)性化的桌面,直到產(chǎn)品快發(fā)布了,桌面的SPEC還在不停的修改。另外,在智能手機(jī)中,桌面占有特殊的地位,很多東西都可能往桌面里塞,桌面不但是各種功能的大雜燴,還是一些系統(tǒng)消息的中轉(zhuǎn)站。

      這個(gè)任務(wù)比較棘手,所以在設(shè)計(jì)時(shí)就分外小心。首先想到的就是采用插件式設(shè)計(jì),把外圍功能獨(dú)立出來,盡量簡(jiǎn)化框架的實(shí)現(xiàn)。

      插件:每一個(gè)最小功能單元都是一個(gè)插件,它可以是可見的,也可以是不可的,也可以是動(dòng)態(tài)變化的。比如時(shí)間、電池電量、網(wǎng)絡(luò)連接、信號(hào)強(qiáng)弱、新事件(如SMS、MMS、EMAL、ALARM和未接電話等)、應(yīng)用程序快捷方式、左右操作按鈕和其它處理系統(tǒng)事件的功能單元。每個(gè)插件都用一個(gè).desktop來描述,這是遵循freedesktop.org的標(biāo)準(zhǔn)的。

      桌面框架包括:狀態(tài)欄、開始菜單、操作欄、桌面區(qū)、事件管理器和主題管理器。而狀態(tài)欄、開始菜單、操作欄、桌面區(qū)和事件管理器都是容器,容納各種插件。對(duì)于可見的插件,可以有自己的表現(xiàn)方式,也可以采用通用的表現(xiàn)方式。

      公共函數(shù)庫:一些抽象的類、實(shí)現(xiàn)插件的輔助類以及其它一些可能被公用的類。

      插件接口:對(duì)于不可見的插件要求實(shí)現(xiàn)事件處理功能,可見的插件還要求實(shí)現(xiàn)繪制功能。

      3. 模擬器設(shè)計(jì)

      一個(gè)同事負(fù)責(zé)設(shè)計(jì)另外一個(gè)平臺(tái)的PC模擬環(huán)境設(shè)計(jì)。在我的建議下,他對(duì)架構(gòu)作了調(diào)整。調(diào)整后的架構(gòu)非常簡(jiǎn)單,也可以認(rèn)為是插件式的設(shè)計(jì),它由下面幾部分組成:

      應(yīng)用程序框架:負(fù)責(zé)模擬器基本功能,如模擬鍵盤和顯示設(shè)備、換膚功能等。

      插件:就是被模擬的平臺(tái),如microwindow及相應(yīng)的手機(jī)應(yīng)用程序。盡管運(yùn)行時(shí)通常只有一個(gè)插件運(yùn)行,這樣做仍然有意義,如果要換成minigui或者其它平臺(tái)時(shí),模擬器不需要作任何修改。

      公共函數(shù)庫:它由應(yīng)用程序框架初始化一些信息和回調(diào)函數(shù),然后供插件(即microwindow)調(diào)用,插件利用它來實(shí)現(xiàn)顯示和輸入等驅(qū)動(dòng)程序。

      插件接口:如起動(dòng)和停止模擬平臺(tái)等。

      4. GIMP

      GIMP是一個(gè)功能強(qiáng)大的圖形圖像編輯器,典型的基于插件式的設(shè)計(jì),在《unix編程藝術(shù)》中,作為插件式設(shè)計(jì)示例介紹過。

      應(yīng)用程序框架:GUI

      插件:完成圖像的各種轉(zhuǎn)換和處理功能,如模糊、去斑和色彩調(diào)整等。

      公共函數(shù)庫:放在libgimp.so里。

      插件接口:對(duì)GIMP感興趣的朋友,可以到官方網(wǎng)站上去閱讀更多的文檔。

    posted @ 2006-09-30 22:57 Coolfiry 閱讀(705) | 評(píng)論 (0)編輯 收藏

      Google推薦的開發(fā)環(huán)境是VS 2003,GoogleDesktop的插件是基于COM的,而COM是語言無關(guān)的,所以你可以用任何能開發(fā)COM的工具(語言)開發(fā)。

      如果你使用的VS 2003或者VS 2005,建立開發(fā)環(huán)境非常容易。不過,如果你像我一樣戀舊,還是喜愛VC6的簡(jiǎn)潔快速,排斥龐大緩慢的VS 2003或者VS 2005,可能就要費(fèi)一點(diǎn)周折了。

      這里只討論VC6的環(huán)境設(shè)置。

      Google沒有為VC6 提供開發(fā)向?qū)В簿褪钦f,所有代碼你都得手工就編寫。如果是出于學(xué)習(xí)的目的,手工去寫這些代碼,付出的勞動(dòng)會(huì)有所回報(bào)的。另外,VC6所帶的ATL版本也有點(diǎn)老,一些類只有在新版本中才有,在VC6中無法使用,所以有時(shí)你不得不面對(duì)一些COM的細(xì)節(jié)問題。同樣,同樣如果出于學(xué)習(xí)的目的,所花費(fèi)的時(shí)間也是值得的。

      建立開發(fā)環(huán)境的第一步就是下載GoogleDesktop的SDK,下載地址為http://desktop.google.com/。

      解開之后,GD_SDK\api目錄下有下面幾個(gè)目錄:

    documentation
    samples
    tools
    wizards

      建議先大概看一下documentation中的文檔,然后閱讀samples中的部分代碼,找一下感覺。

      GoogleDesktop提供全部接口都在三個(gè)IDL文件中聲明:

    GoogleDesktopActionAPI.idl
    GoogleDesktopAPI.idl
    GoogleDesktopDisplayAPI.idl

      開發(fā)GoogleDesktop的插件,有以上文件已經(jīng)足夠(當(dāng)然你要安裝GoogleDesktop本身)了。但是C++中不能直接使用idl文件,要通過midl.exe編譯成頭文件,才能使用。其實(shí)不用這么麻煩,GD_SDK\api\samples\common目錄中已經(jīng)有相關(guān)頭文件了:

    GoogleDesktopDisplayAPI.h

    GoogleDesktopComponentRegistration.h

    GoogleDesktopAPI.h

    GoogleDesktopActionAPI.h

      直接使用這幾個(gè)頭文件,可以省去用midl編譯步驟。只要修改VC6的設(shè)置,讓它可以找到上述頭文件就行了。有兩種方式可以做到這一點(diǎn)。一種方式是針對(duì)當(dāng)前項(xiàng)目的:

      1. 打開菜單Project->Settings

      2. 打開屬性頁的C/C++標(biāo)簽

      3. 選擇Categary的Preprocessor項(xiàng)

      4. 在Additional Include directories一欄加入上述文件所在的目錄

      另一種方式是針對(duì)VC6所有的項(xiàng)目的:

      1. 打開菜單Tool->Options…

      2. 打開屬性頁的Directories標(biāo)簽

      3. 選擇Show directories for中的include files項(xiàng)

      4. 在Directories中加上述文件所在的目錄

      至于選擇哪一種方式,完全看你個(gè)人愛好,后者會(huì)方便一點(diǎn),對(duì)懶人比較適用,但它會(huì)影響所有的VC6項(xiàng)目,或許會(huì)有某些副作用。

    posted @ 2006-09-30 22:55 Coolfiry 閱讀(251) | 評(píng)論 (0)編輯 收藏

    ?

    原文地址:http://www.tkk7.com/BlueDavy/archive/2006/05/28/48593.html

    摘要:插件開發(fā)框架其實(shí)和目前開源界流行的MVC框架之類的相同,都決定了基于這個(gè)框架的開發(fā)方式,如基于MVC框架,就會(huì)按照MVC思想來進(jìn)行開發(fā),而插件開發(fā)框架呢,也是同樣如此,就要求基于插件的方式來進(jìn)行開發(fā),不過插件開發(fā)框架和MVC框架又有不同,插件開發(fā)框架是一個(gè)可以成為系統(tǒng)基礎(chǔ)架構(gòu)的框架,而MVC框架通常來講不足以成為,如在目前的MVC框架Webwork、Struts上我們通常都需要加上Spring、Hibernate來構(gòu)成系統(tǒng)完整的基礎(chǔ)架構(gòu),這個(gè)時(shí)候由于MVC框架的實(shí)現(xiàn)是沒有標(biāo)準(zhǔn)可參照的,就造成了在各種系統(tǒng)中形成了不同的但很類似的基礎(chǔ)架構(gòu),但卻造成了無法復(fù)用的現(xiàn)象;插件開發(fā)框架則是作為統(tǒng)一系統(tǒng)基礎(chǔ)架構(gòu)的一種開發(fā)方式,它使得系統(tǒng)的復(fù)用成為了可能,而同時(shí)由于插件開發(fā)框架對(duì)于動(dòng)態(tài)性的支持,使得系統(tǒng)更加的靈活和可擴(kuò)展。來看看一個(gè)插件開發(fā)框架,應(yīng)該提供些什么東西,作為改變系統(tǒng)架構(gòu)思想的框架,插件框架需要考慮很多方面,如開發(fā)、測(cè)試、部署等,總結(jié)下來一個(gè)插件框架應(yīng)提供插件的開發(fā)規(guī)范;插件開發(fā)、調(diào)試的IDE;

    posted @ 2006-09-30 22:53 Coolfiry 閱讀(271) | 評(píng)論 (0)編輯 收藏

         摘要: N皇后問題是一個(gè)典型的需要用回溯算法來解決的問題。回溯算法可以用遞歸方法來實(shí)現(xiàn),也可以用非遞歸方法來實(shí)現(xiàn)。用遞歸的方法來解決回溯的問題思路很清晰,但是耗費(fèi)的內(nèi)存資源較多,速度也較慢;非遞歸方法具有速度快和耗費(fèi)較少內(nèi)存資源的優(yōu)點(diǎn),但是程序的邏輯結(jié)構(gòu)卻很復(fù)雜——不過搞懂之后覺得也很簡(jiǎn)單。???在寫非遞歸算法之前,參考了網(wǎng)上的一些文章,但是覺得那些程序都很晦澀難懂,而且存在一些問題,我索性自己寫了一個(gè),...  閱讀全文

    posted @ 2006-09-27 22:20 Coolfiry 閱讀(468) | 評(píng)論 (0)編輯 收藏

    煩的很啊,但要認(rèn)認(rèn)真真做人,兢兢業(yè)業(yè)做事哦

    posted @ 2006-09-27 22:15 Coolfiry 閱讀(264) | 評(píng)論 (0)編輯 收藏

    網(wǎng)站如何做分布式(集群)的大綱

    何時(shí)要用分布式

    • 單臺(tái)服務(wù)器無法承受壓力。
    • 需要實(shí)現(xiàn)發(fā)生錯(cuò)誤時(shí)候,自動(dòng)切換
    • 學(xué)習(xí)或者測(cè)試分布式技術(shù)

    應(yīng)用分布式的場(chǎng)景


    一、提供多個(gè)對(duì)外的接口,按照一定規(guī)則,分派不同請(qǐng)求由不同接口來處理。
    這時(shí)候需要考慮:
    • 如何實(shí)現(xiàn)負(fù)載均衡
      • 在哪個(gè)層次實(shí)現(xiàn)轉(zhuǎn)移負(fù)載
      • 負(fù)載的均衡如何實(shí)現(xiàn)
    • 如何實(shí)現(xiàn)故障轉(zhuǎn)移
      • 如何監(jiān)控故障
      • 如何切換服務(wù)

    二、把一個(gè)功能拆分成多個(gè)功能,不同功能分布部署到不同服務(wù)器上

    • 對(duì)外功能的拆分?
      • http://news.sina.com.cn/ http://sports.sina.com.cn/ http://mobile.sina.com.cn/
      • http://www.microsoft.com/china/? http://www.microsoft.com/downloads/
      • SOA
    • n層架構(gòu),其中的一些層分布到不同服務(wù)器上
      • WEB + DB 模式

    網(wǎng)站請(qǐng)求中的分布式

    按照請(qǐng)求流程,我們可以在以下環(huán)節(jié)按照一定規(guī)則,把用戶的請(qǐng)求分流到不同服務(wù)器上:

    • Web Client Level
      • 例子:QQ 設(shè)置中你可以選擇登陸的服務(wù)器IP
    • DNS Based Selection
      • 優(yōu)點(diǎn):
      • 缺點(diǎn):
        • 不能區(qū)分服務(wù)器的差異,也不能反映服務(wù)器的當(dāng)前運(yùn)行狀態(tài)。
        • DNS 的刷新需要時(shí)間,無法及時(shí)故障切換。
    • TCP balancing proxies
      • 硬件
      • 軟件
    • HTTP-aware routers

    • URL重定向

    網(wǎng)站應(yīng)用中的分布式

    • 代理服務(wù)器實(shí)現(xiàn)請(qǐng)求的分離
      • Squid是Linux下一個(gè)緩存Internet數(shù)據(jù)的代理服務(wù)器軟件
    • 拆分網(wǎng)站對(duì)外功能
      • 不同域名前、后綴
      • URL 重寫
    • SOA
      • 每個(gè)Service 分布到一臺(tái)服務(wù)器上
    • n 層架構(gòu)
      • 緩存分布式部署
        • 文件Cache
        • 內(nèi)存Cache (memcached )
          • http://www.danga.com/memcached/
          • https://sourceforge.net/projects/memcacheddotnet/
      • DB分布式集群部署
        • 故障轉(zhuǎn)移
        • 發(fā)布訂閱
        • 分布式分區(qū)視圖
      • 應(yīng)用服務(wù)器(比如定時(shí)發(fā)送郵件通知的服務(wù))

      • 相關(guān)技術(shù):
        • 企業(yè)服務(wù)
        • .net Remoting
        • WCF
        • Web Service

    ?

    如何判斷一個(gè)應(yīng)用是否支持分布式

    如果發(fā)現(xiàn)某一部分應(yīng)用需要做分布式了,就可以按照以下思路來考慮如何改造:

    從應(yīng)用所用數(shù)據(jù)看是否支持分布式

    • 多份并存數(shù)據(jù)(一個(gè)數(shù)據(jù)存在多份)最大多長(zhǎng)時(shí)間同步一次是可接受的。
      • 內(nèi)存緩存的數(shù)據(jù)跟數(shù)據(jù)庫的數(shù)據(jù)(頁面級(jí)緩存和業(yè)務(wù)邏輯緩存)
      • 靜態(tài)文件跟數(shù)據(jù)庫
      • 查詢數(shù)據(jù)庫跟業(yè)務(wù)變更數(shù)據(jù)庫
    • 數(shù)據(jù)按照一定規(guī)則拆分(一個(gè)數(shù)據(jù)只存在一份)對(duì)業(yè)務(wù)是否有影響
      • 過去每年的數(shù)據(jù)遷移到一個(gè)對(duì)應(yīng)歷史庫中。
      • 專用的圖片服務(wù)器 http://pics.ebaystatic.com/

    此處可分析:QQ的在線用戶數(shù)據(jù),會(huì)是如何處理的呢?

    從應(yīng)用邏輯過程看是否支持分布式

    • 是否可以并行執(zhí)行這個(gè)邏輯過程

    • 這個(gè)邏輯過程是否可以拆分成幾個(gè)松耦合的過程

    微軟技術(shù)支持的5種分布式

    夏桅的這篇博客中的圖表就可以很詳細(xì)的對(duì)比這5種分布式:

    Windows的第五種群集方案 - CCS

    posted @ 2006-09-21 15:34 Coolfiry 閱讀(789) | 評(píng)論 (0)編輯 收藏

    http://www.tiobe.com/index.htm?tiobe_index

    這次 vb?和 vb.net 的數(shù)據(jù)再次合并了。C 系的語言 (java, c, c++, C#) 總體占了 50% 強(qiáng)。在 .net 環(huán)境中,vb 大概還是多過新生代的 C# 。
    這次仔細(xì)了看了看。才發(fā)覺這個(gè)升降是去年同期的比較。是能夠使用此語言的工程師,課程,獨(dú)立軟件生產(chǎn)商的相關(guān)比例。不直接代表用語言出了多少代碼。

    原來 Ruby 和 Java 基本上是同時(shí)代的東西。http://www.ruby-lang.org/? http://rubycn.ce-lab.net/?由日本人發(fā)明、流行的東西。
    從運(yùn)行效率、性能上來看,C/C++ 比 Java 強(qiáng)。Java 比 Ruby 強(qiáng)。在比較簡(jiǎn)單的功能中,Java 和 C/C++ 可以相當(dāng)接近。當(dāng)程序的算法比較復(fù)雜,涉及大量數(shù)據(jù)的時(shí)候,Java 速度還是會(huì)落后近一個(gè)數(shù)量級(jí)。此時(shí),內(nèi)存使用也會(huì)有幾倍的差異。
    http://blog.csdn.net/rmartin/archive/2006/08/30/1143161.aspx
    http://www.butunclebob.com/ArticleS.UncleBob.SpeedOfJavaCppRuby

    不知道 D 是什么東東了。倒是在許久以前,從公司的首設(shè)博士那里聽到過一耳朵。感覺語法結(jié)構(gòu)還是 C like 的。http://www.digitalmars.com/d/index.htmlhttp://www.soho-works.net/BLOG/326.asp?http://libai.math.ncu.edu.tw/bcc16/user/forum/read.php?f=15&i=14

    http://www.tiobe.com/index.htm?tiobe_index

    TIOBE Programming Community Index for September 2006

    September Headline: Ruby and D are the hot languages of today

    tiobe language 200609

    tpci trends 200609

    posted @ 2006-09-14 13:35 Coolfiry 閱讀(602) | 評(píng)論 (0)編輯 收藏

    主站蜘蛛池模板: 国产黄色一级毛片亚洲黄片大全| 九九九国产精品成人免费视频| 日韩在线免费视频| 亚洲小说区图片区| 曰批全过程免费视频播放网站| 亚洲AV日韩AV天堂一区二区三区| 黄网站免费在线观看| 国产精品亚洲成在人线| 99在线视频免费观看| 亚洲日韩国产精品第一页一区| 九九热久久免费视频| 久久久久久a亚洲欧洲aⅴ| 大地影院MV在线观看视频免费| 国产亚洲精品va在线| 免费国产污网站在线观看| 亚洲av一综合av一区| 最近中文字幕大全中文字幕免费 | 亚洲av片不卡无码久久| 7723日本高清完整版免费| 91丁香亚洲综合社区| 嫩草影院免费观看| 苍井空亚洲精品AA片在线播放| 免费v片视频在线观看视频| 日本视频免费观看| 久久亚洲综合色一区二区三区| 男女午夜24式免费视频| 亚洲精品自拍视频| 无码日韩人妻av一区免费| 亚洲精品无码av中文字幕| 免费日本黄色网址| 精品久久久久久无码免费| 久久亚洲国产精品一区二区| 蜜桃成人无码区免费视频网站| 亚洲国产av美女网站| 午夜精品在线免费观看| 老司机午夜在线视频免费| 国产性爱在线观看亚洲黄色一级片| 91成人免费福利网站在线| 亚洲色偷偷av男人的天堂| 在线观看免费人成视频色9| 相泽南亚洲一区二区在线播放|