2009-07-30 55 views
3

因此,我在查看人們爲雙面通信創建的示例示例,即由IIS託管並通過Silverlight連接時。有很多的這個那裏(this MSDN article is great)的例子,但所有使用相同的模式:羣集環境中的WCF雙工通信

用戶A連接到服務器A,這讓他在內存中的列表獲得未來的更新。
用戶B連接到服務器A,它會通知列表中有人「登錄」的所有用戶。

...但是當

用戶C連接到服務器C,在內存中的列表服務器C不包含用戶A或B.

的問題會發生什麼是我希望在集羣(Web場)環境中實現這一點。這使事情變得複雜,因爲我無法驗證哪臺機器會接管wcf呼叫,所以將任何消息轉發給所有其他用戶是困難的。

我能想到的最佳場景是實際上客戶端連接到某種路由服務,它接收傳入的請求並將客戶端轉發到特定的計算機。當然,那麼我會失去網絡農場的好處,因爲一臺機器可以有效地處理所有傳入的請求。

不太有效的解決方案是讓服務不斷輪詢某些內容(文件服務器上的文件或數據庫中的表)以查找更改。一旦出現變化,將它們推送給客戶端。這似乎是一個非常醜陋的寶貝,壽。

我錯過了什麼?

更新 - 路由系統對我的需求是不可能的。我的託管公司不允許我通過IP直接連接到農場上的特定機器。我只能連接到通用負載均衡器前端,因此不能保證我的用戶將在同一臺服務器上運行。

到目前爲止,我們只能輪詢db中的表來尋找變化。仍然像一個醜陋的嬰兒。

+1

您的客戶使用哪種技術? – 2009-07-30 13:56:48

+0

@Shiraz Bhaiji:客戶計劃在Silverlight中實施。 – JustLoren 2009-07-30 14:09:41

回答

0

您可以使用「粘滯IP」配置您的Web場。

這意味着當客戶端連接到網絡農場時,他將被路由到一臺機器。來自該客戶端的所有以下請求都將轉到場中的同一臺計算機上。 這有點像您在問題中描述的路由服務。

編輯

可能是最容易實現輪詢系統,其中Silverlight客戶端請求的Web服務器「有沒有什麼新的我」時,該請求將包含的最後一次客戶要求的時間。新東西的列表將被存儲在數據庫表中。所以沒有問題,你打網絡服務器。

此外,你需要注意Silverlight WCF的限制,如果我理解正確,它不會實現所有的WCF。

EDIT 2

在你需要在同一時間向所有用戶溝通的情況下,調用不會需要向下走一路到數據庫。這可以在WCF服務級別的內存中緩存,其他客戶端將從內存中獲取此內容,從而爲您提供更好的性能和更低的數據庫負載。

編輯3

只要你使用的是Silverlight客戶端就很難爲客戶相互直接通信。儘管它們需要額外的工作/成本,但有兩種可能性:

  • 使用Azure服務總線,每個客戶端都會與轉換爲直接通信的雲端點通信。
  • 使用silverlight拖放,使用可以公開WCF服務端點的客戶端。當客戶端啓動時,它向服務器註冊端點。然後,每個客戶端可以詢問在線的服務器,並直接向客戶端發送消息。
+0

這不是正確的解決方案,因爲它不能讓我同時與所有用戶進行通信。只有同一臺機器上的所有用戶。我見過的例子都使用內存中的對象/列表來將數據推送到所有連接的客戶端。客戶端連接到另一臺機器的情況如何? – JustLoren 2009-07-30 13:33:55

+0

我會澄清我的問題:) – JustLoren 2009-07-30 16:00:30

+0

您的數據庫輪詢答案是可行的,但我不禁感到它將在服務器上的CPU密集型。每個.5s會是另一個數據庫命中,詢問「任何新消息?」還有其他解決方案嗎? – JustLoren 2009-08-21 18:56:31

1

假設你不需要的通知實時型,典型的方法是使用一個後端會話數據庫或專用的會話服務器使所有當前登錄的用戶對所有羣集計算機可見。然後,您可以編寫輪詢服務來發送更改通知,或根據您的要求進行更高級的更改。

在您的示例中,您需要將「內存中」用戶列表移動到共享內存服務器或共享數據庫。您當然可以實施某種羣集更新通知以發送給所有機器,但其複雜性可能超出您的需求。

+0

你能否闡述一下「共享內存服務器」? – JustLoren 2009-08-21 18:57:08

1

服務器可以直接相互通信嗎?如果是這樣,您可能需要設置只有服務器場中的其他服務器才能連接的專用端點。然後,當服務器C收到一條消息時,它向服務器A發送一條消息,通知它這個事實,然後服務器A可以將它轉發給它的客戶端。

1

使用Memcached或MSMQ。

使用Memcached,您可以將它用作需要廣播的所有項目的單一事實點。所以,當你得到一個客戶端登錄時,你將一些簡單的數據轉儲到Memcached中。它會通知其他服務器並更新其他服務器的列表。然後,當您發佈信息時,查詢Memcached。

使用MSMQ,將登錄信息推入隊列,然後在兩臺服務器上實現偵聽器,從隊列中讀取數據並更新其內存列表中的「可發佈」信息。這樣,兩臺服務器都會隨時瞭解需要發佈的數據。

1

您的解決方案提供商是否將MS SQL用於數據庫服務器?如果您有完整的MS SQL數據庫權限,則可以實現T-SQL觸發器。當數據庫CRUD操作發生時,您可以編寫一個執行代碼的觸發器。使用當前版本的MS SQL,您甚至可以執行託管(C#/ VB#)代碼。

此解決方案將非常複雜但可能。我會爲你的集羣使用一箇中央MS SQL並編寫一些T-SQL觸發器代碼。當你關心的記錄被修改/ etc時,我會讓SQL服務器向集羣中的其他服務器發送特殊的HTTP Web請求消息(假設集羣中的服務器可以隨意與其他/所有集羣服務器通信)他們知道任何變化。然後,每臺服務器都可以使用全局應用程序緩存向服務器上的每個會話廣播更改。

這是我的非常好的建議。

-Jeff

2

假設你有零控制環境的超越,你可以在每臺服務器上安裝了什麼(即沒有MSMQ,沒有ESB等),那麼我會考慮使用WCF服務器之間進行通信。一個簡單的問題似乎是您的內存列表需要在兩臺服務器之間保持同步,並且每當列表內容發生更改時,都需要通知兩臺服務器的用戶。

通過兩臺服務器託管和使用的內部WCF服務,您可以使用簡單的即時消息傳遞來保持列表同步。想象一下以下情形:

  1. 「用戶A」在服務器A
    1. 添加「用戶A日誌文件,在線用戶列表
    2. 消防信息到服務器B,通知增加了「用戶的A」
      1. 導致服務器B添加‘用戶A’到它的在線用戶列表
      2. 原因服務器B通知用戶登錄的所有用戶
    3. 通知所有用戶在用戶登錄的服務器A
  2. 「用戶B」到服務器B
    1. 添加「用戶B」網上用戶
    2. 消防消息服務器的列表記錄A到通知它ADDD「用戶B」
      1. 導致服務器A到「用戶B」添加到其在線用戶
      2. 名單的原因服務器A通知我們的所有用戶呃登錄
    3. 從在線用戶列表通知所有用戶在用戶登錄的服務器B
  3. '用戶A' 註銷服務器A
    1. 刪除 '用戶A' 的
    2. 向服務器B發送消息,通知它已刪除'用戶A'
      1. 導致服務器B從其在線用戶列表中刪除'用戶A'
      2. 導致服務器B通知用戶註銷
    3. 的所有用戶通知所有用戶在註銷用戶的服務器A
  4. 定期,有服務器A和服務器B同步它們彼此 列表(莫非實現乒乓風格......一個服務器ping其名單向其他服務器, 其他服務器合併和合並pongs列表返回)

以上情景明顯假設你有能力ŧ o在託管服務器上安裝WCF服務,以便它們可以相互通信。我不確定您是否有能力在每臺服務器的內部知道其他服務器,正如您所提到的,所有流量都必須通過負載均衡器。

0

來自MS的速度項目可能比數據庫後端更快; 它是一個內存緩存層,具有所有集羣/故障切換功能......您可以在WEB和DB層之間滑動它;它的API非常簡單,並與.NET的其他部分保持一致。