2009-01-02 108 views
35

如果有一個REST資源需要監視來自其他客戶端的更改或修改,那麼最好(也是最RESTful)的方式是什麼?什麼是監視REST資源更改的RESTful方式?

我這樣做的一個想法是通過提供特定資源來保持連接開放,而不是在資源尚未存在時立即返回。例如,給定資源:

/game/17/playerToMove 

此資源上的「GET」可能會告訴我,這是我的對手輪到移動。而不是不斷輪詢這一資源,找出當輪到我運動,我可能會注意移動數(說5),嘗試檢索下一步的行動:

/game/17/move/5 

在一個「正常」的REST模式,它似乎對此URL的GET請求將返回404(未找到)錯誤。然而,如果相反,服務器保持連接打開,直到我的對手發揮他的舉動,即:

PUT /game/17/move/5 

那麼服務器會返回我的對手投入該資源的內容。這將爲我提供我需要的數據,以及當我的對手移動而不需要輪詢時的一種通知。

這種方案是RESTful嗎?或者它違反了某種REST原則?

+1

「什麼是最簡單的方法來做到這一點,Scrappy?」 – 2012-11-06 10:26:15

+0

您可以使用長輪詢,或將REST與將事件發送到客戶端的websocket服務結合使用。 – inf3rno 2015-05-31 19:32:08

回答

24

您提出的解決方案聽起來像long polling,這可能工作得很好。

你會要求/game/17/move/5和服務器將不會發送任何數據,直到移動5已完成。如果連接斷開,或者超時,只需重新連接,直到獲得有效的響應。

這樣做的好處是非常快 - 只要服務器有新數據,客戶端就會得到它。這也是抵禦掉線,如果客戶端斷開了一段時間(你可以要求/game/17/move/5一個小時它被移動後,就會立即得到數據,然後移動到move/6/等)

與長期問題的工作輪詢是每個「輪詢」都捆綁了一個服務器線程,這個服務器線程很快就會破壞像Apache這樣的服務器(因爲它耗盡了工作線程,所以不能接受其他請求)。您需要專門的Web服務器來處理長輪詢請求。Python模塊twisted(「事件驅動的網絡引擎」)非常適合這種情況,但它比普通的輪詢更有用。

在回答關於Jetty/Tomcat的評論時,我沒有任何Java經驗,但似乎他們都使用類似於Apache的工作線程系統,所以它會有同樣的問題。我確實發現了this post,這似乎正好解決了這個問題(對於Tomcat而言)

2

我發現this article提出了一個新的HTTP頭「When-Modified-After」,它基本上做了同樣的事情 - 服務器等待並保持連接打開,直到資源被修改。

我更喜歡基於版本的方法,而不是基於時間戳的方法,因爲它不太容易出現競爭條件,並且可以提供更多有關您檢索內容的更多信息。對這種方法有什麼想法?

+0

基於版本的方法將使用ETag HTTP標頭。 http://en.wikipedia.org/wiki/HTTP_ETag – Chase 2012-12-18 16:56:21

2

我會建議一個404,如果您的預期客戶端是一個Web瀏覽器,因爲保持連接打開可以主動阻止客戶端到同一個域的瀏覽器請求。這是由客戶多久進行一次輪詢。

+0

這是一種錯誤的錯誤(你怎麼檢測實際的404因爲你要求/遊戲/ X14不是/遊戲/ 14)..返回{'錯誤' :'no new content'}或者其他東西的問題會更少.. – dbr 2009-01-02 04:26:42