在 Golang 中设置网络命名空间后运行 GRPC 时是否有任何已知限制?

在我的 Golang 项目中切换网络名称空间后,我在 GRPC 客户端和服务器之间进行通信时遇到问题。为了解决这个问题,我相应地修改了GRPC示例程序Hello World,结果出现了同样的问题。在 golang 应用程序中切换命名空间后使用 GRPC 时是否有任何已知限制?

我已经阅读了与在 Golang 中切换命名空间相关的问题,但我想这是否会导致问题取决于 GRPC 行为。

  1. GRPC 客户端是否生成任何额外的 goroutines?由于命名空间切换,这样的 goroutine 不一定会在与原始 goroutine 锁定线程相同的命名空间中执行。

  2. 我假设 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")

        }



互换的青春
浏览 132回答 1
1回答

慕雪6442864

我遇到了完全相同的问题,无论是否锁定操作系统线程,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)    }))
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go