我計劃提供兩項服務。用 Ruby 編寫的 HTTP REST 服務用 Go 編寫的 JSON RPC 服務Ruby 服務將打開一個到 Go JSON RPC 服務的 TCP 套接字連接。它將為收到的每個傳入 HTTP 請求執(zhí)行此操作。它將通過套接字向 Go 服務發(fā)送一些數(shù)據(jù),該服務隨后將相應的數(shù)據(jù)發(fā)送回套接字。去代碼Go 服務 go 看起來像這樣(簡化):srv := new(service.App) // this would expose a Process methodrpc.Register(srv)listener, err := net.Listen("tcp", ":8080")if err != nil { // handle error}for { conn, err := listener.Accept() if err != nil { // handle error } go jsonrpc.ServeConn(conn)}請注意,我們使用 goroutine 為傳入連接提供服務,因此我們可以并發(fā)處理請求。紅寶石代碼下面是一段簡單的 Ruby 代碼片段,它演示了(理論上)我將數(shù)據(jù)發(fā)送到 Go 服務的方式:require "socket"require "json"socket = TCPSocket.new "localhost", "8080"b = { :method => "App.Process", :params => [{ :Config => JSON.generate({ :foo => :bar }) }], :id => "0"}socket.write(JSON.dump(b))response = JSON.load socket.readline我擔心的是:這會是一個安全的事件序列嗎?我不是在問這是否是“線程安全的”,因為我不擔心跨 go 例程操縱共享內(nèi)存。我更關心我的 Ruby HTTP 服務是否會取回它期望的數(shù)據(jù)?如果我有兩個并行請求進入我的 HTTP 服務(或者 Ruby 應用程序托管在負載均衡器之后,因此HTTP 服務的不同實例正在處理多個請求),那么我可以讓實例 A 將消息 Foo 發(fā)送到 Go服務; 而實例 B 發(fā)送消息 Bar。Go 服務內(nèi)部的業(yè)務邏輯將根據(jù)其輸入返回不同的響應,因此我想確保 Ruby 實例 A 為 Foo 返回正確的響應,而 B 為 Bar 返回正確的響應。我假設套接字連接更像是一個隊列,因為如果實例 A 先向 Go 服務發(fā)出請求,然后B 這樣做,但 B 無論出于何種原因響應更快,那么 Go 服務會將 B 的響應寫入套接字并且 Ruby 應用程序的實例 A 最終將讀取錯誤的套接字數(shù)據(jù)(這顯然只是一種可能的情況,因為我可能很幸運并且讓實例 B 在實例 A 之前讀取了套接字數(shù)據(jù))。解決方案?我不確定這個問題是否有簡單的解決方案。除非我不使用 TCP 套接字或 RPC 而是依賴 Go 服務中的標準 HTTP。但我想要 TCP 的性能和更少的開銷。我擔心設計可能會變得更加復雜,因為可能必須實現(xiàn)一個外部隊列作為與 Ruby 服務同步響應的一種方式??赡苁且驗槲业?Ruby 服務本質(zhì)上是同步的(HTTP 響應/請求),所以我別無選擇,只能為 Go 服務切換到 HTTP。但是我想先與社區(qū)進行仔細檢查,以防萬一我遺漏了一些明顯的東西。
1 回答

HUX布斯
TA貢獻1876條經(jīng)驗 獲得超6個贊
是的,如果您每次都創(chuàng)建一個新連接,這是安全的。
也就是說,您的方法存在潛在問題:
TCP 連接建立起來相當昂貴,因此您可能希望通過連接池重用連接
如果您同時發(fā)出太多請求,您將耗盡端口/打開文件描述符,這將導致您的程序崩潰
您沒有任何超時,因此最終可能會出現(xiàn)永遠無法完成的孤立 TCP 連接(由于 Go 方面的問題或網(wǎng)絡問題)
我認為最好使用 HTTP(盡管有開銷),因為已經(jīng)編寫了庫來處理這些問題。HTTP 也更易于調(diào)試,因為您只需 curl 一個端點來測試它。
我個人可能會選擇gRPC。
- 1 回答
- 0 關注
- 138 瀏覽
添加回答
舉報
0/150
提交
取消