日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
Java理論與實(shí)踐:Web層的狀態(tài)復(fù)制

不管正在構(gòu)建的是 J2EE 還是 J2SE 服務(wù)器應(yīng)用程序,都有可能以某種方式使用 Java Servlet —— 可能是直接地通過(guò)像 JSP 技術(shù)、Velocity 或者 WebMacro 這樣的表示層,也可能通過(guò)一個(gè)基于 servlet 的 Web 服務(wù)實(shí)現(xiàn),如 Axis 或者 Glue。Servlet API 提供的一個(gè)最重要的功能是會(huì)話(huà)管理 —— 通過(guò) HttpSession 接口進(jìn)行用戶(hù)狀態(tài)的認(rèn)證、失效和維護(hù)。

目前創(chuàng)新互聯(lián)建站已為超過(guò)千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)站空間、綿陽(yáng)服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計(jì)、澧縣網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶(hù)導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶(hù)和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

會(huì)話(huà)狀態(tài)

幾乎每一個(gè) Web 應(yīng)用程序都有一些會(huì)話(huà)狀態(tài),這些狀態(tài)有可能像記住您是否已登錄這么簡(jiǎn)單,也可能是您的會(huì)話(huà)的更詳細(xì)的歷史,如購(gòu)物車(chē)的內(nèi)容、以前查詢(xún)結(jié)果的緩存或者 20 頁(yè)動(dòng)態(tài)問(wèn)卷表的完整響應(yīng)歷史。因?yàn)?HTTP 協(xié)議本身是無(wú)狀態(tài)的,所以需要將會(huì)話(huà)狀態(tài)存儲(chǔ)在某處并與瀏覽會(huì)話(huà)以某種方式相關(guān)聯(lián),使得下次請(qǐng)求同一 Web 應(yīng)用程序的頁(yè)面時(shí)可以容易地獲取。幸運(yùn)的是,J2EE 提供了幾種管理會(huì)話(huà)狀態(tài)的方法 —— 狀態(tài)可以存儲(chǔ)在數(shù)據(jù)層,用 Servlet API 的 HttpSession 接口存儲(chǔ)在 Web 層,用有狀態(tài)會(huì)話(huà) bean 存儲(chǔ)在 Enterprise JavaBeans(EJB)層,甚至用 cookie 或者隱藏表單字段將狀態(tài)存儲(chǔ)在客戶(hù)層。不幸的是,會(huì)話(huà)狀態(tài)管理不當(dāng)會(huì)帶來(lái)嚴(yán)重的性能問(wèn)題。

如果應(yīng)用程序能夠在 HttpSession 中存儲(chǔ)用戶(hù)狀態(tài),這種方法通常比其他方法更好。在客戶(hù)端用 HTTP cookie 或者隱藏表單字段存儲(chǔ)會(huì)話(huà)狀態(tài)有很大的安全風(fēng)險(xiǎn) —— 它將應(yīng)用程序的一部分內(nèi)部?jī)?nèi)容暴露給了非受信任的客戶(hù)層。(一個(gè)早期的電子商務(wù)網(wǎng)站將購(gòu)物車(chē)內(nèi)容(包括價(jià)格)存儲(chǔ)在隱藏表單字段中,從而可以很容易被非法利用,讓任何了解 HTML 和 HTTP 的用戶(hù)可以以 0.01 美元購(gòu)買(mǎi)任何商品。噢)此外,使用 cookie 或者隱藏表單字段很混亂,容易出錯(cuò),并且脆弱(如果用戶(hù)禁止在瀏覽器中使用 cookie,那么基于 cookie 的方法就完全不能工作)。

在 J2EE 應(yīng)用程序中存儲(chǔ)服務(wù)器端狀態(tài)的其他方法是使用有狀態(tài)會(huì)話(huà) bean,或者在數(shù)據(jù)庫(kù)中存儲(chǔ)會(huì)話(huà)狀態(tài)。雖然有狀態(tài)會(huì)話(huà) bean 在會(huì)話(huà)狀態(tài)管理方面有更大的靈活性,但是在可能的情況下,將會(huì)話(huà)狀態(tài)存儲(chǔ)在 Web 層仍然有好處。如果業(yè)務(wù)對(duì)象是無(wú)狀態(tài)的,那么通常可以?xún)H僅添加更多 Web 服務(wù)器來(lái)擴(kuò)展應(yīng)用程序,而不用添加更多 Web 服務(wù)器和更多 EJB 容器, 這樣的成本一般要低一些并且容易完成。使用 HttpSession 存儲(chǔ)會(huì)話(huà)狀態(tài)的另一個(gè)好處是 Servlet API 提供了一種會(huì)話(huà)失效時(shí)通知的容易方法。在數(shù)據(jù)庫(kù)中存儲(chǔ)會(huì)話(huà)狀態(tài)的成本可能難以承受。

servlet 規(guī)范沒(méi)有要求 servlet 容器進(jìn)行某種類(lèi)型的會(huì)話(huà)復(fù)制或者持久性,但是它建議將狀態(tài)復(fù)制作為 servlet 首要 存在理由(raison d'etre) 的重要部分,并且它對(duì)作為進(jìn)行會(huì)話(huà)復(fù)制的容器提出了一些要求。會(huì)話(huà)復(fù)制可以提供大量好處 —— 負(fù)載平衡、伸縮性、容錯(cuò)和高可用性。相應(yīng)地,大多數(shù) servlet 容器支持某種形式的 HttpSession 復(fù)制,但是復(fù)制的機(jī)制、配置和時(shí)間是由實(shí)現(xiàn)決定的。

HttpSession API

簡(jiǎn)單地說(shuō), HttpSession 接口支持幾種方法,servlet、JSP 頁(yè)或者其他表示層組件可以用這些方法來(lái)跨多個(gè) HTTP 請(qǐng)求維護(hù)會(huì)話(huà)信息。會(huì)話(huà)綁定到特定的用戶(hù),但是在 Web 應(yīng)用程序的所有 servlet 中共享 —— 不特定于某一個(gè) servlet。一種考慮會(huì)話(huà)的有用方法是,會(huì)話(huà)像一個(gè)在會(huì)話(huà)期間存儲(chǔ)對(duì)象的 Map —— 可以用 setAttribute 按名字存儲(chǔ)會(huì)話(huà)屬性,并用 getAttribute 提取它們。 HttpSession 接口還包含會(huì)話(huà)生存周期方法,如 invalidate() (它通知容器應(yīng)丟棄會(huì)話(huà))。清單 1 顯示 HttpSession 接口最常用的元素:

清單 1. HttpSession API

 
 
 
  1. public interface HttpSession {
  2.      Object getAttribute(String s);
  3.      Enumeration getAttributeNames();
  4.      void setAttribute(String s, Object o);
  5.      void removeAttribute(String s);
  6.      boolean isNew();
  7.      void invalidate();
  8.      void setMaxInactiveInterval(int i);
  9.      int getMaxInactiveInterval();
  10.      ...
  11.  }

理論上,可以跨群集一致性地完全復(fù)制會(huì)話(huà)狀態(tài),這樣群集中的所有節(jié)點(diǎn)都可以服務(wù)任何請(qǐng)求,一個(gè)簡(jiǎn)單的負(fù)載平衡器可以以輪詢(xún)方式傳送請(qǐng)求,避開(kāi)有故障的主機(jī)。不過(guò),這種緊密的復(fù)制有很高的性能成本,并且難于實(shí)現(xiàn),當(dāng)群集接近某一規(guī)模時(shí),還會(huì)有伸縮性的問(wèn)題。

一種更常用的方式是將負(fù)載平衡與會(huì)話(huà)相似性(affinity) 結(jié)合起來(lái) —— 負(fù)載平衡器可以將會(huì)話(huà)與連接相關(guān)聯(lián),并將會(huì)話(huà)中以后的請(qǐng)求發(fā)送給同一服務(wù)器。有很多硬件和軟件負(fù)載平衡器支持這個(gè)功能,并且這意味著只有主連接主機(jī)和會(huì)話(huà)需要故障轉(zhuǎn)移到另一臺(tái)服務(wù)器時(shí)才訪問(wèn)復(fù)制的會(huì)話(huà)信息。

復(fù)制方式

復(fù)制提供了一些可能的好處,包括可用性、容錯(cuò)和伸縮性。此外,有大量會(huì)話(huà)復(fù)制的方法可用:方法的選擇取決于應(yīng)用程序群集的規(guī)模、復(fù)制的目標(biāo)和 servlet 容器支持的復(fù)制設(shè)施。復(fù)制有性能成本,包括 CPU 周期(存儲(chǔ)在會(huì)話(huà)中的序列化對(duì)象)、網(wǎng)絡(luò)帶寬(廣播更新),以及基于磁盤(pán)的方案中寫(xiě)入到磁盤(pán)或者數(shù)據(jù)庫(kù)的成本。

幾乎所有 servlet 容器都通過(guò)存儲(chǔ)在 HttpSession 中的序列化對(duì)象進(jìn)行 HttpSession 復(fù)制,所以如果是創(chuàng)建一個(gè)分布式應(yīng)用程序,應(yīng)當(dāng)確保只將可序列化對(duì)象放到會(huì)話(huà)中。(一些容器對(duì)像 EJB 引用、事務(wù)上下文、還有其他非可序列化的 J2EE 對(duì)象類(lèi)型有特殊的處理。)

基于JDBC 的復(fù)制

一種會(huì)話(huà)復(fù)制的方法是序列化會(huì)話(huà)內(nèi)容并將它寫(xiě)入數(shù)據(jù)庫(kù)。這種方法相當(dāng)直觀,其優(yōu)點(diǎn)是不僅會(huì)話(huà)可以故障轉(zhuǎn)移到其他主機(jī),而且即使整個(gè)群集失效,會(huì)話(huà)數(shù)據(jù)也可以保存下來(lái)?;跀?shù)據(jù)庫(kù)的復(fù)制的缺點(diǎn)是性能成本 —— 數(shù)據(jù)庫(kù)事務(wù)是昂貴的。雖然它可以在 Web 層很好地伸縮,但是它可能在數(shù)據(jù)層產(chǎn)生伸縮問(wèn)題 —— 如果群集增長(zhǎng)大到一定程度,擴(kuò)展數(shù)據(jù)層以容納會(huì)話(huà)數(shù)據(jù)會(huì)很困難或者成本無(wú)法接受。

基于文件的復(fù)制

基于文件的復(fù)制類(lèi)似于使用數(shù)據(jù)庫(kù)存儲(chǔ)序列化的會(huì)話(huà),只不過(guò)是使用共享文件服務(wù)器而不是數(shù)據(jù)庫(kù)來(lái)存儲(chǔ)會(huì)話(huà)數(shù)據(jù)。這種方式的成本一般比使用數(shù)據(jù)庫(kù)的成本(硬件成本、軟件許可證和計(jì)算開(kāi)銷(xiāo))低,其代價(jià)則是可靠性(數(shù)據(jù)庫(kù)可提供比文件系統(tǒng)更強(qiáng)的持久化保證)。

基于內(nèi)存的復(fù)制

另一種復(fù)制方式是與群集中的一個(gè)或者多個(gè)其他服務(wù)器共享序列化的會(huì)話(huà)數(shù)據(jù)副本。復(fù)制所有會(huì)話(huà)到所有主機(jī)中提供了最大的可用性,并且負(fù)載平衡最容易,但是因?yàn)閺?fù)制消息所消耗的每個(gè)節(jié)點(diǎn)的內(nèi)存和網(wǎng)絡(luò)帶寬,最終會(huì)限制群集的規(guī)模。一些應(yīng)用服務(wù)器支持與“伙伴(buddy)”節(jié)點(diǎn)的基于內(nèi)存的復(fù)制,其中每一個(gè)會(huì)話(huà)存在于主服務(wù)器上和一臺(tái)(或更多)備份服務(wù)器上。這種方案比將所有會(huì)話(huà)復(fù)制到所有服務(wù)器的伸縮性更好,但是當(dāng)需要將會(huì)話(huà)故障轉(zhuǎn)移到另一臺(tái)服務(wù)器上時(shí)會(huì)使負(fù)載平衡任務(wù)復(fù)雜化,因?yàn)樗仨氄页隽硗饽囊慌_(tái)(幾臺(tái))服務(wù)器有這個(gè)會(huì)話(huà)。

時(shí)間考慮

除了決定如何存儲(chǔ)復(fù)制會(huì)話(huà)數(shù)據(jù),還有什么時(shí)候復(fù)制數(shù)據(jù)的問(wèn)題。最可靠但也最昂貴的方法是每次數(shù)據(jù)改變時(shí)復(fù)制它(如每次 servlet 調(diào)用結(jié)束)。不那么昂貴、但是在故障時(shí)會(huì)有丟失一些數(shù)據(jù)的風(fēng)險(xiǎn)的方法是在每超過(guò) N 秒時(shí)復(fù)制數(shù)據(jù)。

與時(shí)間問(wèn)題有關(guān)的問(wèn)題是,是復(fù)制整個(gè)會(huì)話(huà)還是只試嘗復(fù)制會(huì)話(huà)中改變了的屬性(它包含的數(shù)據(jù)會(huì)少得多)。這些都需要在可靠性和性能之間進(jìn)行取舍。Servlet 開(kāi)發(fā)人員應(yīng)當(dāng)認(rèn)識(shí)到在故障轉(zhuǎn)移時(shí),會(huì)話(huà)狀態(tài)可能變得“過(guò)時(shí)”(是幾次請(qǐng)求前的復(fù)制),并應(yīng)當(dāng)準(zhǔn)備處理不是最新的會(huì)話(huà)內(nèi)容。(例如,如果一個(gè)interview 的第 3 步產(chǎn)生一個(gè)會(huì)話(huà)屬性,而用戶(hù)在第 4 步時(shí),請(qǐng)求被故障轉(zhuǎn)移到一個(gè)具有兩次請(qǐng)求之前的會(huì)話(huà)狀態(tài)復(fù)制的系統(tǒng)上,那么第 4 步的 servlet 代碼應(yīng)預(yù)備在會(huì)話(huà)中找不到這個(gè)屬性,并采取相應(yīng)的行動(dòng) —— 如重定向,而不是認(rèn)定它會(huì)在那里、并在找不到它時(shí)拋出一個(gè) NullPointerException 。)

容器支持

Servlet 容器的 HttpSession 復(fù)制選項(xiàng)以及如何配置這些選項(xiàng)是各不相同的。IBM WebSphere ?提供的復(fù)制選項(xiàng)是最多的,它提供了在內(nèi)存中復(fù)制或者基于數(shù)據(jù)庫(kù)的復(fù)制、在 servlet 末尾或者基于時(shí)間的復(fù)制時(shí)間、傳播全部會(huì)話(huà)快照(JBoss 3.2 或以后版本)或者只傳播改變了的屬性等選擇?;趦?nèi)存的復(fù)制基于 JMS 發(fā)布-訂閱,它可以復(fù)制到所有克隆、一個(gè)“伙伴”復(fù)制品或者一個(gè)專(zhuān)門(mén)的復(fù)制服務(wù)器。

WebLogic 還提供了一組選擇,包括內(nèi)存中(使用一個(gè)伙伴復(fù)制品)、基于文件的或者基于數(shù)據(jù)庫(kù)的。JBoss 與 Tomcat 或者 Jetty servlet 容器一同使用時(shí),進(jìn)行基于內(nèi)存的復(fù)制,可以選擇 servlet 末尾或者基于時(shí)間的復(fù)制時(shí)間,而快照選項(xiàng)(在 JBoss 3.2 或以后版本)是只復(fù)制改變了的屬性。Tomcat 5.0 為所有群集節(jié)點(diǎn)提供了基于內(nèi)存的復(fù)制。此外,通過(guò)像 WADI 這樣的項(xiàng)目,可以用 servlet 過(guò)濾機(jī)制將會(huì)話(huà)復(fù)制添加到像 Tomcat 或者 Jetty 這樣的 servlet 容器中。

改進(jìn)分布式 Web 應(yīng)用程序的性能

不管決定使用什么機(jī)制進(jìn)行會(huì)話(huà)復(fù)制,可以用幾種方式改進(jìn) Web 應(yīng)用程序的性能和伸縮性。首先記住,為了獲得會(huì)話(huà)復(fù)制的好處,需要在部署描述符中將 Web 應(yīng)用程序標(biāo)記為 distributable,并保證在會(huì)話(huà)中的所有內(nèi)容都是可序列化的。

保持會(huì)話(huà)最小

因?yàn)閺?fù)制會(huì)話(huà)有隨著會(huì)話(huà)中的對(duì)象圖(object graph) 的變大而增加成本,所以應(yīng)當(dāng)盡可能地在會(huì)話(huà)中少放置數(shù)據(jù)。這樣做會(huì)減少?gòu)?fù)制的序列化的開(kāi)銷(xiāo)、網(wǎng)絡(luò)帶寬要求和磁盤(pán)要求。特別地,將共享對(duì)象存儲(chǔ)在會(huì)話(huà)中一般不是好主意,因?yàn)樗鼈冃枰獜?fù)制到它們所屬的 每一個(gè)會(huì)話(huà)中。

不要繞過(guò) setAttribute

在改變會(huì)話(huà)的屬性時(shí),要知道即使 servlet 容器只是試圖做最小的更新(只傳播改變了的屬性),如果沒(méi)有調(diào)用 setAttribute ,容器也可能沒(méi)有注意到已經(jīng)改變的屬性。(想像在會(huì)話(huà)中有一個(gè) Vector ,表示購(gòu)物車(chē)中的商品 —— 如果調(diào)用 getAttribute() 獲取 Vector 、然后向它添加一些內(nèi)容,并且不再次調(diào)用 setAttribute ,容器可能不會(huì)意識(shí)到 Vector 已經(jīng)改變了。)

使用細(xì)化的會(huì)話(huà)屬性

對(duì)于支持最小更新的容器,可以通過(guò)將多個(gè)細(xì)化的對(duì)象而不是一個(gè)大塊頭放到會(huì)話(huà)中而降低會(huì)話(huà)復(fù)制的成本。這樣,對(duì)快速改變的數(shù)據(jù)的改變也不會(huì)迫使容器去序列化并傳播慢速改變的數(shù)據(jù)。

完成后使之失效

如果知道用戶(hù)完成了會(huì)話(huà)的使用(如,用戶(hù)選擇注銷(xiāo)登錄),確保調(diào)用 HttpSession.invalidate() 。否則,會(huì)話(huà)將持久化直到它失效,這會(huì)消耗內(nèi)存,并且可能是長(zhǎng)時(shí)間的(取決于會(huì)話(huà)超時(shí)時(shí)間)。許多 servlet 容器對(duì)可以跨所有會(huì)話(huà)使用的內(nèi)存的數(shù)量有一個(gè)限制,達(dá)到這個(gè)限制時(shí),會(huì)序列化最先使用的會(huì)話(huà)并將它寫(xiě)到磁盤(pán)上。如果知道用戶(hù)使用完了會(huì)話(huà),可以使容器不再處理它并使它作廢。

保持會(huì)話(huà)干凈

如果在會(huì)話(huà)中有大的項(xiàng),并且只在會(huì)話(huà)的一部分中使用,那么當(dāng)不再需要時(shí)應(yīng)刪除它們。刪除它們會(huì)減少會(huì)話(huà)復(fù)制的成本。(這種做法類(lèi)似于使用顯式 nulling 以幫助垃圾收集器,老讀者知道我一般不建議這樣做,但是在這種情況下,因?yàn)橛袕?fù)制,在會(huì)話(huà)中保持垃圾的成本要高得多,因此值得以這種方式幫助容器。)

結(jié)束語(yǔ)

通過(guò) HttpSession 復(fù)制,Servlet 容器可以在構(gòu)建復(fù)制的、高可用性的 Web 應(yīng)用程序方面給您減輕很多負(fù)擔(dān)。不過(guò),對(duì)于復(fù)制有一些配置選項(xiàng),每個(gè)容器都不一樣,復(fù)制策略的選擇對(duì)于應(yīng)用程序的容錯(cuò)、性能和伸縮性有影響。復(fù)制策略的選擇不應(yīng)當(dāng)是事后的 —— 您應(yīng)當(dāng)在構(gòu)建 Web 應(yīng)用程序時(shí)就考慮它。并且,一定不要忘記進(jìn)行負(fù)載測(cè)試以確定應(yīng)用程序的伸縮性 —— 在客戶(hù)替您做之前。


文章名稱(chēng):Java理論與實(shí)踐:Web層的狀態(tài)復(fù)制
當(dāng)前地址:http://www.5511xx.com/article/dhhhjij.html