在 Web 服務(wù)中至少有三個因素(或缺少這些因素)與性能有直接關(guān)系:
Web 服務(wù)給日益復(fù)雜的功能提供了一個公共接口。雖然沒有一個針對底層服務(wù)的規(guī)范,但是基本的概念是您編寫代碼位并將它們部署到網(wǎng)絡(luò)中。您可以通過多種傳輸利用這個功能,最普通的是 HTTP。Web 服務(wù)的無效率就在這里:許多傳輸不是以性能為中心的,并且 XML 的包裝和解析給予了直接過程調(diào)用無法承擔的開銷。但是,正如阿爾伯特・愛因斯坦(Albert Einstein)曾說過的,時間是相對的。
在因特網(wǎng)的世界中,多數(shù)人按照秒來思考時間。多數(shù) Web 站點都在力爭比六秒更快的響應(yīng)時間??紤]一下您可以使用 Web 服務(wù)調(diào)用來構(gòu)建一個 Web 站點(如新聞門戶網(wǎng)站),那么 Web 服務(wù)的性能甚至需要更快。這是一個挑戰(zhàn)。其目標是使半?yún)⑴c的 Web 服務(wù)的響應(yīng)時間大約為三秒。您可以通過查看您已經(jīng)控制的 Web 服務(wù)部分(具有特殊功效的代碼位)來達到這個目標。
![]() |
|
如今的 Web 高速緩存系統(tǒng)利用一些指向內(nèi)容片段的唯一的標識符。他們利用底層的協(xié)議來跟蹤數(shù)據(jù)位(如 HTML 文檔或圖像)的及時性。雖然 HTTP 傳輸上的 Web 服務(wù)有端點(URL),但是使其唯一的簡單對象訪問協(xié)議(Simple Object Access Protocol(SOAP))信封(envelope)部分是 SOAP 信封中的參數(shù)值,如 清單 1 所示。由于 SOAP 是 XML,幾個標記可能有許多不同的標簽但仍然標注同一個數(shù)據(jù)。作為一個整體,您可以創(chuàng)建一個與下一個 SOAP 信封不同的 SOAP 信封并同時使它們恰好代表同一個數(shù)據(jù)。此外,如果您決定在一個 SOAP 信封單獨的、唯一的部分的基礎(chǔ)上進行高速緩存,那么沒什么辦法來表明這個查詢是否適于這種高速緩存。
開發(fā)人員為特定類型的情況和數(shù)據(jù)調(diào)整當前的商業(yè) Web 高速緩存解決方案。而且,即使有解決方案存在,它可能也沒有將開發(fā)人員所要求的操作考慮在內(nèi)。雖然有現(xiàn)成的商業(yè)工具可以使用,但是運行您自己的高速緩存對象則提供了最好的靈活性、最強的控制和最大的購買能力。
![]() |
|
多數(shù)進程都涉及到了計算。計算可以是一個等式或者是能產(chǎn)生一個新值的網(wǎng)絡(luò)交易。不管計算是什么,您都應(yīng)該標識出浪費時間的進程部分??紤]一下報告原子時間(atomic time)的進程吧。如果這個進程需要一個到政府服務(wù)部門的簡單網(wǎng)絡(luò)時間協(xié)議(Simple Network Time Protocol(SNTP))連接,那么更加頻繁地計算比每幾秒鐘計算一次浪費時間。完成一個到原子時間服務(wù)的連接所需的時間會影響時間讀取的精確性。對于這個示例來說,假設(shè)您僅保持十秒的精度。獲得當前時間的網(wǎng)絡(luò)調(diào)用是高速緩存的一個完美項,因為您的 10 秒約束意味著數(shù)據(jù)在至多 10 秒鐘之內(nèi)不會更改。您僅僅需要大約每 8 秒進行一次新的連接,以嘗試對網(wǎng)絡(luò)等待時間進行補償。
這種樣式的高速緩存是簡單的。涉及到兩個靜態(tài)變量:您上次檢查時間的時間以及時間本身。您上一次檢查的時間作為觸發(fā)刷新來自時間服務(wù)器(timeserver)的時間的變量。這個時間需要在存儲時間過期的任何時刻時被刷新。這是在上一次檢查的時間戳記基礎(chǔ)上被檢查的。顯然,如果客戶機對時間的請求在所存儲的時間過期前進入,您會返回到已被高速緩存的時間。
您還可以為文本轉(zhuǎn)化為語言(text-to-speech)服務(wù)生成并高速緩存音頻文件。生成大量數(shù)據(jù)以代表一個音頻文件需要耗費許多資源。這個服務(wù)接收字符串并將音頻文件作為一個附件返回。您可以存儲這個動態(tài)生成的音頻并將文本表示存儲為密鑰。
這夠簡單的了,但是請考慮一下:您將這些已高速緩存的項保存多久以及其他客戶機將多久調(diào)用一次這個 Web 服務(wù)?
第一個問題訴諸了這樣一個事實:每一個系統(tǒng)的資源都是有限的。將 100 MB 的音頻數(shù)據(jù)存儲在內(nèi)存中可能使存儲量過大。您可以設(shè)計一個高速緩存來擁有一個最大的存儲量。它可以將用得最多的條目保存,同時又將最陳舊的和最少用到的條目清除。您可以決定這個高速緩存沒有時間限制。
第二個問題突出顯示了服務(wù)可能被其他客戶機很少使用,以至于對任何事物進行高速緩存都沒有用處。例如,假設(shè)一個想像的 Web 服務(wù)的總交易時間為兩秒。如果對這個 Web 服務(wù)的調(diào)用不多(每分鐘少于一個),那么可以確定沒有必要進行高速緩存。然而,如果負載是每秒 100 個調(diào)用,那么可能有正當?shù)睦碛蛇M行高速緩存。一個變通方法是使用一個能在需要時存儲條目而在過了有效期后清除條目的自清除高速緩存(self-pruning cache)。清除高速緩存對象減少了它的內(nèi)存量。高速緩存能夠依靠實現(xiàn)將常常被高速緩存的對象保存,時間長于不常使用的被高速緩存的對象。
高速緩存的設(shè)計常常以其將得到使用的環(huán)境為基礎(chǔ)。本文既包括了簡單的示例,也包括了復(fù)雜的示例。本文還考慮到了以下內(nèi)容:
![]() |
|
高速緩存在任意應(yīng)用程序中都會是一個有用的工具。在 Web 服務(wù)中,您可以更加頻繁地使用高速緩存,因為應(yīng)用程序的本質(zhì)在許多情況下是重復(fù)的和高負荷的查詢。有時您在代碼中插入一個高速緩存解決方案是合適的。在其他情況下,當您可以將一個 Web 服務(wù)調(diào)用的全部結(jié)果高速緩存時,在該 Web 服務(wù)被調(diào)用之前就插入高速緩存檢查會比較好。為了演示這后一種方法,假設(shè)您正在使用 Apache 的 Axis 中的 Java(TM) 開發(fā)環(huán)境和 Web 應(yīng)用程序服務(wù)器(如 IBM WebSphere)。(請注意您在這種類型的環(huán)境中需要做的每一樣工作都在用于 Web 服務(wù)的 IBM WebSphere SDK 中有所提供。)這個練習的目標是將高速緩存與實際的 Web 服務(wù)代碼分離開來。
Apache 的第一個 SOAP 實現(xiàn)取決于提供程序的概念。這個代碼位將 SOAP 信封的對象和方法進行解碼,實例化本地對象,并返回將會在返回 SOAP 信封中被包裝起來的結(jié)果。Axis 有一個與提供程序功能相當?shù)牟糠?,不過它通常被稱為軸心點(pivot point)。這是因為 Axis 提供了您可以用來定義交易流的體系結(jié)構(gòu)。您通過處理程序定義流。每一個處理程序都可以對當前傳入的和傳出的 SOAP 信封進行操作。處理程序提供了將方法和服務(wù)作為一個大一些的服務(wù)的流的一部分執(zhí)行的能力,如 圖 1 所示。軸心點恰恰是另一個處理程序,但是它暗示了請求成為響應(yīng)的點。這個軸心點是一個您可以插入高速緩存的地方。
本示例應(yīng)用程序的高速緩存是一個通用的解決方案。您將把對象設(shè)計為一個單子實例(singleton)(這個設(shè)計模式將把這個對象限制在一個單個實例中)并使用合適的檢索和存儲方法對高速緩存進行操作。高速緩存將這些對象存儲一個固定時間并將旋轉(zhuǎn)一個線程來在需要時清除這些項,如 圖 2 所示。對于什么可以被高速緩存這個問題只有一個限制 ― 這個項必須是一個對象。
因為許多 Apache 項目具有開放源代碼性質(zhì),因此您可以為 Axis SOAP 實現(xiàn)下載源代碼。(在撰寫本文時它仍是測試版,但是它最終會是一個受歡迎的針對 Java Web 服務(wù)工作的解決方案。)您將修改 RPCProvider 類(org.apache.axis.providers.java.RPCProvider.java)。許多提供程序都支持多種傳輸。雖然您可以編寫自己的類,但是您可以采用簡單的途徑,利用 Axis 開發(fā)人員已經(jīng)做的所有艱辛勞動。您完全可以拷貝由 Apache 員工開發(fā)的 RPCProvider 并添加一些代碼來以一個 RPCCachingProvider 結(jié)束。為了高速緩存一個來自 Web 服務(wù)的響應(yīng),您需要生成一個用來對它進行索引的唯一的密鑰。在將被調(diào)用的對象和 SOAP 信封中的變元的基礎(chǔ)上(如 清單 1 所示),您可以生成這樣一個密鑰。具體說來,您需要確定服務(wù)、方法和變元。
|
請注意這個高速緩存提供程序假定變元有唯一的字符串表示,但不是每一個調(diào)用都有唯一的字符串表示。例如,當一個字節(jié)數(shù)組作為字符串被檢索時,它將看起來有些像 [B@4f25045a。每一個字節(jié)數(shù)組看起來都是不同的,高速緩存將假定每一個數(shù)組都是唯一的,這導(dǎo)致了高速緩存沒有有效工作。雖然有許多解決這個問題的方法,但是本文使密鑰生成簡單。一旦您有了一個唯一的密鑰,請檢查一下看看在高速緩存中是否有這個項。如果有這個項,那么就返回已存儲的響應(yīng)。在這種情況下,您可以在高速緩存一個 Web 服務(wù)調(diào)用產(chǎn)生的響應(yīng)的地方高速緩存 SOAP 體,如 清單 2中的 soapenv:Body 標記描述的那樣。您可以決定更新高速緩存項的時間來使其時間更久些。但是,如果高速緩存沒有一個匹配的項,您應(yīng)當繼續(xù)執(zhí)行這個調(diào)用并存儲所產(chǎn)生的響應(yīng)片段。您可以指定所高速緩存的項目每次保留 30 秒,并在每次被請求時刷新,如 清單 3所示。
|
|
在軸心點實現(xiàn)高速緩存系統(tǒng)將其與服務(wù)代碼分離開來。奇妙之處在于服務(wù)的部署。不要標識缺省的提供程序(java:RPC),而是將軸心點指定為處理程序并向指向您的新的高速緩存提供程序的服務(wù)添加一個參數(shù),如 清單 4 所示。這個體系結(jié)構(gòu)讓您在部署時決定是否使用高速緩存。您甚至還可以用一個服務(wù)參數(shù)為高速緩存項具體化生存時間。Axis 提供了所有的這個功能和靈活性。您可以在舊的 Apache SOAP 實現(xiàn)中完成同一個提供程序概念,但是為了訪問方法和參數(shù)值,您要多做一點兒工作。
|
![]() |
|
既然您已經(jīng)探索了高速緩存系統(tǒng)并且創(chuàng)建了一個通用的高速緩存對象,您可以學習如何在其他的 Web 服務(wù)解決方案中集成高速緩存了。雖然您是在流方案中實現(xiàn)這個通用的高速緩存對象,但是您也可以在其他場合使用它。如果不將代碼用于工作中,那么即使有它們也沒用。
![]() |
|
這第一個示例研究了在訪問 Web 服務(wù)之前需要進行認證以幫助限制訪問和跟蹤使用情況的需求。有時您需要檢查一個用戶連接到公司 LDAP 目錄或數(shù)據(jù)庫的認證憑證,對此進行高速緩存的操作就是這樣的事務(wù)。
這個示例使用了一個固定大小的高速緩存,如 1 MB 的存儲器或 100 個高速緩存項。它使用用戶標識作為密鑰,其值為作為 MD5 散列存儲的密碼。這確保了安全并同時仍能可以根據(jù)所高速緩存項而驗證未來的密碼。如果認證失敗,您可以除去這個標識。最后,為了安全起見,請考慮一下將高速緩存超時,因為密碼更改和標識會被取消。
第一次您檢查用戶的憑證時,在成功登錄時請將它們存儲在高速緩存中。如果憑證經(jīng)證明是無效的,那么便會返回錯誤。對這個服務(wù)的后繼調(diào)用可以獲得密碼認證的安全性,而實際上不一定會導(dǎo)致數(shù)據(jù)庫連接或公司 LDAP 目錄查找的開銷。雖然這看起來可能并沒有節(jié)省多少開銷,但如果時間很長而且負載很大時,這樣就能夠節(jié)省不少的開銷。
![]() |
|
有時,您可能發(fā)現(xiàn)您的 Web 服務(wù)是個精巧的系統(tǒng)中的一部分。在這第二個示例中,系統(tǒng)需要一臺客戶機來首先獲得一個已被認證的令牌并將這個令牌給后繼服務(wù)。為了進一步加強系統(tǒng)的安全,令牌只能被使用一次。使 Web 服務(wù)能夠處理哪些令牌先前已經(jīng)使用過就可以實施這個只用一次模型(use once model)。它使令牌避免了惡意提交以在一個資源被使用一次后獲得對它的訪問。這個方案利用了一些在 Axis 安全性演示和 IBM Web Services ToolKit 早期版本中的數(shù)字簽名的概念。在那些示例中,數(shù)字簽名在 SOAP 信封的基礎(chǔ)上被創(chuàng)建。可以應(yīng)用同樣的驗證測試。
例如,您可以生成一個特別的有時間戳的認證令牌(這個令牌已被數(shù)字簽名以防止在傳輸過程中篡改)。在訪問第二個服務(wù)時,您可以驗證第一個服務(wù)是始發(fā)者(originator)且這個令牌具有完整性。這提供了一個使許多 Web 服務(wù)解決方案安全的方法;一個對象級別的高速緩存能使您迅速且簡單地完成。
在這個實例中,高速緩存系統(tǒng)是自清除種類的。您僅需要一個通過其密鑰存儲項的方法。您可以將生存時間設(shè)置為比原先的令牌請求時間的有效期長。這個高速緩存便是自清除的,因此您維護了健康的資源使用。
當接收到一個請求時,您可以檢查這個項是不是不在高速緩存中。如果它在高速緩存中,則拋出一個錯誤。如果它不在高速緩存中,您知道這是一個有效的請求,并將這個項處理并存儲在高速緩存中。當包已經(jīng)超時并從高速緩存中被清除時,將錯誤消息從先前已被處理更改為令牌失效。使用這個示例中的高速緩存能夠加速性能,因為您可以在提交前決定是否處理這個請求。
![]() |
|
使您的 Web 服務(wù)在高度緊張的環(huán)境中順利執(zhí)行對于技術(shù)的存活非常重要。從短期來看,您將看到許多 Web 高速緩存專家都重新設(shè)計他們的工具和解決方案以變得更加通曉 Web 服務(wù)。即使在他們設(shè)計的進候,有時也會在服務(wù)級別智能使用高速緩存中獲益。隨著底層 SOAP 實現(xiàn)的成熟,您將開始看到設(shè)計模式參考。這些參考將會講述如何構(gòu)建快速的和可伸縮的 Web 服務(wù)解決方案。到那個時候,運行您自己的解決方案吧。即使在聯(lián)網(wǎng)世界到來的時候,有時也有使用定制的高速緩存更好執(zhí)行的情況。隨著 Web 服務(wù)越來越受到歡迎,人們對它的要求也會增加。當您構(gòu)建這個分布式基礎(chǔ)結(jié)構(gòu)時,請思考一下速度。當您通過重復(fù)使用先前的計算而不是重復(fù)底層的進程來提取代碼時,您便贏得了時間。