在我的 Golang 項目中切換網絡名稱空間后,我在 GRPC 客戶端和服務器之間進行通信時遇到問題。為了解決這個問題,我相應地修改了GRPC示例程序Hello World,結果出現了同樣的問題。在 golang 應用程序中切換命名空間后使用 GRPC 時是否有任何已知限制?我已經閱讀了與在 Golang 中切換命名空間相關的問題,但我想這是否會導致問題取決于 GRPC 行為。GRPC 客戶端是否生成任何額外的 goroutines?由于命名空間切換,這樣的 goroutine 不一定會在與原始 goroutine 鎖定線程相同的命名空間中執行。我假設 GRPC 服務器為每個客戶端生成 goroutine,但它是否會在生成新 goroutine 之前在原始 goroutine 中創建套接字?這個問題也與生成的 goroutines 不必在調用 grpc.Serve() 的相同命名空間中執行有關(命名空間切換需要 runtime.LockOSThread())。如果服務器和客戶端在匹配的命名空間(ip netns exec ...)中啟動,則通信有效,但如果在客戶端內部執行命名空間切換,則通信失敗。在服務器內部執行名稱空間切換時通信也有效,因此問題應該在客戶端。greeter_client/main.go:package mainimport ( "fmt" "log" "os" "runtime" "syscall" "time" pb "grpctest/helloworld/helloworld" "github.com/vishvananda/netns" "golang.org/x/net/context" "google.golang.org/grpc")const ( defaultName = "world" defaultAddress = "localhost:50051" nsEnv = "NAMESPACE" addressEnv = "ADDRESS" blockEnv = "DIALBLOCK")func main() { fmt.Printf("* Client thread id before runtime.LockOSThread(): %d\n", syscall.Gettid()) runtime.LockOSThread() defer runtime.UnlockOSThread() fmt.Printf("* Client thread id after runtime.LockOSThread(): %d\n", syscall.Gettid()) var dialOpts []grpc.DialOption dialOpts = append(dialOpts, grpc.WithInsecure()) _, ok := os.LookupEnv(blockEnv) if ok == true { dialOpts = append(dialOpts, grpc.WithBlock()) fmt.Printf("* Dial in blocked mode\n") } else { fmt.Printf("* Dial in unblocked mode\n") } address, ok := os.LookupEnv(addressEnv) if ok == false { address = defaultAddress } fmt.Printf("* Talk to server at %s\n", address) var origns netns.NsHandle namespace, ok := os.LookupEnv(nsEnv) if ok { fmt.Printf("* Switch namespace to %s\n", namespace) origns, err := netns.Get() if err != nil { log.Fatal("failed to get current namespace") }
1 回答

慕雪6442864
TA貢獻1812條經驗 獲得超5個贊
我遇到了完全相同的問題,無論是否鎖定操作系統線程,netns 都會在每個新的 goroutine 上切換回原始名稱空間。
我發現只要服務器在正確的 netns 中啟動(我放棄了嘗試以編程方式執行此操作并只是通過生成服務器進程exec.Command),您只需為 GRPC 客戶端設置自定義撥號程序以在連接到正確的網絡:
dialOpts = append(dialOpts, grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
netns.Set(newns)
return net.DialTimeout("tcp", addr, timeout)
}))
- 1 回答
- 0 關注
- 176 瀏覽
添加回答
舉報
0/150
提交
取消