2017-01-16 85 views
3

我們目前正在尋找RPC框架,但不幸的是我們無法找到任何具有信號功能但我們需要它。我們查看了gRPC,Apache Thrift,Cap-n-Proto,發現其中沒有一個人提供了像DBus那樣的開箱即用功能。值得一提的是,我們需要它作爲IPC。另外,我們需要監視另外一個套接字,一個用於RPC服務器,另一個用於另一個服務器。在DBus我們可以將它添加到glib的主循環中。我們的目標RPC必須允許這個。在DBus中是否有任何具有信號功能的RPC框架?

P.S. DBus並不是我們所需要的,因爲我們只需要客戶端 - 服務器體系結構而不是client-bus-daemon。

P.P.S.關於off-topic - 我在這個問題上什麼都沒有看到需要自以爲是的答案。答案應該包含事實而不是意見。

回答

6

信號可以通過幾種不同的方式在Cap'n Proto之上實現。對象

鏈有一個頭兒原RPC調用花很長的時間才能完成沒有問題。同一連接上的其他呼叫可以正常繼續,並且一次可以有多個未決呼叫。因此,接收信號的一種策略是在返回之前等待信號。

許多RPC系統支持掛電話,但有一個額外的挑戰:如果你有一個信號流,以及客戶端觀察流中的每個信號,然後事情就變得複雜,如果正在產生新的信號,這一點很重要客戶端比RPC更快地讀取它們。您需要爲每個客戶端保留一個緩衝區。但如果客戶死亡並停止提出請求會怎麼樣?現在,您需要某種超時後清除它。

與大多數其他RPC系統不同,Cap'n Proto支持即時生成新對象。因此,您可以將您的信號流表示爲一系列對象。例如:

struct MyPayload { ... } 

interface MyInterface { 
    subscribe @0() -> (firstSignal :Signal(MyPayload)); 
    # Subscribe to signals from this interface. 
} 

interface Signal(Type) { 
    # One signal in a stream of signals. Has a payload, and lets you 
    # wait for the next signal. 

    get @0() -> (value :Type); 
    # Gets the payload value of this signal. (Returns immediately.) 

    waitForNext @1() -> (nextSignal :Signal(Type)); 
    # Waits for the next signal in the sequence, returning a new 
    # `Signal` object representing it. 
} 

這極大地簡化了,因爲頭兒原服務器端狀態管理,儘快將自動調用每個對象的析構函數,因爲所有的客戶都表示,他們用它做(通過破壞客戶端參考,又名「放棄」它)。如果客戶端斷開連接,則其所有引用都將被隱式刪除。

回調

因爲頭兒原允許在兩個方向上的RPC調用(客戶端 - >服務器和服務器 - >客戶端),你可以實現一個「信號」或者發佈/使用回調訂閱機制:

struct MyPayload { ... } 

interface MyInterface { 
    subscribe @0 (cb :Callback(MyPayload)) -> (handle :Handle); 
} 

interface Callback(Type) { 
    call @0 (value :Type); 
} 

interface Handle {} 

客戶端調用subscribe()並傳遞迴調對象cb。然後,服務器可以隨時在發出信號時回撥給客戶端。

請注意subscribe()返回一個Handle,這是一個沒有方法的對象。這樣做的目的是檢測客戶何時退訂。如果客戶端丟棄handle,則會通知服務器(服務器端對象的析構函數將運行),然後服務器可以註銷回調。這也處理客戶端斷開連接的情況 - 所有對象引用都隱式地斷開連接。

乍一看,由於其簡單性,該解決方案可能看起來比鏈式對象解決方案好得多。但是,它有一個問題,即現在您的對象引用指向兩個方向,這可能導致循環。在客戶端代碼中,必須小心確保回調實現不「擁有」保持註冊的句柄,否則它永遠不會被清理(連接關閉時除外)。在等待服務器取消註冊回調的同時,您還必須確保在刪除句柄後短時間內仍可以調用回調。這些問題並沒有出現在對象鏈解決方案中,這可能會使解決方案的實施更加清晰。

其他RPC系統

我討論上面,因爲我是作家,是因爲它提供了比大多數RPC系統更多的選擇頭兒原。

如果你使用gRPC,你可以使用它的「流媒體」功能來支持類似信號的東西。流式RPC可以隨着時間的推移返回多個響應。

我不確定節儉。我最後一次嘗試它時,請求必須是FIFO,這意味着長時間運行的RPC是不可能的。然而,那是很久以前的事了,也許從那以後它就變了。

+0

你能否告訴我如果我不想在第一次接收到信號後取消註冊回調?你的意思是我應該在某處存儲'Handle'嗎? –

+0

@VictorPolevoy客戶應該把'Handle'保存在內存中,是的。雖然可能不會存儲到磁盤,因爲整個操作都與特定的實時網絡連接有關。如果連接死亡,那麼回調將不再起作用。客戶端需要重新連接並註冊新的回調。 –

+0

有沒有一種方法可以通過提供capnp數據緩衝區來解析從套接字接收的來自外部的套接字? –

相關問題