在我的 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 main
import (
"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")
}
慕雪6442864
相关分类