2010-10-27 26 views
0

這建立在How to send messages between Companies上。如果我決定公司S(upplier)應該以某種簡單的基於HTTP的方式輪詢公司(B)的訂單,那麼最好的實現方式是什麼。如何確保通過網絡服務器的拉/查詢傳輸郵件

  • 我假設公司B有一個Web服務器正在運行,並且該Web服務器的後端數據庫是持久的。我們應該儘可能少地假設S上的存儲過程,並且他們是否能夠保持狀態(例如,已經傳輸的GUID列表)
  • B和S之間的因特網連接是不可靠的。
  • 我們必須達到eventual consistency這意味着在一個時間點B和S之間的所有訂單都應該被轉移。

實施此類系統的最佳實踐是什麼?

回答

3

這種問題的一種方法是使用某種排隊產品,作爲我立即考慮MQ的IBM人員。然而,因爲我自己並不是真正的MQ人,所以我可能會對您採用的基於服務的方法感到滿意。

想到兩種可能的方法。一種是使用WS Reliable Messaging,它將可靠性問題推入Web服務基礎架構。另一種方法是在簡單但不可靠的服務之上提供自己的可靠協議。

我對WS Reliable Messaging實現系統沒有認真的實踐經驗,我確信它可以工作,但它確實需要對參與者進行某種程度的控制 - 因爲它是一個相對較新的標準我們不能保證任何給定的IT商店都將實施交付,並且供應商之間的互操作性可能是一個問題。我對每一端的SW堆棧的控制越多,我就越傾向於使用WS Reliable Messaging。 [我也應該提到WS Atomic Transaction,它也可以用來構建可靠的服務,同樣的操作間問題也適用。]

那麼你自己怎麼樣?這裏的關鍵是要使所有服務都是冪等的。由於我們沒有跨越兩個系統的交易保證,因此我們必須假定任何給定的服務呼叫都可能會因未知結果而失敗。

我打算假設B想要確認S已經下了訂單,因此我們需要在訂單轉移時更新B和S的信息。所以

Give me the next order(s) 

I have stored {orders ...} 

我們如何定義 「下一步」:

B必須提供諸如這些。如果我們正在處理的卷可以讓我們有一個單一的「線程」轉移,最簡單的情況很好地工作。然後,B一次一個地發送已發送的訂單,並且訂單具有單調遞增的ID。我們可以簡化爲:

I have stored order <65,004> please give me the next 

請注意,這是一個冪等的請求:它可以安全地重複多次。另外請注意,S必須預期兩次獲得相同訂單的可能性,並檢查重複項。

+0

在e分佈式系統中,單調遞增的ID有些困難,但是我們可以額外添加:「我現在已經存儲了消息,可以刪除它」請求。 – max 2010-10-27 09:37:11

+0

++爲網絡服務 – 2010-11-09 16:43:17

+0

您能否給我一個「Web服務」的例子,WS- *堆棧似乎給我一個不兼容的複雜混亂,但這可能只是我缺乏經驗。我在哪裏可以找到Github上的WS- *的Ruby/Python/PHP/Perl庫? – max 2010-11-11 19:00:29

1

您可能正在尋找的是兩階段提交。它是在互聯網很好的描述,這裏例如:

http://en.wikipedia.org/wiki/Two-phase_commit_protocol

它的要點:

的提交過程如下:

* Phase 1 
     o Each participating resource manager coordinates local 
     operations and forces all log records out: 
     o If successful, respond "OK" 
     o If unsuccessful, either allow a time-out or respond "OOPS" 
* Phase 2 
     o If all participants respond "OK": 
      * Coordinator instructs participating resource managers to "COMMIT" 
      * Participants complete operation writing the log record 
       for the commit 
     o Otherwise: 
      * Coordinator instructs participating resource managers to "ROLLBACK" 
      * Participants complete their respective local undos 

應該對任何類型的數據工作。

+0

我認爲讓「另一端」實現(和測試)兩個階段的原子提交將是相當困難的。 – max 2010-11-03 22:26:30

1

好吧,首先你不能保證任何東西在一個不可靠的鏈接。 Two Generals' Problem證明了這對於確定性和非確定性協議。你所能做的就是將不可靠性降低到可接受的程度。

最簡單的方法是,在你的情況下,一旦服務器收到一個輪詢請求,它會發送x數量的回覆,全部使用相同的GUID。例如。

S: B, anything new? 
S: B, anything new? 
S: B, anything new? 
B: Yes, S, I need a jacket (order #123). 
S: B, anything new? 
B: Yes, S, I need a jacket (order #123). 
S: B, anything new? 
B: Yes, S, I need a jacket (order #123). 
S: B, anything new? 
B: Yes, S, I need a jacket (order #123). 
B: Yes, S, I need some shoes (order #124). 
S: B, anything new? 
B: Yes, S, I need a jacket (order #123). 
B: Yes, S, I need some shoes (order #124). 
S: B, anything new? 
B: Yes, S, I need some shoes (order #124). 
S: B, anything new? 
B: Yes, S, I need some shoes (order #124). 
... 

S可以收到大量郵件與訂單,但由於#與每個請求一起發送,這不是什麼大不了的事。如果我們之前錯過了,我們現在就得到它。如果我們沒有得到它,嗚呼!我們現在擁有它。系統工作!在我的示例中,您會注意到B發送消息5次。在現實的情況下,您可能會發送數百或數千次的消息,直到您獲得所需的可靠性。

現在上述解決方案是處理和帶寬密集型,但它確實工作。一個更聰明的方法是做TCP的工作:有一個三方握手。

S: Hello B. Are you there? -> SYN 
B: Hello S, yep I'm here. What's up? -> SYN+ACK 
S: Oh good, you're there. -> ACK 
S: B, anything new? 
B: Yes, S, I need a jacket (order #123). 

但HTTP ..已經這樣做。所以如果有什麼東西沒有到位,你會知道的。連接超時,連接斷開等。

現在,您可以在應用程序級別(輸入WS-ReliableMessaging)中重新編寫這些方案,但確實TCP已經可靠。對這些SOAP(ish)框架和人造協議(他們通常在HTTP之上工作)的一些批評者指責他們在更高級別的抽象層面上本質上重塑了輪子 - 輪子的問題。

底線是任何系統都可能失敗,包括可靠的消息傳遞系統。

就最終一致性而言,我想你可能會感到困惑。最終的一致性僅適用於分佈式存儲系統,在Write()之後,您可能無法確定性檢索Read()一段時間。這看起來並不像你的問題。我的意思是,我看到你在說什麼,但是在一個eventually consistent系統中,假設節點之間有可靠的(足夠的)連接。你不會做出這樣的假設(即使我認爲你應該...... TCP是相當可靠的)。

+0

有趣的評論。我所描述的確實可以模擬爲分佈式存儲系統 - 但是大多數分佈式系統都可以。想想看,你重複和參考TCP的方法正在攻擊錯誤的問題(可能我曾經笨拙地描述過)。在公司之間IP連接關閉(沒問題,只是重試),或者它工作。但後端系統經常停機,或者無法處理該非ASCII字符,或者對於超過35個字符的電子郵件地址有緩衝區溢出......所以更多的是關於「在正確的位置重試」。 – max 2010-11-03 22:30:28

1

建立在什麼,蒂娜提到。 Webservices將是上述問題的完美解決方案。 有些協議可以商定哪些可以定義記錄的數量。

S ---> D (Call a service which would list record keys) 
D----> S (provide xml of keys) 
S----> D (Request each of the records) 
D----> S (Submit record) 

在一個新的記錄條目的情況下,同步後製成,目的地可以調用部署在源服務,這會處理的新紀錄。

由於通信處理購買Web服務引擎,您不必擔心消息參數。爲了安全起見,可以添加SSL。

乾杯!

1

我認爲你試圖說B公司是被動參與者。 S(供應商)只需要能夠獲得所有B崗位的訂單(最終一致性)。但是B不需要也不關心S已經有什麼命令(不需要提交)。

如果公司B具有半精確時鐘,則可以使用日期作爲單調遞增的GUID,具體取決於事件的分辨率 - 無論如何您都不需要輪詢是否需要毫秒分辨率。你只使用B的時鐘,所以你不必擔心同步。如果B公佈所有訂單,S可以從最後一次停止的訂單中提取訂單。

我不確定您是否意味着最佳實踐或最佳折衷方案,以實現易於實施的系統。根據音量和響應時間,無論如何您都無需使其成爲動態系統。將訂單作爲文本文件(由時間戳命名)轉儲到由日期命名的目錄中,並將它們全部向下(或有選擇地)拉下。你甚至可以按小時或任何有意義的方式將它們存儲在目錄中。 HTTP GET是冪等的。

這可能很醜陋,但聽起來您並不認爲B公司會帶來太多複雜性。使用SSL和授權,它被鎖定並加密。

如果你不需要性能,簡單就沒有問題。你真的從複雜的協議中獲得了什麼?

+0

在分鐘左右的時間間隔內進行輪詢的好主意,從而削弱了時鐘同步的要求。 – max 2010-11-10 07:59:09

相關問題