服務的有狀態和無狀態


對服務器程序來說,究竟是有狀態服務,還是無狀態服務,其判斷依舊——兩個來自相同發起者的請求在服務器端是否具備上下文關系。

狀態化請求,服務器端一般都要保存請求的相關信息,每個請求可以默認地使用以前的請求信息。

無狀態請求,服務器端所能夠處理的過程必須全部來自於請求所攜帶的信息,以及其他服務器端自身所保存的、並且可以被所有請求所使用的公共信息。

 

一、比較

有狀態服務常常用於實現事務(並不是唯一辦法,下文有另外的方案)。舉一個常見的例子,在商城里購買一件商品。需要經過放入購物車、確認訂單、付款等多個步驟。

由於HTTP協議本身是無狀態的,所以為了實現有狀態服務,就需要通過一些額外的方案。比如最常見的session,將用戶挑選的商品(購物車),保存到session中,當付款的時候,再從購物車里取出商品信息 


服務要設計為無狀態的,這主要是從可伸縮性來考慮的。

如果server是無狀態的,那么對於客戶端來說,就可以將請求發送到任意一台server上,然后就可以通過負載均衡等手段,實現水平擴展

如果server是有狀態的,那么就無法很容易地實現了,因為客戶端需要始終把請求發到同一台server才行,所謂session遷移”等方案,也就是為了解決這個問題 

6486d16d-38c6-38de-837f-637ff99c30d4.png

三、session和cookie 

基於session和cookie都可以實現事務,可以認為,session是有狀態的,而cookie是無狀態的 

四、無狀態實現事務的方法 

並不是一定要用有狀態服務才能實現事務,本文提供另外的幾種方案作為參考 
舉一個多次提交的場景作為例子:用戶需要提交很多數據,分為2個頁面提交 

d2a571e3-dea4-3fad-bf5b-e896730ebf10.png

這里就涉及到2次http請求,第一次提交字段1、2、3,第二次提交字段4、5、6 

用session很容易實現這個需求,server只需要將第一次提交的數據,保存在session里,然后返回第2個表單作為相應;然后取出第一次提交的數據,和第二次提交的數據匯聚以后,一起存入數據庫即可 

不用session同樣也可以實現,server接收到第一次請求以后,將數據作為隱藏元素,放在第2個表單里返回;這樣用戶第2次提交的時候,就隱含地再次提交了第一次的數據;server將所有數據存入數據庫 
用HTML5,則還可以進一步優化,client可以將第一次提交的數據,保存在sessionStorage里 
用cookie也是類似的道理,同樣可以實現,但是不太好 

總的來說,3種替代方案(隱藏表單元素、sessionStorage、cookie)都避免了在server端暫存數據,從而實現了stateless service。本質上,這3種方案的請求里,都包含了所有必須的數據,符合本文一開始的定義 

五、將有狀態服務轉換成無狀態服務 

根據本文一開始的定義,除了將所有信息都放在請求里之外,還有另外一種方法可以實現無狀態服務,即將信息放在一個單獨可共享的地方,獨立於server存在 
比如,同樣還是采取session的方式,在服務端保存數據,減少每次client請求傳輸的數據量(節省流量),但是將session集中存放,比如放在單獨的session層里。這種情況下,server同樣是無狀態的,可以做水平擴展 

47bd72bf-1162-33d2-be07-0ddcebdc633a.png


六、總結 
有狀態服務可以比較容易地實現事務,在不需要考慮水平擴展時,是比較好的選擇 
無狀態服務的優勢在於可以很方便地水平伸縮,但是在實現事務時,需要做一些額外的動作 
可以通過剝離session等方法,將一個有狀態服務,轉換成無狀態服務 

 

注:什么是事務?

事務,就是把一堆事情綁在一起做,都成功了才算完成,否則就恢復之前的樣子。
舉例:銀行ATM取錢,扣款成功后突然大停電,吐錢的操作還沒做,這時候就要恢復沒取錢時候的狀態,否則錢扣了還沒拿到手,多冤枉

 

原文鏈接;

http://kyfxbl.iteye.com/blog/1831869


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM