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

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

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

    from:http://www.infoq.com/cn/articles/micro-soa-2

    上一篇文章中,我說到SOA是一個特別大的話題,不但沒有絕對統(tǒng)一的原則,而且很多原則本身的內(nèi)容也具備相當(dāng)模糊性和寬泛性。雖然我們可以說SOA ≈ 模塊化開發(fā) + 分布式計算,但由于其原則的模糊性,我們?nèi)匀缓茈y說什么應(yīng)用是絕對符合SOA的,只能識別出哪些是不符合SOA的。

    本篇將對8種可操作的服務(wù)設(shè)計原則進(jìn)行細(xì)化的分析,作為SOA實踐的參考。

    服務(wù)設(shè)計原則1:優(yōu)化遠(yuǎn)程調(diào)用

    這里的遠(yuǎn)程調(diào)用特指RPC(Remote Procedure Call)。當(dāng)然更面向?qū)ο蟮恼f法應(yīng)該是遠(yuǎn)程方法調(diào)用或者遠(yuǎn)程服務(wù)調(diào)用等等。

    由于SO接口通常要被遠(yuǎn)程訪問,而網(wǎng)絡(luò)傳輸,對象序列化/反序列化等開銷都遠(yuǎn)遠(yuǎn)超過本地Object訪問幾個數(shù)量級,所以要加快系統(tǒng)的響應(yīng)速度、減少帶寬占用和提高吞吐量,選擇高性能的遠(yuǎn)程調(diào)用方式經(jīng)常是很重要的。

    但是遠(yuǎn)程調(diào)用方式往往又要受限于具體的業(yè)務(wù)和部署環(huán)境,比如內(nèi)網(wǎng)、外網(wǎng)、同構(gòu)平臺、異構(gòu)平臺等等。有時還要考慮它對諸如分布式事務(wù),消息級別簽名/加密,可靠異步傳輸?shù)确矫娴闹С殖潭龋ㄟ@些方面通常被稱為SLA:service level agreement),甚至還包括開發(fā)者的熟悉和接受程度等等。

    因此,遠(yuǎn)程調(diào)用方式往往需要根據(jù)具體情況做出選擇和權(quán)衡。

    以Java遠(yuǎn)程Service為例分析不同場景下,傳輸方式的某些可能較好選擇:

    • 內(nèi)網(wǎng) + 同框架Java客戶端 + 大并發(fā):多路復(fù)用的TCP長連接 + kryo (二進(jìn)制序列化) (kryo也可以用Protostuff,F(xiàn)ST等代替)
    • 內(nèi)網(wǎng) + 不同框架Java客戶端:TCP + Kryo
    • 內(nèi)網(wǎng) + Java客戶端 + 2PC分布式事務(wù):RMI/IIOP (TCP + 二進(jìn)制)
    • 內(nèi)網(wǎng) + Java客戶端 + 可靠異步調(diào)用:JMS + Kryo (TCP + 二進(jìn)制)
    • 內(nèi)網(wǎng) + 不同語言客戶端:thrift(TCP + 二進(jìn)制序列化)
    • 外網(wǎng) + 不同語言客戶端 + 企業(yè)級特性:HTTP + WSDL + SOAP (文本)
    • 外網(wǎng) + 兼顧瀏覽器、手機(jī)等客戶端:HTTP + JSON (文本)
    • 外網(wǎng) + 不同語言客戶端 + 高性能:HTTP + ProtocolBuffer (二進(jìn)制)

    簡單來說,從性能上講,tcp協(xié)議 + 二進(jìn)制序列化更適合內(nèi)網(wǎng)應(yīng)用。從兼容性、簡單性上來說,http協(xié)議 + 文本序列化更適合外網(wǎng)應(yīng)用。當(dāng)然這并不是絕對的。另外,tcp協(xié)議在這里并不是限定遠(yuǎn)程調(diào)用協(xié)議一定只能是位于OSI網(wǎng)絡(luò)模型的第四層的原始tcp,它可以包含tcp之上的任何非http協(xié)議。

    所以,回答上面提到的問題,WebServices (經(jīng)典的WSDL+SOAP+HTTP)雖然是最符合前述SOA設(shè)計原則的技術(shù),但并不等同于SOA,我認(rèn)為它只是滿足了SOA的底線,而未必是某個具體場景下的最佳選擇。這正如一個十項全能選手在每個單項上是很難和單項冠軍去競爭的。更理想的SOA Service最好能在可以支持WebServices的同時,支持多種遠(yuǎn)程調(diào)用方式,適應(yīng)不同場景,這也是Spring Remoting,SCA,Dubbo,F(xiàn)inagle等分布式服務(wù)框架的設(shè)計原則。

    遠(yuǎn)程調(diào)用技術(shù)解釋:HTTP + JSON適合SOA嗎?

    JSON簡單易讀,通用性極佳,甚至能很好支持瀏覽器客戶端,同時也常被手機(jī)APP使用,大有取代XML之勢。

    但JSON本身缺乏像XML那樣被廣泛接受的標(biāo)準(zhǔn)schema,而一般的HTTP + JSON的遠(yuǎn)程調(diào)用方式也缺乏像Thrift,CORBA,WebServices等等那樣標(biāo)準(zhǔn)IDL(接口定義語言),導(dǎo)致服務(wù)端和客戶端之間不能形成強(qiáng)的服務(wù)契約,也就不能做比如自動代碼生成。所以HTTP + JSON在降低了學(xué)習(xí)門檻的同時,可能顯著的增加復(fù)雜應(yīng)用的開發(fā)工作量和出錯可能性。

    例如,新浪微博提供了基于HTTP + JSON的Open API,但由于業(yè)務(wù)操作比較復(fù)雜,又在JSON上封裝實現(xiàn)了各種語言的客戶端類庫,來減少用戶的工作量。

    為了解決這方面的問題,業(yè)界有很多不同方案來為HTTP + JSON補(bǔ)充添加IDL,如RSDL、JSON-WSP、WADL、WSDL 2.0等等,但事實上它們的接受度都不太理想。

    另外值得一提的是,JSON格式和XML一樣有冗余,即使做GZIP壓縮之類的優(yōu)化,傳輸效率通常也不如很多二進(jìn)制格式,同時壓縮、解壓還會引入額外的性能開銷。

    遠(yuǎn)程調(diào)用技術(shù)解釋:Apache Thrift多語言服務(wù)框架

    Thrift是最初來自facebook的一套跨語言的service開發(fā)框架,支持C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, JavaScript, Node.js, Smalltalk, Delphi等幾乎所有主流編程語言,具有極好的通用性。

    Thrift被facebook,twitter等巨頭以及開源社區(qū)都廣泛使用,是非常成熟的技術(shù)。

    Thrift的服務(wù)契約通過類似如下形式的IDL定義:

    struct User {     1: i32 id,     2: string name,     3: string password }  service UserService {     void store(1: User user),     UserProfile retrieve(1: i32 id) } 

    非常類似于C語言,易讀易寫,比WSDL簡單明了得多。比用java之類的編程語言也更方便,有時候可以把所有相關(guān)的接口和數(shù)據(jù)結(jié)構(gòu)定義放到同一個文件,發(fā)布出去的時候不用再打一個壓縮包之類,甚至可以直接粘貼到文檔中

    Thrift還提供工具,可以基于IDL自動生成各種語言對應(yīng)的服務(wù)端和客戶端代碼:

    [lishen@dangdang thrift]thrift --gen java user.thrift [lishen@dangdang thrift]$ thrift --gen cpp user.thrift [lishen@dangdang thrift]$ thrift --gen php user.thrift [lishen@dangdang thrift]$ thrift --gen csharp user.thrift 

    我認(rèn)為thrift是比WebServices更簡單高效的技術(shù),是在SOA中對WebServices最具有替代性的技術(shù)之一。

    遠(yuǎn)程調(diào)用技術(shù)解釋:多路復(fù)用的TCP長連接

    這是一種追求極致高性能高伸縮的方式,這里只做簡要介紹。

    比較典型的是twitter的Mux RPC協(xié)議以及google的SPDY協(xié)議,在其中多個請求同時共用同一個長連接,即一個連接交替?zhèn)鬏敳煌埱蟮淖止?jié)塊。它既避免了反復(fù)建立連接開銷,也避免了連接的等待閑置從而減少了系統(tǒng)連接總數(shù),同時還避免了TCP順序傳輸中的線頭阻塞(head-of-line blocking)問題。

    另外,國內(nèi)比較著名的開源dubbo框架的默認(rèn)RPC協(xié)議,以及業(yè)界許多小型開源RPC框架也都是類似的思路。

    采用多路復(fù)用機(jī)制后,一般就要求服務(wù)器端和客戶端都支持額外的類似于會話層(即OSI網(wǎng)絡(luò)模型第六層)的語義,導(dǎo)致它們必須要依賴于同一套RPC框架。

    其他很多RPC機(jī)制都是使用TCP短連接。即使有些RPC使用了長連接,但一個連接同一時間只能發(fā)送一個請求,然后連接就處于閑置狀態(tài),來等待接收該請求的響應(yīng),待響應(yīng)完畢,該連接才能被釋放或者復(fù)用。

    HTTP 1.1也支持一種基于pipeline模式的長連接,其中多個HTTP請求也可共用一個連接,但它要求響應(yīng)(response)也必須按照請求(request)的順序傳輸返回,即FIFO先進(jìn)先出。而在完全多路復(fù)用的連接中,哪個的響應(yīng)先ready就可以先傳輸哪個,不用排隊。

    當(dāng)然,短連接、長連接和多路復(fù)用長連接之間不存在絕對的好壞,需要取決于具體業(yè)務(wù)和技術(shù)場景,在此不詳細(xì)展開了。

    遠(yuǎn)程調(diào)用技術(shù)解釋:Java高效序列化

    最近幾年,各種新的Java高效序列化方式層出不窮,不斷刷新序列化性能的上限,例如Kryo,F(xiàn)ST等開源框架。它們提供了非常高效的Java對象的序列化和反序列化實現(xiàn),相比JDK標(biāo)準(zhǔn)的序列化方式(即基于Serializable接口的標(biāo)準(zhǔn)序列化,暫不考慮用諸如Externalizable接口的定制序列化),在典型場景中,其序列化時間開銷可能縮短20倍以上,生成二進(jìn)制字節(jié)碼的大小可能縮減4倍以上。

    另外,這些高效Java序列化方式的開銷也顯著少于跨語言的序列化方式如thrift的二進(jìn)制序列化,或者JSON等等

    遠(yuǎn)程調(diào)用技術(shù)解釋:RMI/IIOP和分布式事務(wù)

    RMI/IIOP是Java EE中標(biāo)準(zhǔn)的遠(yuǎn)程調(diào)用方式,IIOP是CORBA的協(xié)議,只有IIOP上的RMI才支持兩階段提交的分布式事務(wù),同時提供和CORBA的互操作。

    當(dāng)然,嚴(yán)格的兩階段提交事務(wù)并不高效,還可能嚴(yán)重影響系統(tǒng)伸縮性甚至可用性等等,一般只應(yīng)用在非常關(guān)鍵的業(yè)務(wù)中。

    遠(yuǎn)程調(diào)用技術(shù)解釋:Google ProtocolBuffer跨語言序列化

    ProtocolBuffer是google開發(fā)的跨語言的高效二進(jìn)制序列化方式,其序列化性能和thrift比較類似。事實上thrift最初就是ProtocolBuffer的仿制品。但它和thrift最大的不同是他沒有自帶的RPC實現(xiàn)(因為google沒有將RPC部分開源,但有大量第三方實現(xiàn))。

    由于不和RPC方式耦合,反而使得ProtocolBuffer能被方便的集成進(jìn)大量已有的系統(tǒng)和框架中。在國內(nèi)它也被百度、淘寶等廣泛的應(yīng)用在Open API中,和HTTP搭配作為一種高效的跨平臺跨組織的集成方式。

    服務(wù)設(shè)計原則2:消除冗余數(shù)據(jù)

    同樣由于service的遠(yuǎn)程調(diào)用開銷很高,所以在它的輸入?yún)?shù)和返回結(jié)果中,還要盡量避免攜帶當(dāng)前業(yè)務(wù)用例不需要的冗余的字段,來減少序列化和傳輸?shù)拈_銷。同時,去掉冗余字段也可以簡化接口,避免給外部用戶帶來不必要的業(yè)務(wù)困惑。

    比如article service中有個返回article list的方法

    List<Article> getArticles(...)

    如果業(yè)務(wù)需求僅僅是要列出文章的標(biāo)題,那么在返回的article中就要避免攜帶它的contents等等字段。

    這里經(jīng)典解決方案就是引入OO中常用的Data Transfer Object (DTO)模式,專門針對特定service的用例來定制要傳輸?shù)臄?shù)據(jù)字段。這里就是添加一個AriticleSummary的額外數(shù)據(jù)傳輸對象:

    List<ArticleSummary> getArticleSummaries(...)

    額外的DTO確實是個麻煩,而一般OO程序通常則可直接返回自己的包含冗余的業(yè)務(wù)模型。

    服務(wù)設(shè)計原則3:粗粒度契約

    同樣由于遠(yuǎn)程調(diào)用開銷高,同時service的外部使用者對特定業(yè)務(wù)流程的了解也比不上組織內(nèi)部的人,所以service的契約(接口)通常需要是粗粒度的,其中的一個操作就可能對應(yīng)到一個完整的業(yè)務(wù)用例或者業(yè)務(wù)流程,這樣既能減少遠(yuǎn)程調(diào)用次數(shù),同時又降低學(xué)習(xí)成本和耦合度。

    而OO接口通常可以是非常細(xì)粒度的,提供最好的靈活性和重用性。

    例如,article service支持批量刪除文章,OO接口中可以提供

    deleteArticle(long id)

    供用戶自己做循環(huán)調(diào)用(暫不考慮后端SQL之類優(yōu)化),但SO接口中,則最好提供

    deleteArticles(Set<Long> ids)

    供客戶端調(diào)用,將可能的N次遠(yuǎn)程調(diào)用減少為一次。

    例如,下訂單的用例,要有一系列操作

    addItem -> addTax -> calculateTotalPrice -> placeOrder 

    OO中我們完全可以讓用戶自己來靈活選擇,分別調(diào)用這些細(xì)粒度的可復(fù)用的方法。但在SO中,我們需要將他們封裝到一個粗粒度的方法供用戶做一次性遠(yuǎn)程調(diào)用,同時也隱藏了內(nèi)部業(yè)務(wù)的很多復(fù)雜性。另外,客戶端也從依賴4個方法變成了依賴1個方法,從而大大降低了程序耦合度。

    順便值得一提的是,如果上面訂單用例中每個操作本身也是遠(yuǎn)程的service(通常在內(nèi)網(wǎng)之中),這種粗粒度封裝就變成了經(jīng)典的service composition(服務(wù)組合)甚至service orchestration(服務(wù)編排)了。這種情況下粗粒度service同樣可能提高了性能,因為對外網(wǎng)客戶來說,多次跨網(wǎng)的遠(yuǎn)程調(diào)用變成了一次跨網(wǎng)調(diào)用 + 多次內(nèi)網(wǎng)調(diào)用。

    對這種粗粒度service封裝和組合,經(jīng)典解決方案就是引入OO中常用的Facade模式,將原來的對象屏蔽到專門的“外觀”接口之后。同時,這里也很可能要求我們引入新的service參數(shù)/返回值的數(shù)據(jù)結(jié)構(gòu)來組合原來多個操作的對象模型,這就同樣用到前述的DTO模式。

    一個簡單Facade示例(FooService和BarService是兩個假想的本地OO service,façade將它們的結(jié)果值組合返回):

    class FooBarFacadeImpl implements FooBarFacade {     private FooService fooService;     private BarService barService;      public FooBarDto getFooBar() {         FooBarDto fb = new FooBarDto();         fb.setFoo(fooService.getFoo());         fb.setBar(barService.getBar());         return fb;     } }   

    當(dāng)然,有的時候也可以不用facade和DTO,而在是FooService和BarService之外添加另一個本地service和domain model,這要和具體業(yè)務(wù)場景有關(guān)。

    服務(wù)設(shè)計原則4:通用契約

    由于service不假設(shè)用戶的范圍,所以一般要支持不同語言和平臺的客戶端。但各種語言和平臺在功能豐富性上有很大差異,這就決定了服務(wù)契約必須取常見語言、平臺以及序列化方式的最大公約數(shù),才能保證service廣泛兼容性。由此,服務(wù)契約中不能有某些語言才具備的高級特性,參數(shù)和返回值也必須是被廣泛支持的較簡單的數(shù)據(jù)類型(比如不能有對象循環(huán)引用)。

    如果原有的OO接口不能滿足以上要求,則在此我們同樣需要上述的Facade和DTO,將OO接口轉(zhuǎn)換為通用的SO契約。

    例如原有對象模型

    class Foo {    private Pattern regex; }

    Pattern是Java特有的預(yù)編譯好的,可序列化的正則表達(dá)式(可提高性能),但在沒有特定框架支持下,可能不好直接被其他語言識別,所以可添加DTO:

    class FooDto {    private String regex; }

    服務(wù)設(shè)計原則5:隔離變化

    雖然OO和SO都追求低耦合,但SO由于使用者范圍極廣,就要求了更高程度的低耦合性。

    比如前述的article service,OO中可以直接返回article對象,而這個article對象在OO程序內(nèi)部可能做為核心的建模的domain model,甚至作為O/R mapping等等。而在SO如果還直接返回這個article,即使沒有前面所說的冗余字段,復(fù)雜類型等問題,也可能讓外部用戶與內(nèi)部系統(tǒng)的核心對象模型,甚至O/R mapping機(jī)制,數(shù)據(jù)表結(jié)構(gòu)等等產(chǎn)生了一定關(guān)聯(lián)度,這樣一來,內(nèi)部的重構(gòu)經(jīng)常都會可能影響到外部的用戶。

    所以,這里再次對Facade和DTO產(chǎn)生了需求,用它們作為中介者和緩沖帶,隔離內(nèi)外系統(tǒng),把內(nèi)部系統(tǒng)變化對外部的沖擊減少到最小程度。

    服務(wù)設(shè)計原則6:契約先行

    Service是往往涉及不同組織之間的合作,而按照正常邏輯,兩個組織之間合作的首要任務(wù),就是先簽訂明確的契約,詳細(xì)規(guī)定雙方合作的內(nèi)容,合作的形式等等,這樣才能對雙方形成強(qiáng)有力的約束和保障,同時大家的工作也能夠并行不悖,不用相互等待。因此SOA中,最佳的實踐方式也是契約先行,即先做契約的設(shè)計,可以有商務(wù),管理和技術(shù)等不同方面的人員共同參與,并定義出相應(yīng)的WSDL或者IDL,然后在開發(fā)的時候再通過工具自動生成目標(biāo)語言的對應(yīng)代碼。

    對于WSDL來說,做契約先行的門檻略高,如果沒有好的XML工具很難手工編制。但對于Thrift IDL或者ProtocolBuffer等來說,由于它們和普通編程語言類似,所以契約設(shè)計相對是比較容易的。另外,對于簡單的HTTP + JSON來說(假設(shè)不補(bǔ)充使用其他描述語言),由于JSON沒有標(biāo)準(zhǔn)的schema,所以是沒法設(shè)計具有強(qiáng)約束力的契約的,只能用另外的文檔做描述或者用JSON做輸入輸出的舉例。

    但是,契約先行,然后再生成服務(wù)提供端的代碼,畢竟給service開發(fā)工作帶來了較大的不便,特別是修改契約的時候?qū)е麓a需要重寫。因此,這里同樣可能需要引入Facade和DTO,即用契約產(chǎn)生的都是Facade和DTO代碼,它們負(fù)責(zé)將請求適配和轉(zhuǎn)發(fā)到其他內(nèi)部程序,而內(nèi)部程序則可以保持自己的主導(dǎo)性和穩(wěn)定性。

    另外,契約先行可能會給前面提到的多遠(yuǎn)程調(diào)用支持帶來一些麻煩。

    當(dāng)然契約先行也許并不是能被廣泛接受的實踐方式,就像敏捷開發(fā)中“測試先行”(也就是測試驅(qū)動開發(fā))通常都是最佳實踐,但真正施行的團(tuán)隊卻非常之少,這方面還需要不斷摸索和總結(jié)。但我們至少可以認(rèn)為Echo中Java2WSDL并不被認(rèn)為是SOA的最佳實踐。

    服務(wù)設(shè)計原則7:穩(wěn)定和兼容的契約

    由于用戶范圍的廣泛性,所以SO的服務(wù)契約和Java標(biāo)準(zhǔn)API類似,在公開發(fā)布之后就要保證相當(dāng)?shù)姆€(wěn)定性,不能隨便被重構(gòu),即使升級也要考慮盡可能的向下兼容性。同時,如果用契約先行的方式,以后頻繁更改契約也導(dǎo)致開發(fā)人員要不斷重做契約到目標(biāo)語言映射,非常麻煩。

    這就是說SO對契約的質(zhì)量要求可能大大高于一般的OO接口,理想的情況下,甚至可能需要專人(包括商務(wù)人員)來設(shè)計和評估SO契約(不管是否用契約先行的方式),而把內(nèi)部的程序?qū)崿F(xiàn)交給不同的人,而兩者用Facade和DTO做橋梁。

    服務(wù)設(shè)計原則8:契約包裝

    前述原則基本都是針對service提供端來講的,而對service消費端而言,通過契約生成對應(yīng)的客戶端代碼,經(jīng)常就可以直接使用了。當(dāng)然,如果契約本身就是Java接口之類(比如在Dubbo,Spring Remoting等框架中),可以略過代碼生成的步驟。

    但是,service的返回值(DTO)和service接口(Facade),可能被消費端的程序到處引用到。

    這樣消費端程序就較強(qiáng)的耦合在服務(wù)契約上了,如果服務(wù)契約不是消費端定義的,消費端就等于把自己程序的部分主導(dǎo)權(quán)完全讓渡給了別人。

    一旦契約做更改,或者消費端要選擇完全不同的service提供方(有不同的契約),甚至改由本地程序自己來實現(xiàn)相關(guān)功能,修改工作量就可能非常大了。

    另外,通過契約生成的客戶端代碼,經(jīng)常和特定傳輸方式是相關(guān)的(比如webservices stub),這樣給切換遠(yuǎn)程調(diào)用方式也會帶來障礙。

    因此,就像在通常應(yīng)用中,我們要包裝數(shù)據(jù)訪問邏輯(OO中的DAO或者Repository模式),或者包裝基礎(chǔ)服務(wù)訪問邏輯(OO中的Gateway模式)一樣,在較理想的SOA設(shè)計中,我們也可以考慮包裝遠(yuǎn)程service訪問邏輯,由于沒有恰當(dāng)?shù)拿Q,暫時稱之為Delegate Service模式,它由消費端自己主導(dǎo)定義接口和參數(shù)類型,并將調(diào)用轉(zhuǎn)發(fā)給真正的service客戶端生成代碼,從而對它的使用者完全屏蔽了服務(wù)契約,這些使用者甚至不知道這個服務(wù)到底是遠(yuǎn)程提供的的還是本地提供的。

    此外,即使我們在消費端是采用某些手工調(diào)用機(jī)制(如直接構(gòu)建和解析json等內(nèi)容,直接收發(fā)JMS消息等等),我們同樣可以用delegate service來包裝相應(yīng)的邏輯。

    delegate service示例1:

    // ArticlesService是消費端自定義的接口 class ArticleServiceDelegate implements ArticlesService {     // 假設(shè)是某種自動生成的service客戶端stub類     private ArticleFacadeStub stub;      public void deleteArticles(List<Long> ids) {         stub.deleteArticles(ids);     } }   

    delegate service示例2:

    // ArticlesService是消費端自定義的接口 class ArticleServiceDelegate implements ArticlesService {      public void deleteArticles(List<Long> ids) {         // 用JMS和FastJson手工調(diào)用遠(yuǎn)程service         messageClient.sendMessage(queue, JSON.toJSONString(ids));     } }   

    從面向?qū)ο蟮矫嫦蚍?wù),再從面向服務(wù)到面向?qū)ο?/h2>

    總結(jié)上面的幾個原則,雖然只是談及有限的幾個方面,但大致也可看出OO和SO在實際的設(shè)計開發(fā)中還是有不少顯著的不同之處,而且我們沒有打算用SO的原則來取代過去的OO設(shè)計,而是引入額外的層次、對象和OO設(shè)計模式,來補(bǔ)充傳統(tǒng)的OO設(shè)計。

    其實就是形成了這種調(diào)用流程:

    • service提供端:OO程序 <- SOA層(Facade和DTO)<- 遠(yuǎn)程消費端

    • service消費端:OO程序 -> Delegate Service -> SOA層(Facade和DTO 或者 其他動態(tài)調(diào)用機(jī)制)-> 遠(yuǎn)程提供端

    Facade、DTO和Delegate Service負(fù)責(zé)做OO到SO和SO到OO的中間轉(zhuǎn)換。

    現(xiàn)在,可以回答Echo示例中的問題:通過“透明的”配置方式,將OO程序發(fā)布為遠(yuǎn)程Service,雖然可能較好的完成了從本地對象到遠(yuǎn)程對象的跨越,但通常并不能較好的完成OO到SO的真正跨越。

    同時,透明配置方式也通常無法直接幫助遺留應(yīng)用(如ERP等)轉(zhuǎn)向SOA。

    當(dāng)然,在較為簡單和使用范圍確定很有限應(yīng)用(比如傳統(tǒng)和局部的RPC)中,透明式遠(yuǎn)程service發(fā)布會帶來極大的便利。

    另外,上面對SO的所有討論都集中在RPC的方式,其實SO中也用message的方式做集成,它也是個大話題,暫時不在此詳論了。

    為什么不能放棄面向?qū)ο螅?/h2>

    SO是有它的特定場景的,比如遠(yuǎn)程的,范圍不定的客戶端。所以它的那些設(shè)計原則并不能被借用來指導(dǎo)一般性的程序開發(fā),比如很多OO程序和SO原則完全相反,經(jīng)常都要提供細(xì)粒度接口和復(fù)雜參數(shù)類型以追求使用的使用靈活性和功能的強(qiáng)大性。

    就具體架構(gòu)而言,我認(rèn)為SOA層應(yīng)該是一個很薄的層次(thin layer),將OO應(yīng)用或者其他遺留性應(yīng)用加以包裝和適配以幫助它們面向服務(wù)。其實在通常的web開發(fā)中,我們也是用一個薄的展現(xiàn)層(或者叫Web UI層之類)來包裝OO應(yīng)用,以幫助它們面向瀏覽器用戶。因此,F(xiàn)açade、DTO等不會取代OO應(yīng)用中核心的Domain Model、Service等等 (這里的service是OO中service,未必是SO的)。

    綜合起來,形成類似下面的體系結(jié)構(gòu):

    理想和現(xiàn)實

    需要特別指出的是,上面提到的諸多SO設(shè)計原則是在追求一種相對理想化的設(shè)計,以達(dá)到架構(gòu)的優(yōu)雅性,高效性,可重用性,可維護(hù)性,可擴(kuò)展性等等。

    而在現(xiàn)實中任何理論和原則都可能是需要作出適當(dāng)妥協(xié)的,因為現(xiàn)實是千差萬別的,其情況遠(yuǎn)比理論復(fù)雜,很難存在放之四海而皆準(zhǔn)的真理。

    而且很多方面似乎本來也沒有必要追求完美和極致,比如如果有足夠能力擴(kuò)充硬件基礎(chǔ)設(shè)施,就可以考慮傳輸一些冗余數(shù)據(jù),選擇最簡單傳輸方式,并多來幾次遠(yuǎn)程調(diào)用等等,以減輕設(shè)計開發(fā)的工作量。

    那么理想化的原則就沒有意義了嗎?比如領(lǐng)域驅(qū)動設(shè)計(Domain-Driven Design)被廣泛認(rèn)為是最理想的OO設(shè)計方式,但極少有項目能完全采用它;測試驅(qū)動開發(fā)也被認(rèn)為是最佳的敏捷開發(fā)方式,但同樣極少有團(tuán)隊能徹底采用它。但是,恐怕沒有多少人在了解它們之后會否認(rèn)它們巨大的意義。

    理想化的原則可以更好的幫助人們理解某類問題的本質(zhì),并做為好的出發(fā)點或者標(biāo)桿,幫助那些可以靈活運用,恰當(dāng)取舍的人取得更大的成績,應(yīng)付關(guān)鍵的挑戰(zhàn)。這正如孔子說的“取乎其上,得乎其中;取乎其中,得乎其下;取乎其下,則無所得矣”。

    另外,值得一提的是,SOA從它的理念本身來說,就帶有一些的理想主義的傾向,比如向“全世界”開放,不限定客戶端等等。如果真愿意按SOA的路徑走,即使你是個土豪,偷個懶比浪費網(wǎng)絡(luò)帶寬重要,但說不定你的很多用戶是土鱉公司,浪費幾倍的帶寬就大大的影響他們的利潤率。

    延伸討論:SOA和敏捷軟件開發(fā)矛盾嗎?

    SOA的服務(wù)契約要求相當(dāng)?shù)姆€(wěn)定性,一旦公開發(fā)布(或者雙方合同商定)就不應(yīng)該有經(jīng)常的變更,它需要對很多方面有極高的預(yù)判。而敏捷軟件開發(fā)則是擁抱變化,持續(xù)重構(gòu)的。軟件設(shè)計大師Martin Fowler把它們歸結(jié)為計劃式設(shè)計和演進(jìn)式設(shè)計的不同。

    計劃理論(或者叫建構(gòu)理論)和演進(jìn)理論是近代哲學(xué)的兩股思潮,影響深遠(yuǎn),派生出了比如計劃經(jīng)濟(jì)和市場經(jīng)濟(jì),社會主義和自由主義等等各種理論。

    但是,計劃式設(shè)計和演進(jìn)式設(shè)計并不絕對矛盾,就像計劃經(jīng)濟(jì)和市場經(jīng)濟(jì)也不絕對矛盾,非此即彼,這方面需要在實踐中不斷摸索。前面我們討論的設(shè)計原則和架構(gòu)體系,就是將SOA層和OO應(yīng)用相對隔離,分而治之,在SOA層需要更多計劃式設(shè)計,而OO應(yīng)用可以相對獨立的演進(jìn),從而在一定程度緩解SOA和敏捷開發(fā)的矛盾。

    延伸討論:SOA和REST是一回事嗎?

    從最本質(zhì)的意義上講,REST(Representational State Transfer)實際是一種面向資源架構(gòu)(ROA),和面向服務(wù)架構(gòu)(SOA)是有根本區(qū)別的。

    例如,REST是基于HTTP協(xié)議,對特定資源做增(HTTP POST)、刪(HTTP DELETE)、改(HTTP PUT)、查(HTTP GET)等操作,類似于SQL中針對數(shù)據(jù)表的INSERT、DELETE、UPDATE、SELECT操作,故REST是以資源(資源可以類比為數(shù)據(jù))為中心的。而SOA中的service通常不包含這種針對資源(數(shù)據(jù))的細(xì)粒度操作,而是面向業(yè)務(wù)用例、業(yè)務(wù)流程的粗粒度操作,所以SOA是以業(yè)務(wù)邏輯為中心的。

    但是在實際使用中,隨著許多REST基本原則被不斷突破,REST的概念被大大的泛化了,它往往成為很多基于HTTP的輕量級遠(yuǎn)程調(diào)用的代名詞(例如前面提到過的HTTP + JSON)。比如,即使是著名的Twitter REST API也違反不少原始REST的基本原則。

    在這個泛化的意義上講,REST也可以說是有助于實現(xiàn)SOA的一種輕量級遠(yuǎn)程調(diào)用方式。

    SOA架構(gòu)的進(jìn)化

    前面討論的SOA的所有問題,基本都集中在service本身的設(shè)計開發(fā)。但SOA要真正發(fā)揮最大作用,還需要不斷演進(jìn)成更大的架構(gòu)(也就是從微觀SOA過渡到宏觀SOA),在此略作說明:

    • 第一個層次是service架構(gòu):開發(fā)各種獨立的service并滿足前面的一些設(shè)計原則,我們前面基本都集中在討論這種架構(gòu)。這些獨立的service有點類似于小孩的積木。

    • 第二個層次是service composition(組合)架構(gòu):獨立的service通過不同組合來構(gòu)成新的業(yè)務(wù)或者新的service。在理想情況下,可以用一種類似小孩搭積木的方式,充分發(fā)揮想象力,將獨立的積木(service)靈活的拼裝組合成新的形態(tài),還能夠自由的替換其中的某個構(gòu)件。這體現(xiàn)出SOA高度便捷的重用性,大大提高企業(yè)的業(yè)務(wù)敏捷度。

    • 第三個層次是service inventory(清單)架構(gòu):通過標(biāo)準(zhǔn)化企業(yè)服務(wù)清單(或者叫注冊中心)統(tǒng)一的組織和規(guī)劃service的復(fù)用和組合。當(dāng)積木越來越多了,如果還滿地亂放而沒有良好的歸類整理,顯然就玩不轉(zhuǎn)了。

    • 第四個層次是service-oriented enterprise架構(gòu)……

    總結(jié)

    至此,我們只是簡要的探討了微觀層面的SOA,特別是一些基本設(shè)計原則及其實踐方式,以期能夠略微展示SOA在實踐中的本質(zhì),以有助于SOA更好的落地,進(jìn)入日常操作層面。

    最后,打個比方:SOA不分貴賤(不分語言、平臺、組織),不遠(yuǎn)萬里(通過遠(yuǎn)程調(diào)用)的提供服務(wù)(service),這要求的就是一種全心全意為人民服務(wù)的精神……

    作者簡介

    沈理,當(dāng)當(dāng)網(wǎng)架構(gòu)師和技術(shù)委員會成員,主要負(fù)責(zé)當(dāng)當(dāng)網(wǎng)的SOA實施(即服務(wù)化)以及分布式服務(wù)框架的開發(fā)。以前也有在BEA、Oracle、Redhat等外企的長期工作經(jīng)歷,從事過多個不同SOA相關(guān)框架和容器的開發(fā)。他的郵箱:shenli@dangdang.com


    感謝馬國耀對本文的審校。

    給InfoQ中文站投稿或者參與內(nèi)容翻譯工作,請郵件至editors@cn.infoq.com。也歡迎大家通過新浪微博(@InfoQ)或者騰訊微博(@InfoQ)關(guān)注我們,并與我們的編輯和其他讀者朋友交流。

    posted @ 2014-10-16 14:06 小馬歌 閱讀(235) | 評論 (0)編輯 收藏
     
    from:http://www.infoq.com/cn/articles/micro-soa-1

    大量互聯(lián)網(wǎng)公司都在擁抱SOA和服務(wù)化,但業(yè)界對SOA的很多討論都比較偏向高大上。本文試圖從稍微不同的角度,以相對接地氣的方式來討論SOA,集中討論SOA在微觀實踐層面中的緣起、本質(zhì)和具體操作方式,另外也用相當(dāng)篇幅介紹了當(dāng)今互聯(lián)網(wǎng)行業(yè)中各種流行的遠(yuǎn)程調(diào)用技術(shù)等等,比較適合從事實際工作的架構(gòu)師和程序員來閱讀。

    為了方便閱讀,本話題將分為兩篇展現(xiàn)。本文是上篇,著眼于微觀SOA的定義,并簡單分析其核心原則。

    亞馬遜CEO杰夫•貝佐斯:鮮為人知的SOA大師

    由于SOA有相當(dāng)?shù)碾y度和門檻,不妨先從一個小故事說起,從中可以管窺一點SOA的大意和作用。

    按照亞馬遜前著名員工Steve Yegge著名的“酒后吐槽”,2002年左右,CEO貝佐斯就在亞馬遜強(qiáng)制推行了以下六個原則(摘自酷殼):

    1. 所有團(tuán)隊的程序模塊都要以通過Service Interface 方式將其數(shù)據(jù)與功能開放出來。
    2. 團(tuán)隊間的程序模塊的信息通信,都要通過這些接口。
    3. 除此之外沒有其它的通信方式。其他形式一概不允許:不能使用直接鏈結(jié)程序、不能直接讀取其他團(tuán)隊的數(shù)據(jù)庫、不能使用共享內(nèi)存模式、不能使用別人模塊的后門、等等,等等,唯一允許的通信方式只能是能過調(diào)用 Service Interface。
    4. 任何技術(shù)都可以使用。比如:HTTP、Corba、Pubsub、自定義的網(wǎng)絡(luò)協(xié)議、等等,都可以,貝佐斯不管這些。
    5. 所有的Service Interface,毫無例外,都必須從骨子里到表面上設(shè)計成能對外界開放的。也就是說,團(tuán)隊必須做好規(guī)劃與設(shè)計,以便未來把接口開放給全世界的程序員,沒有任何例外
    6. 不這樣的做的人會被炒魷魚

    據(jù)說,亞馬遜網(wǎng)站展示一個產(chǎn)品明細(xì)的頁面,可能要調(diào)用200-300個Service,以便生成高度個性化的內(nèi)容。

    Steve還提到:

    Amazon已經(jīng)把文化轉(zhuǎn)變成了“一切以Service第一”為系統(tǒng)架構(gòu)的公司,今天,這已經(jīng)成為他們進(jìn)行所有設(shè)計時的基礎(chǔ),包括那些絕不會被外界所知的僅在內(nèi)部使用的功能。

    那時,如果沒有被解雇的的恐懼他們一定不會去做。我是說,他們今天仍然怕被解雇,因為這基本上是那兒每天的生活,為那恐怖的海盜頭子貝佐斯工作。不過,他們這么做的確是因為他們已經(jīng)相信Service這就是正確的方向。他們對于SOA的優(yōu)點和缺點沒有疑問,某些缺點還很大,也不疑問。但總的來說,這是正確的,因為,SOA驅(qū)動出來的設(shè)計會產(chǎn)生出平臺(Platform)。

    今天,我們都知道亞馬遜從世界上最大圖書賣場進(jìn)化為了世界上最成功的云平臺……

    貝佐斯的六原則展示出高度的遠(yuǎn)見和超強(qiáng)的信念,即使放到十幾年后的今天,依然覺得振聾發(fā)聵……想起一句老話:“不謀萬世者,不足以謀一時;不謀全局者,不足以謀一隅。”

    當(dāng)然,像貝佐斯這種將神性與魔性集于一身的專橫人物,既可能創(chuàng)造劃時代的進(jìn)步,也可能制造前所未有的災(zāi)難。

    SOA漫談:宏觀與微觀

    SOA即面向服務(wù)架構(gòu),是一個特別大的話題。

    為了方便討論,我在此先草率的將SOA分為兩個層面(大概模仿宏觀和微觀經(jīng)濟(jì)學(xué),但這里的劃分沒有絕對界限):

    • 宏觀SOA:面向高層次的部門級別、公司級別甚至行業(yè)級別;涉及商業(yè)、管理、技術(shù)等方面的綜合的、全局的考慮;架構(gòu)體系上包括服務(wù)治理(governance,如服務(wù)注冊,服務(wù)監(jiān)控),服務(wù)編排(orchestration,如BPM,ESB),服務(wù)協(xié)同(choreography,更多面向跨企業(yè)集成)等等。我認(rèn)為SOA本身最主要是面向宏觀層面的架構(gòu),其帶來益處也最能在宏觀高層次上體現(xiàn)出來,同時大部分SOA的業(yè)界討論也集中在這方面。
    • 微觀SOA:面向有限的、局部的團(tuán)隊和個人;涉及獨立的、具體的服務(wù)在業(yè)務(wù)、架構(gòu)、開發(fā)上的考慮。

    很多業(yè)界專家都認(rèn)為SOA概念過于抽象,不接地氣,我認(rèn)為主要是宏觀SOA涉及面太廣,經(jīng)常需要做通盤考慮,而其中很多方面距離一般人又比較遠(yuǎn)。而在微觀層面的SOA更容易達(dá)到濤哥過去提出的“三貼近”:貼近實際、貼近生活、貼近群眾。

    同時,宏觀SOA要取得成功,通常的前提也是SOA在微觀層面的落地與落實,正如宏觀經(jīng)濟(jì)學(xué)一般要有堅實的微觀基礎(chǔ)(比如大名鼎鼎的凱恩斯主義曾廣受詬病的一點就是缺乏微觀基礎(chǔ))

    因此,我們著眼于SOA落地的目的,著重來分析微觀SOA,也算是對業(yè)界主流探討的一個小小的補(bǔ)充。

    SOA定義

    按照英文維基百科定義:SOA是一種“軟件”和“軟件架構(gòu)”的設(shè)計模式(或者叫設(shè)計原則)。它是基于相互獨立的軟件片段要將自身的功能通過“服務(wù)”提供給其他應(yīng)用。

    什么是“服務(wù)”?按照OASIS的定義:Service是一種按照既定“接口“來訪問一個或多個軟件功能的機(jī)制(另外這種訪問要符合“服務(wù)描述”中策略和限制)

    Service示例(代碼通常以java示例)

    public interface Echo {     String echo(String text); }  public class EchoImpl implements Echo {     public String echo(String text) {         return text;     } }

    可能每個開發(fā)人員每天都在寫類似的面向?qū)ο蟮腟ervice,難道這就是在實施SOA嗎?

    SOA設(shè)計原則

    既然SOA是設(shè)計原則(模式),那么它包含哪些內(nèi)容呢?事實上,這方面并沒有最標(biāo)準(zhǔn)的答案,多數(shù)是遵從著名SOA專家Thomas Erl的歸納:

    標(biāo)準(zhǔn)化的服務(wù)契約 Standardized service contract 服務(wù)的松耦合 Service loose coupling 服務(wù)的抽象 Service abstraction 服務(wù)的可重用性 Service reusability 服務(wù)的自治性 Service autonomy 服務(wù)的無狀態(tài)性 Service statelessness 服務(wù)的可發(fā)現(xiàn)性 Service discoverability 服務(wù)的可組合性 Service composability ....

    這些原則總的來說要達(dá)到的目的是:提高軟件的重用性,減少開發(fā)和維護(hù)的成本,最終增加一個公司業(yè)務(wù)的敏捷度。

    但是,業(yè)界著名專家如Don Box,David Orchard等人對SOA又有各自不同的總結(jié)和側(cè)重。

    SOA不但沒有絕對統(tǒng)一的原則,而且很多原則本身的內(nèi)容也具備相當(dāng)模糊性和寬泛性:例如,所謂松耦合原則需要松散到什么程度才算是符合標(biāo)準(zhǔn)的呢?這就好比一個人要帥到什么程度才算是帥哥呢?一棟樓要高到多少米才算是高樓呢?可能不同人心中都有自己的一桿秤……部分由于這些理論上的不確定因素,不同的人理解或者實施的SOA事實上也可能有比較大的差別。

    淺析松耦合原則

    SOA原則比較多,真正的理解往往需要逐步的積累和體會,所以在此不詳細(xì)展開。這里僅以服務(wù)的松耦合為例,從不同維度來簡單剖析一下這個原則,以說明SOA原則內(nèi)涵的豐富性:

    • 實現(xiàn)的松耦合:這是最基本的松耦合,即服務(wù)消費端不需要依賴服務(wù)契約的某個特定實現(xiàn),這樣服務(wù)提供端的內(nèi)部變更就不會影響到消費端,而且消費端未來還可以自由切換到該契約的其他提供方。

    • 時間的松耦合:典型就是異步消息隊列系統(tǒng),由于有中介者(broker),所以生產(chǎn)者和消費者不必在同一時間都保持可用性以及相同的吞吐量,而且生產(chǎn)者也不需要馬上等到回復(fù)。

    • 位置的松耦合:典型就是服務(wù)注冊中心和企業(yè)服務(wù)總線(ESB),消費端完全不需要直接知道提供端的具體位置,而都通過注冊中心來查找或者服務(wù)總線來路由。

    • 版本的松耦合:消費端不需要依賴服務(wù)契約的某個特定版本來工作,這就要求服務(wù)的契約在升級時要盡可能的提供向下兼容性。

    SOA與傳統(tǒng)軟件設(shè)計

    我們可以認(rèn)為:SOA ≈ 模塊化開發(fā) + 分布式計算

    將兩者傳統(tǒng)上的最佳實踐結(jié)合在一起,基本上可以推導(dǎo)出SOA的多數(shù)設(shè)計原則。SOA從軟件設(shè)計(暫不考慮業(yè)務(wù)架構(gòu)之類)上來講,自身的新東西其實不算很多。

    SOA原則的應(yīng)用

    基于SOA的原則,也許我們很難說什么應(yīng)用是絕對符合SOA的,但是卻能剔除明顯不符合SOA的應(yīng)用。

    用上述標(biāo)準(zhǔn)化契約,松耦合和可重用這幾個原則來嘗試分析一下上面Echo示例:

    • Echo的服務(wù)契約是用Java接口定義,而不是一種與平臺和語言無關(guān)的標(biāo)準(zhǔn)化協(xié)議,如WSDL,CORBA IDL。當(dāng)然可以抬杠,Java也是行業(yè)標(biāo)準(zhǔn),甚至全國牙防組一致認(rèn)定的東西也是行業(yè)標(biāo)準(zhǔn)。

    • Java接口大大加重了與Service客戶端的耦合度,即要求客戶端必須也是Java,或者JVM上的動態(tài)語言(如Groovy、Jython)等等……

    • 同時,Echo是一個Java的本地接口,就要求調(diào)用者最好在同一個JVM進(jìn)程之內(nèi)……

    • Echo的業(yè)務(wù)邏輯雖然簡單獨立,但以上技術(shù)方面的局限就導(dǎo)致它無法以后在其他場合被輕易重用,比如分布式環(huán)境,異構(gòu)平臺等等。

    因此,我們可以認(rèn)為Echo并不太符合SOA的基本設(shè)計原則。

    透明化的轉(zhuǎn)向SOA?

    修改一下上面的Echo,添加Java EE的@WebServices注解(annotation)

    @WebServices public class EchoImpl implements Echo {     public String echo(String text) {         return text;     } }

    現(xiàn)在將Echo發(fā)布為Java WebServices,并由底層框架自動生成WSDL來作為標(biāo)準(zhǔn)化的服務(wù)契約,這樣就能與遠(yuǎn)程的各種語言和平臺互操作了,較好的解決了上面提到的松耦合和可重用的問題。按照一般的理解,Echo似乎就成為比較理想的SOA service了。

    但是……即使這個極端簡化的例子,也會引出不少很關(guān)鍵的問題,它們決定SOA設(shè)計開發(fā)的某些難度:

    • 將一個普通的Java對象通過添加注解“透明的”變成WebServices就完成了從面向?qū)ο蟮矫嫦蚍?wù)的跨越?
    • 通過Java接口生成WSDL服務(wù)契約是好的方式嗎?
    • WebServices是最合適遠(yuǎn)程訪問技術(shù)嗎?

    面向?qū)ο蠛兔嫦蚍?wù)的對比

    面向?qū)ο螅∣O)和面向服務(wù)(SO)在基礎(chǔ)理念上有大量共通之處,比如都盡可能追求抽象、封裝和低耦合。

    但SO相對于OO,又有非常不同的典型應(yīng)用場景,比如:

    • 多數(shù)OO接口(interface)都只被有限的人使用(比如團(tuán)隊和部門內(nèi)),而SO接口(或者叫契約)一般來說都不應(yīng)該對使用者的范圍作出太多的限定和假設(shè)(可以是不同部門,不同企業(yè),不同國家)。還記得貝佐斯原則嗎?“團(tuán)隊必須做好規(guī)劃與設(shè)計,以便未來把接口開放給全世界的程序員,沒有任何例外”。

    • 多數(shù)OO接口都只在進(jìn)程內(nèi)被訪問,而SO接口通常都是被遠(yuǎn)程調(diào)用。

    簡單講,就是SO接口使用范圍比一般OO接口可能廣泛得多。我們用網(wǎng)站打個比方:一個大型網(wǎng)站的web界面就是它整個系統(tǒng)入口點和邊界,可能要面對全世界的訪問者(所以經(jīng)常會做國際化之類的工作),而系統(tǒng)內(nèi)部傳統(tǒng)的OO接口和程序則被隱藏在web界面之后,只被內(nèi)部較小范圍使用。而理想的SO接口和web界面一樣,也是變成系統(tǒng)入口和邊界,可能要對全世界開發(fā)者開放,因此SO在設(shè)計開發(fā)之中與OO相比其實會有很多不同。

    小結(jié)

    在前述比較抽象的SOA大原則的基礎(chǔ)上,我們可嘗試推導(dǎo)一些較細(xì)化和可操作的原則,在具體實踐中體現(xiàn)SO的獨特之處。請關(guān)注本系列文章的下篇!

    作者簡介

    沈理,當(dāng)當(dāng)網(wǎng)架構(gòu)師和技術(shù)委員會成員,主要負(fù)責(zé)當(dāng)當(dāng)網(wǎng)的SOA實施(即服務(wù)化)以及分布式服務(wù)框架的開發(fā)。以前也有在BEA、Oracle、Redhat等外企的長期工作經(jīng)歷,從事過多個不同SOA相關(guān)框架和容器的開發(fā)。他的郵箱:shenli@dangdang.com


    感謝馬國耀對本文的審校。

    posted @ 2014-10-16 14:05 小馬歌 閱讀(198) | 評論 (0)編輯 收藏
     

    在《直接拿來用!最火的Android開源項目(一)》中,我們詳細(xì)地介紹了GitHub上最受歡迎的TOP20 Android開源項目,引起了許多讀者的熱議,作為開發(fā)者,你最常用的是哪些開源項目?使用起來是否能讓你得心應(yīng)手?今天,我們將介紹另外20個Android開源項目,在這些項目中,你又用到了哪些呢?

    21. drag-sort-listview

    DragSortListView(DSLV)是Android ListView的一個擴(kuò)展,支持拖拽排序和左右滑動刪除功能。重寫了TouchInterceptor(TI)類來提供更加優(yōu)美的拖拽動畫效果。

     

    DSLV主要特性:

     

    • 完美的拖拽支持;
    • 在拖動時提供更平滑的滾動列表滾動;
    • 支持每個ListItem高度的多樣性
    • 公開startDrag()和stopDrag()方法;
    • 有公開的接口可以自定義拖動的View。

     

    DragSortListView適用于帶有任何優(yōu)先級的列表:收藏夾、播放列表及清單等,算得上是目前Android開源實現(xiàn)拖動排序操作最完美的方案。

    22. c-geo-opensource

    c:geo是Android設(shè)備上一個簡單而又強(qiáng)大的非官方地理尋寶客戶端。與其他類似應(yīng)用不同的是,c:geo不需要Web瀏覽器,也不需要文件輸出。你可以在毫無準(zhǔn)備的情況下,毫無后顧之憂地帶上你的智能手機(jī)去進(jìn)行地理尋寶。當(dāng)然,你也不需要付錢,因為它是免費的。

    c-geo-opensource包含了c:geo所有開源代碼。

    詳情請參考:c:geo

    23. NineOldAndroids

    自Android 3.0以上的版本,SDK新增了一個android.animation包,里面的類都是跟動畫效果實現(xiàn)相關(guān)的,通過Honeycomb API,能夠?qū)崿F(xiàn)非常復(fù)雜的動畫效果。但如果開發(fā)者想在3.0以下的版本中也能使用到這套API,那么Nine Old Androids就會是你最好的選擇,該API和Honeycomb API完全一樣,只是改變了你使用com.nineoldandroids.XXX的入口。

    該項目包含兩個工程,一個是Library,即為動畫效果的實現(xiàn)庫,另一個則是Sample,是對如何使用該API的演示。開發(fā)者可以直接登陸Google Play下載安裝Nine Old Androids Sample,查看演示。

    詳情請參考:Nine Old Androids

    24. ppsspp

    PPSSPP是由GC/Wii模擬器Dolphin聯(lián)合創(chuàng)始人之一Henrik Rydgård開發(fā)的一款免費的跨平臺開源模擬器,支持Windows、Linux、Mac、Android、iOS、BlackBerry 10等主流計算機(jī)與移動操作系統(tǒng),可直接工作在x86、x64、ARM等CPU平臺上,以GNU GPLv2許可協(xié)議發(fā)布,主要使用C++編寫以提高效率和可移植性。

    只要支持OpenGL ES 2.0,PPSSPP就可以在相當(dāng)?shù)鸵?guī)格的硬件設(shè)備上運行,包括基于ARM的手機(jī)及平板電腦。

    詳情請參考:PPSSPP

    25. androidquery

    Android-Query(AQuery)是一個輕量級的開發(fā)包,用于實現(xiàn)Android上的異步任務(wù)和操作UI元素,可讓Android應(yīng)用開發(fā)更簡單、更容易,也更有趣。

    26. droid-fu

    Droid-Fu是一個開源的通用Android應(yīng)用庫,其主要目的是為了讓Android開發(fā)更容易,包含有許多工具類,還有非常易用的Android組件。

    Droid-Fu提供支持的領(lǐng)域包括:

     

    • Android應(yīng)用的生命周期幫助
    • 支持處理Intents和diagnostics類
    • 后臺任務(wù)支持
    • HTTP消息處理
    • 對象、HTTP響應(yīng)及遠(yuǎn)程圖像高速緩存
    • 定制各種Adapter及View

     

    Droid-Fu最大的優(yōu)勢在于它的應(yīng)用生命周期幫助類,如果你正在開發(fā)一款A(yù)ndroid應(yīng)用,而它的主要任務(wù)是運行后臺任務(wù),比如從Web上抓取數(shù)據(jù),那么,你一定會使用到Droid-Fu,不過,目前該項目在GitHub上已經(jīng)停止更新維護(hù)。

    詳情請參考:droid-fu

    27. TextSecure

    TextSecure是Whisper Systems團(tuán)隊開發(fā)的一個Android上的加密信息客戶端,旨在增強(qiáng)用戶和企業(yè)通信的安全性,其源代碼于2011年被Twitter發(fā)布在GitHub開源數(shù)據(jù)庫中。

    該軟件允許用戶將在Android設(shè)備上所有發(fā)送和接收的短信內(nèi)容進(jìn)行加密,還可以將加密信息發(fā)送給另一個TextSecure用戶。

    28. XobotOS

    XobotOS是Xamarin的一個研究項目,用于將Android 4.0從Java/Dalvik移植到C#,并對移植后的性能及內(nèi)存占用情況進(jìn)行檢測。

    29. ignition

    在編寫Android應(yīng)用時,通過提供即用組件和包含許多樣板文件的實用類,ignition可以讓你的Android應(yīng)用快速起步。ignition涵蓋的區(qū)域包括:

     

    • Widget、Adapter、Dialog等UI組件;
    • 允許編寫簡單卻強(qiáng)大的網(wǎng)絡(luò)代碼的HTTP Wrapper庫;
    • 加載遠(yuǎn)程Web圖像并進(jìn)行緩存的類;
    • 簡單但有效的緩存框架(將對所有對象樹做出響應(yīng)的HTTP緩存到內(nèi)存或硬盤中);
    • Intents、diagnostics等幾個能讓API級別更容易向后兼容的幫助類;
    • 更友好、更強(qiáng)大的AsyncTask實現(xiàn)。

     

    ignition包括三個子項目:

     

    • ignition-core——是一個可以直接編譯到App中的Android庫項目。
    • ignition-support——一個標(biāo)準(zhǔn)的Java庫項目,被部署為一個普通的JAR,包含了大部分實用工具類。開發(fā)者可以獨立使用該工程的核心模塊。
    • ignition-location——一個可以直接編譯到應(yīng)用程序中的Android AspectJ庫項目。能夠讓定位應(yīng)用在不需要Activity位置更新處理的情況下獲取到最新的位置信息。

     

    詳情請參考:ignition Sample applications

    30. android_page_curl

    android_page_curl是一個在Android上使用OpenGL ES實現(xiàn)類似書本翻頁效果的示例程序。(點擊鏈接查看視頻演示

    31. asmack

    說到aSmack,自然要先提提Smack。Smack API是一個完整的實現(xiàn)了XMPP協(xié)議的開源API庫,而aSmack則是Smack在Android上的構(gòu)建版本,于2013年2月初遷移到GitHub上,該資源庫并不包含太多的代碼,只是一個構(gòu)建環(huán)境。開發(fā)者可以利用該API進(jìn)行基于XMPP協(xié)議的即時消息應(yīng)用程序開發(fā)。

    詳情請參考:asmack

    32. AndroidBillingLibrary

    In-app Billing是一項Google Play服務(wù),能夠讓你在應(yīng)用內(nèi)進(jìn)行數(shù)字內(nèi)容銷售,可銷售的數(shù)字內(nèi)容范圍非常廣,包括媒體文件、照片等下載內(nèi)容,還包括游戲級別、藥劑、增值服務(wù)和功能等虛擬內(nèi)容。Android Billing Library可以實現(xiàn)In-app Billing的所有規(guī)范,并提供更高級的類來進(jìn)行使用。

    Google于2012年底正式發(fā)布了v3版Android In-app Billing,但截至目前,GitHub上的Android Billing Library還只能支持到v2版,據(jù)悉Google將于2013年初對它進(jìn)行更新。

    詳情請參考:Google Play In-app Billing

    33. Crouton

    Crouton是Android上的一個可以讓開發(fā)者對環(huán)境中的Toast進(jìn)行替換的類,以一個應(yīng)用程序窗口的方式顯示,而其顯示位置則由開發(fā)者自己決定。

    開發(fā)者可以直接登陸Google Play下載安裝Crouton Demo,查看應(yīng)用演示。

    34. cwac-endless

    CommonsWare Android Components(CWAC)是一個開源的Android組件庫,用來解決Android開發(fā)中各個方面的常見問題,每個 CWAC組件打包成一個獨立的jar文件,其中就包含cwac-endless。

    cwac-endless提供一個EndlessAdapter,這是一個自動分頁的List,當(dāng)用戶瀏覽到List最后一行時自動請求新的數(shù)據(jù)。

    詳情請參考:Commons Ware

    35. DiskLruCache

    在Android應(yīng)用開發(fā)中,為了提高UI的流暢性、響應(yīng)速度,提供更高的用戶體驗,開發(fā)者常常會絞盡腦汁地思考如何實現(xiàn)高效加載圖片,而DiskLruCache實現(xiàn)正是開發(fā)者常用的圖片緩存技術(shù)之一。Disk LRU Cache,顧名思義,硬件緩存,就是一個在文件系統(tǒng)中使用有限空間進(jìn)行高速緩存。每個緩存項都有一個字符串鍵和一個固定大小的值。

    點擊鏈接下載該庫項目。

    36. Android-SlideExpandableListView

    如果你對Android提供的Android ExpandableListView并不滿意,一心想要實現(xiàn)諸如Spotify應(yīng)用那般的效果,那么SlideExpandableListView絕對是你最好的選擇。該庫允許你自定義每個列表項目中的ListView,一旦用戶點擊某個按鈕,即可實現(xiàn)該列表項目區(qū)域滑動。

    37. gauges-android

    Gaug.es for Android是由gaug.es推出的一款在Android設(shè)備上對網(wǎng)站流量數(shù)據(jù)進(jìn)行實時統(tǒng)計的應(yīng)用。gauges-android包含了該應(yīng)用的源代碼,開發(fā)者可以直接登陸Google Play下載安裝該應(yīng)用。

    38. acra

    ACRA是一個能夠讓Android應(yīng)用自動將崩潰報告以谷歌文檔電子表的形式進(jìn)行發(fā)送的庫,旨在當(dāng)應(yīng)用發(fā)生崩潰或出現(xiàn)錯誤行為時,開發(fā)者可以獲取到相關(guān)數(shù)據(jù)。

    39. roboguice

    RoboGuice是Android平臺上基于Google Guice開發(fā)的一個庫,可以大大簡化Android應(yīng)用開發(fā)的代碼及一些繁瑣重復(fù)的代碼。給Android帶來了簡單、易用的依賴注入,如果你使用過Spring或Guice的話,你就會知道這種編程方式是多么的便捷。

    40. otto

    Otto是由Square發(fā)布的一個著重于Android支持的基于Guava的強(qiáng)大的事件總線,在對應(yīng)用程序不同部分進(jìn)行解耦之后,仍然允許它們進(jìn)行有效的溝通。

    詳情請參考:Otto

     

    轉(zhuǎn)自:http://www.csdn.net/article/2013-05-06/2815145-Android-open-source-projects-two

    分類: android
    posted @ 2014-09-26 17:15 小馬歌 閱讀(245) | 評論 (0)編輯 收藏
     
         摘要: GitHub在中國的火爆程度無需多言,越來越多的開源項目遷移到GitHub平臺上。更何況,基于不要重復(fù)造輪子的原則,了解當(dāng)下比較流行的Android與iOS開源項目很是必要。利用這些項目,有時能夠讓你達(dá)到事半功倍的效果。為此,CSDN特整理了在GitHub平臺上最受歡迎的Android及iOS開源項目,以饗開發(fā)者。下面,就讓我們一起來看看,在GitHub平臺上,究竟有哪些Android開源項目最火...  閱讀全文
    posted @ 2014-09-26 17:14 小馬歌 閱讀(216) | 評論 (0)編輯 收藏
     
    mysql高可用方案MHA介紹
     
    概述
     
    MHA是一位日本MySQL大牛用Perl寫的一套MySQL故障切換方案,來保證數(shù)據(jù)庫系統(tǒng)的高可用.在宕機(jī)的時間內(nèi)(通常10—30秒內(nèi)),完成故障切換,部署MHA,可避免主從一致性問題,節(jié)約購買新服務(wù)器的費用,不影響服務(wù)器性能,易安裝,不改變現(xiàn)有部署。
     
       還支持在線切換,從當(dāng)前運行master切換到一個新的master上面,只需要很短的時間(0.5-2秒內(nèi)),此時僅僅阻塞寫操作,并不影響讀操作,便于主機(jī)硬件維護(hù)。
     
    在有高可用,數(shù)據(jù)一致性要求的系統(tǒng)上,MHA 提供了有用的功能,幾乎無間斷的滿足維護(hù)需要。
     
     優(yōu)點
     
    1        master自動監(jiān)控和故障轉(zhuǎn)移
     
      在當(dāng)前已存在的主從復(fù)制環(huán)境中,MHA可以監(jiān)控master主機(jī)故障,并且故障自動轉(zhuǎn)移。
     
    即使有一些slave沒有接受新的relay log events,MHA也會從最新的slave自動識別差異的relay log events,并apply差異的event到其他slaves。因此所有的slave都是一致的。MHA秒級別故障轉(zhuǎn)移(9-12秒監(jiān)測到主機(jī)故障,任選7秒鐘關(guān)閉電源主機(jī)避免腦裂,接下來apply差異relay logs,注冊到新的master,通常需要時間10-30秒即total downtime)。另外,在配置文件里可以配置一個slave優(yōu)先成為master。因為MHA修復(fù)了slave之間的一致性,dba就不用去處理一致性問題。
     
         當(dāng)遷移新的master之后,并行恢復(fù)其他slave。即使有成千上萬的slave,也不會影響恢復(fù)master時間,slave也很快完成。
     
          DeNA公司在150+主從環(huán)境中用MHA。當(dāng)其中一個master崩潰,MHA4秒完成故障轉(zhuǎn)移,這是主動/被動集群解決方案無法完成的。
     
    2        互動(手動)master故障轉(zhuǎn)移
     
     MHA可以用來只做故障轉(zhuǎn)移,而不監(jiān)測master,MHA只作為故障轉(zhuǎn)移的交互。
     
    3        非交互式故障轉(zhuǎn)移
     
     非交互式的故障轉(zhuǎn)移也提供(不監(jiān)控master,自動故障轉(zhuǎn)移)。這個特性很有用,特別是你已經(jīng)安裝了其他軟件監(jiān)控master。比如,用Pacemaker(Heartbeat)監(jiān)測master故障和vip接管,用MHA故障轉(zhuǎn)移和slave提升。
     
    4        在線切換master到不同主機(jī)
     
     在很多情況下,有必要將master轉(zhuǎn)移到其他主機(jī)上(如替換raid控制器,提升master機(jī)器硬件等等)。這并不是master崩潰,但是計劃維護(hù)必須去做。計劃維護(hù)導(dǎo)致downtime,必須盡可能快的恢復(fù)。快速的master切換和優(yōu)雅的阻塞寫操作是必需的,MHA提供了這種方式。優(yōu)雅的master切換, 0.5-2秒內(nèi)阻塞寫操作。在很多情況下0.5-2秒的downtime是可以接受的,并且即使不在計劃維護(hù)窗口。這意味著當(dāng)需要更換更快機(jī)器,升級高版本時,dba可以很容易采取動作。
     
    5        master crash不會導(dǎo)致主從數(shù)據(jù)不一致性
     
        當(dāng)master crash后,MHA自動識別slave間relay logevents的不同,然后應(yīng)用與不同的slave,最終所有slave都同步。結(jié)合通過半同步一起使用,幾乎沒有任何數(shù)據(jù)丟失。
     
    其他高可用方案
     
    6        MHA部署不影響當(dāng)前環(huán)境設(shè)置
     
    MHA最重要的一個設(shè)計理念就是盡可能使用簡單。使用與5.0+以上主從環(huán)境,其他HA方案需要改變mysql部署設(shè)置,MHA不會讓dba做這些部署配置,同步和半同步環(huán)境都可以用。啟動/停止/升級/降級/安裝/卸載 MHA都不用改變mysql主從(如啟動/停止)。
     
    當(dāng)你需要升級MHA到新版本時,不需要停止mysql,僅僅更新HMA版本,然后重新啟動MHAmanger即可。
     
       MHA 支持包含5.0/5/1/5.5(應(yīng)該也支持5.6,翻譯文檔時MHA開發(fā)者沒更新對于5.6版本)。有些HA方案要求特定的mysql版本(如mysqlcluster,mysql with global transaction id 等),而且你可能不想僅僅為了MasterHA而遷移應(yīng)用。很多情況下,公司已經(jīng)部署了許多傳統(tǒng)的mysql應(yīng)用,開發(fā)或dba不想花太多時間遷移到不同的存儲引擎或新的特性(newer bleeding edge distributions 不知道這個是否該這么翻譯)。
     
    7        不增加服務(wù)器費用
     
    MHA 包含MHA Manager和MHA node。MHA node運行在每臺mysql服務(wù)器上,Manager可以單獨部署一臺機(jī)器,監(jiān)控100+以上master,總服務(wù)器數(shù)量不會有太大增加。需要注意的是Manager也可以運行在slaves中的一臺機(jī)器上。
     
    8        性能無影響
     
    當(dāng)監(jiān)控master,MHA只是幾秒鐘(默認(rèn)3秒)發(fā)送ping包,不發(fā)送大的查詢。主從復(fù)制性能不受影響
     
    9        適用任何存儲引擎
     
    Mysql不僅僅適用于事務(wù)安全的innodb引擎,在主從中適用的引擎,MHA都可以適用。即使用遺留環(huán)境的mysiam引擎,不進(jìn)行遷移,也可以用MHA。
     
     
     
     與其他HA方案比較
     
    Doing everything manually
    Mysql replication 是同步或半同步。當(dāng)master崩潰時,很有可能一些slave還沒有接受最新的relay log events,這意味著每一個slave都相互處在不同的狀態(tài)。人為修復(fù)一致性問題顯得不再平凡。沒有一致性問題,主從也可能不會啟動(如duplicate key error)。花費1個多小時重新啟動主從復(fù)制顯得不同尋常。
     
     
     
    Single master and single slave
    在單一主從情況下,一些slave 落后與其他slave的情況將不會發(fā)生。其中一個master崩潰,可以輕松的讓應(yīng)用轉(zhuǎn)移到一個新的master上面,提供對外服務(wù),故障遷移很簡單。
     
     
     
    Master, one candidate master, and multiple slaves雙主多從
    雙主多從的架構(gòu)也很常見。主master掛掉,備用master將接替主master提供服務(wù)。某些情況配置為多主架構(gòu)。
     
     
     
    M(RW)-----M2(R)                      M(RW), promoted from M2
     
           |                                          |
     
      +----+----+          --(master crash)-->   +-x--+--x-+
     
     S(R)     S2(R)                             S(?)      S(?)
     
                                              (Fromwhich position should S restart replication?)
     
    但是這并不作為master故障轉(zhuǎn)移方案。當(dāng)前master掛掉,剩余slave不一定接受全部relay log events,修復(fù)數(shù)據(jù)一致性還是問題。
     
     
     
    這種架構(gòu)使用廣泛,但是不是所有人都能深刻理解上述問題。當(dāng)前master掛掉,slave變得不統(tǒng)一或者slave不能從新的master復(fù)制數(shù)據(jù)。
     
    也許雙master,其中一個master只讀,每個master都至少有一個slave也許可能解決問題。
     
             M(RW)--M2(R)
              |      |
            S(R)   S2(R)
     
     
    Pacemaker + DRBD
    Pecemaker(Heartbeat)+DRBD+Mysql是一個通用方案。但是這個方案也有以下問題
     
    1 費用問題,特別是跑大量主從環(huán)境。Pecemaker+DRBD是主動/被動的解決方案,因此需要一臺被動服務(wù)器對外不提供任何應(yīng)用服務(wù)。基本的需要四臺mysql服務(wù)器,one active master,one passive master,two slaves。
     
    2 宕機(jī)時間(downtime)。Pacemaker+DRBD是主備集群,主master掛掉,備用master啟用。這可能花費長的時間,特別是沒有用innodb plugin。即使用innodb plugin,花費幾分鐘開始在備用master上接受連接也不尋常。另外,因為備用master上數(shù)據(jù)/文件緩存是空的,恢復(fù)時間,熱身(填充數(shù)據(jù)到data buffer pool)花費不可忽視的時間。實踐中,需要一臺或更多slave提供足夠的讀服務(wù)。在熱身時間內(nèi),空緩存導(dǎo)致寫性能降低
     
    3 寫問題下降或一致性問題。為了讓主動/被動集群真正的工作,每次提交(commit)后,必須刷新事務(wù)日志(binary log和innodb log),也就是必須設(shè)置innodb-flush-log-at-trx-commit=1,sync-binlog=1。設(shè)置sync-binlog=1會降低寫性能,因為fsync()函數(shù)被序列化(sync-binlog=1,group commit失效)。大部分案例中,不設(shè)置sync-binlog=1.如果沒有設(shè)置sync-binlog=1,活動master crash,新的master(先前被動服務(wù)器)可能會丟失一些已經(jīng)發(fā)送到slave的binary log events。假如 master 掛掉,slave A接受到mysqld-bin.000123,位置1500。binlog data刷新到硬盤的位置在1000,那么新的master數(shù)據(jù)也只能mysqld-bin.000123的1000處,然后在啟動時創(chuàng)建一個新的binary log mysqld-bin.000124。如果發(fā)生這種情況,slave A不能繼續(xù)復(fù)制,因為新的master 沒有mysqld-bin.000123位置1500.
     
     4 復(fù)雜。對多數(shù)人來說,安裝/初始化pacemake和DRBD不是容易的事情。相對于其他案例,初始化DRBD需要重新創(chuàng)建系統(tǒng)分區(qū)也不容易。要求dba在DRBD和linux內(nèi)核層有足夠的技能。如果dba執(zhí)行了一個錯誤命令(如執(zhí)行drbdadm–overwrite-data-of-peer primary 在被動節(jié)點),那么將會損壞活動的數(shù)據(jù)。重要的是另外一旦硬盤io層出現(xiàn)問題,多數(shù)dba處理這種問題不是容易的。
     
    MySQL Cluster
    Mysql cluster是真正的高可用解決方案,但是必須得用NDB存儲引擎。如果你用innodb,將不能發(fā)揮mysql cluster集群優(yōu)勢。
     
    Semi-Synchronous Replication
    半同步復(fù)制大大降低了binlog event僅僅存在于崩潰master上的這種風(fēng)險。這非常有用的能避免數(shù)據(jù)丟失。但是半同步不能解決所有一致性問題,只能保證一個(不是所有)slave接受到master端的commit的binlog events,其他slave也許還沒有接受全部的binlog events。不能apply不同的binlog events 從新的slave到 其他slave上,也不能保證相互一致性
     
    Global Transaction ID
    GlobalTransaction ID所要達(dá)到的目的跟MHA相同,但它覆蓋更多。MHA只是兩級復(fù)制,但是global transaction id覆蓋任何級別的復(fù)制環(huán)境,即使第兩級復(fù)制失敗,dba也能覆蓋第三級。Check Google'sglobal transaction id project for details。
    posted @ 2014-08-05 13:45 小馬歌 閱讀(295) | 評論 (0)編輯 收藏
     

    第一種方法:

    RENAME database olddbname TO newdbname

    這個是5.1.7到5.1.23版本可以用的,但是官方不推薦,會有丟失數(shù)據(jù)的危險

    第二種方法:

    1.創(chuàng)建需要改成新名的數(shù)據(jù)庫。 
    2.mysqldum 導(dǎo)出要改名的數(shù)據(jù)庫 
    3.刪除原來的舊庫(確定是否真的需要) 
    當(dāng)然這種方法雖然安全,但是如果數(shù)據(jù)量大,會比較耗時,哎,當(dāng)時連這種方法都沒有想到,真有想死的沖動。

    第三種方法:

    我這里就用一個腳本,很簡單,相信大家都看的懂

    #!/bin/bash # 假設(shè)將sakila數(shù)據(jù)庫名改為new_sakila # MyISAM直接更改數(shù)據(jù)庫目錄下的文件即可  mysql -uroot -p123456 -e 'create database if not exists new_sakila' list_table=$(mysql -uroot -p123456 -Nse "select table_name from information_schema.TABLES where TABLE_SCHEMA='sakila'")  for table in $list_table do     mysql -uroot -p123456 -e "rename table sakila.$table to new_sakila.$table" done

    這里用到了rename table,改表名的命令,但是如果新表名后面加數(shù)據(jù)庫名,就會將老數(shù)據(jù)庫的表移動到新的數(shù)據(jù)庫,所以,這種方法即安全,又快速。

    posted @ 2014-07-31 10:02 小馬歌 閱讀(58274) | 評論 (1)編輯 收藏
     
    from:http://passover.blog.51cto.com/2431658/732629

    在線上環(huán)境中我們是采用了tomcat作為Web服務(wù)器,它的處理性能直接關(guān)系到用戶體驗,在平時的工作和學(xué)習(xí)中,歸納出以下七種調(diào)優(yōu)經(jīng)驗。

    1. 服務(wù)器資源

        服務(wù)器所能提供CPU、內(nèi)存、硬盤的性能對處理能力有決定性影響。
        (1) 對于高并發(fā)情況下會有大量的運算,那么CPU的速度會直接影響到處理速度。
        (2) 內(nèi)存在大量數(shù)據(jù)處理的情況下,將會有較大的內(nèi)存容量需求,可以用-Xmx -Xms -XX:MaxPermSize等參數(shù)對內(nèi)存不同功能塊進(jìn)行劃分。我們之前就遇到過內(nèi)存分配不足,導(dǎo)致虛擬機(jī)一直處于full GC,從而導(dǎo)致處理能力嚴(yán)重下降。
        (3) 硬盤主要問題就是讀寫性能,當(dāng)大量文件進(jìn)行讀寫時,磁盤極容易成為性能瓶頸。最好的辦法還是利用下面提到的緩存。

    2. 利用緩存和壓縮

        對于靜態(tài)頁面最好是能夠緩存起來,這樣就不必每次從磁盤上讀。這里我們采用了Nginx作為緩存服務(wù)器,將圖片、css、js文件都進(jìn)行了緩存,有效的減少了后端tomcat的訪問。

        另外,為了能加快網(wǎng)絡(luò)傳輸速度,開啟gzip壓縮也是必不可少的。但考慮到tomcat已經(jīng)需要處理很多東西了,所以把這個壓縮的工作就交給前端的Nginx來完成。可以參考之前寫的《利用nginx加速web訪問》。

        除了文本可以用gzip壓縮,其實很多圖片也可以用圖像處理工具預(yù)先進(jìn)行壓縮,找到一個平衡點可以讓畫質(zhì)損失很小而文件可以減小很多。曾經(jīng)我就見過一個圖片從300多kb壓縮到幾十kb,自己幾乎看不出來區(qū)別。

    3. 采用集群

        單個服務(wù)器性能總是有限的,最好的辦法自然是實現(xiàn)橫向擴(kuò)展,那么組建tomcat集群是有效提升性能的手段。我們還是采用了Nginx來作為請求分流的服務(wù)器,后端多個tomcat共享session來協(xié)同工作。可以參考之前寫的《利用nginx+tomcat+memcached組建web服務(wù)器負(fù)載均衡》。

    4. 優(yōu)化tomcat參數(shù)

        這里以tomcat7的參數(shù)配置為例,需要修改conf/server.xml文件,主要是優(yōu)化連接配置,關(guān)閉客戶端dns查詢。

    1. <Connector port="8080"   
    2.            protocol="org.apache.coyote.http11.Http11NioProtocol"  
    3.            connectionTimeout="20000"  
    4.            redirectPort="8443"   
    5.            maxThreads="500"   
    6.            minSpareThreads="20"  
    7.            acceptCount="100" 
    8.            disableUploadTimeout="true" 
    9.            enableLookups="false"   
    10.            URIEncoding="UTF-8" /> 

    5. 改用APR庫

        tomcat默認(rèn)采用的BIO模型,在幾百并發(fā)下性能會有很嚴(yán)重的下降。tomcat自帶還有NIO的模型,另外也可以調(diào)用APR的庫來實現(xiàn)操作系統(tǒng)級別控制。

        NIO模型是內(nèi)置的,調(diào)用很方便,只需要將上面配置文件中protocol修改成org.apache.coyote.http11.Http11NioProtocol,重啟即可生效。上面配置我已經(jīng)改過了,默認(rèn)的是HTTP/1.1。

        APR則需要安裝第三方庫,在高并發(fā)下會讓性能有明顯提升。具體安裝辦法可以參考http://www.cnblogs.com/huangjingzhou/articles/2097241.html。安裝完成后重啟即可生效。如使用默認(rèn)protocal就是apr,但最好把將protocol修改成org.apache.coyote.http11.Http11AprProtocol,會更加明確

        在官方找到一個表格詳細(xì)說明了這三種方式的區(qū)別:

    1.                   Java Blocking Connector   Java Nio Blocking Connector   APR/native Connector 
    2.                              BIO                         NIO                       APR 
    3. Classname                AjpProtocol               AjpNioProtocol           AjpAprProtocol 
    4. Tomcat Version           3.x onwards                 7.x onwards              5.5.x onwards 
    5. Support Polling              NO                          YES                       YES 
    6. Polling Size                 N/A                   maxConnections             maxConnections 
    7. Read Request Headers      Blocking                  Sim Blocking                   Blocking 
    8. Read Request Body         Blocking                  Sim Blocking                   Blocking 
    9. Write Response            Blocking                  Sim Blocking                   Blocking 
    10. Wait for next Request     Blocking                  Non Blocking               Non Blocking 
    11. Max Connections        maxConnections              maxConnections             maxConnections 

    6. 優(yōu)化網(wǎng)絡(luò)

        Joel也明確提出了優(yōu)化網(wǎng)卡驅(qū)動可以有效提升性能,這個對于集群環(huán)境工作的時候尤為重要。由于我們采用了linux服務(wù)器,所以優(yōu)化內(nèi)核參數(shù)也是一個非常重要的工作。給一個參考的優(yōu)化參數(shù):

    1. 1. 修改/etc/sysctl.cnf文件,在最后追加如下內(nèi)容: 
    2.  
    3. net.core.netdev_max_backlog = 32768 
    4. net.core.somaxconn = 32768 
    5. net.core.wmem_default = 8388608 
    6. net.core.rmem_default = 8388608 
    7. net.core.rmem_max = 16777216 
    8. net.core.wmem_max = 16777216 
    9. net.ipv4.ip_local_port_range = 1024 65000 
    10. net.ipv4.route.gc_timeout = 100 
    11. net.ipv4.tcp_fin_timeout = 30 
    12. net.ipv4.tcp_keepalive_time = 1200 
    13. net.ipv4.tcp_timestamps = 0 
    14. net.ipv4.tcp_synack_retries = 2 
    15. net.ipv4.tcp_syn_retries = 2 
    16. net.ipv4.tcp_tw_recycle = 1 
    17. net.ipv4.tcp_tw_reuse = 1 
    18. net.ipv4.tcp_mem = 94500000 915000000 927000000 
    19. net.ipv4.tcp_max_orphans = 3276800 
    20. net.ipv4.tcp_max_syn_backlog = 65536 
    21.  
    22. 2. 保存退出,執(zhí)行sysctl -p生效 

    7. 讓測試說話

        優(yōu)化系統(tǒng)最忌諱的就是只調(diào)優(yōu)不測試,有時不適當(dāng)?shù)膬?yōu)化反而會讓性能更低。以上所有的優(yōu)化方法都要在本地進(jìn)行性能測試過后再不斷調(diào)整參數(shù),這樣最終才能達(dá)到最佳的優(yōu)化效果。

     

    補(bǔ)充Bio、Nio、Apr模式的測試結(jié)果:

        對于這幾種模式,我用ab命令模擬1000并發(fā)測試10000詞,測試結(jié)果比較意外,為了確認(rèn)結(jié)果,我每種方式反復(fù)測試了10多次,并且在兩個服務(wù)器上都測試了一遍。結(jié)果發(fā)現(xiàn)Bio和Nio性能差別非常微弱,難怪默認(rèn)居然還是Bio。但是采用apr,連接建立的速度會有50%~100%的提升。直接調(diào)用操作系統(tǒng)層果然神速啊,這里強(qiáng)烈推薦apr方式!

     

    參考資料:
    http://16.199.geisvps.com/bbs/2836/24238.html

    posted @ 2014-07-29 10:31 小馬歌 閱讀(1739) | 評論 (0)編輯 收藏
     
         摘要: 1、MySQL錯誤日志里出現(xiàn):140331 10:08:18 [ERROR] Error reading master configuration140331 10:08:18 [ERROR] Failed to initialize the master info structure140331 10:08:18 [Note] Event Scheduler: Loaded 0 events&n...  閱讀全文
    posted @ 2014-07-25 14:56 小馬歌 閱讀(22055) | 評論 (0)編輯 收藏
     
         摘要: http://www.oschina.net/question/12_90733作為 MySQL 5.5 和 5.6 性能比較的一部分,我研究了下兩個版本默認(rèn)參數(shù)的差異,為了了解差異內(nèi)容,我使用如下的 SQL 語句分別在 MySQL 5.5 和 5.6 版本進(jìn)行查詢,得出下表(點擊圖片查看大圖):讓我們來看看這些差異的配置中最重要的也是影響最大的部分:performance_schema...  閱讀全文
    posted @ 2014-07-23 15:41 小馬歌 閱讀(233) | 評論 (0)編輯 收藏
     
         摘要: ZooKeeper是一個分布式開源框架,提供了協(xié)調(diào)分布式應(yīng)用的基本服務(wù),它向外部應(yīng)用暴露一組通用服務(wù)——分布式同步(Distributed Synchronization)、命名服務(wù)(Naming Service)、集群維護(hù)(Group Maintenance)等,簡化分布式應(yīng)用協(xié)調(diào)及其管理的難度,提供高性能的分布式服務(wù)。ZooKeeper本身可以以Standalone模式...  閱讀全文
    posted @ 2014-07-23 11:57 小馬歌 閱讀(317) | 評論 (0)編輯 收藏
    僅列出標(biāo)題
    共95頁: First 上一頁 17 18 19 20 21 22 23 24 25 下一頁 Last 
     
    主站蜘蛛池模板: 亚洲熟女乱综合一区二区| 女人18一级毛片免费观看| 最新精品亚洲成a人在线观看| 国产亚洲欧美日韩亚洲中文色| 四虎免费在线观看| 亚洲熟妇无码一区二区三区| 无码国产精品一区二区免费 | 一区二区三区在线免费| 亚洲?V无码乱码国产精品| 美女18一级毛片免费看| 亚洲精品国产精品国自产观看| av成人免费电影| 国产亚洲综合久久系列| 最近中文字幕免费2019| 亚洲人成7777影视在线观看| 18禁成年无码免费网站无遮挡| 亚洲av片在线观看| 亚洲综合色成在线播放| 一级毛片**不卡免费播| 精品亚洲国产成人| 全部免费国产潢色一级| 成人免费乱码大片A毛片| 亚洲色偷偷av男人的天堂| 韩国日本好看电影免费看| 一区二区三区免费精品视频| 亚洲福利在线视频| 成人毛片18女人毛片免费96| 女人裸身j部免费视频无遮挡| 国产成人无码综合亚洲日韩| 亚洲一区二区三区免费在线观看| 亚洲国产欧洲综合997久久| 亚洲天堂免费在线视频| 黄色永久免费网站| 一级毛片a免费播放王色| 亚洲国产美女视频| 亚洲综合区小说区激情区| 日本免费人成在线网站| 国产va免费观看| 亚洲中文字幕乱码熟女在线| 亚洲永久精品ww47| 国产精品视频永久免费播放|