Golang监听多个端口的UDP连接时,与BigTable连接会发生阻塞。

huangapple go评论89阅读模式
英文:

Golang listenUDP multiple ports blocking with BigTable connection

问题

我正在创建一个简单的UDP客户端,它监听多个端口并将请求保存到Bigtable中。

在提问之前,监听不同的端口非常重要。

在我包含Bigtable之前,一切都运行得很好。但是在包含Bigtable之后,监听器完全阻塞。

我简化了没有Bigtable的代码,如下所示:

func flow(port string) {

    protocol := "udp"
    udpAddr, err := net.ResolveUDPAddr(protocol, "0.0.0.0:"+port)
    if err != nil {
        fmt.Println("Wrong Address")
        return
    }

    udpConn, err := net.ListenUDP(protocol, udpAddr)
    if err != nil {
        fmt.Println(err)
    }
    defer udpConn.Close()

    for {
        Publish(udpConn, port)
    }
}

func main() {

    fmt.Print("Starting server.........")
    for i := *Start; i <= *End; i++ {
        x := strconv.Itoa(i)
        go flow(x)
    }
}

这段代码运行良好,但是一旦我添加了以下Bigtable的代码,整个程序就会阻塞。如果我删除创建监听器的go例程(这意味着我不能在多个端口上监听),它就能正常工作。

func createBigTable() {
    ctx := context.Background()

    client, err := bigtable.NewClient(ctx, *ProjectID, *Instance)
    if err != nil {
        log.Fatal("Bigtable NewClient:", err)
    }

    Table = client.Open("x")

}

我通过在createBigTable函数中添加一个查询来使其工作,但程序后面仍然会阻塞。

我不知道这是否是Bigtable、gRPC还是我的实现方式的问题。

非常感谢您提供有关如何修复的建议。

--- 更新 ---

我发现问题不仅仅出现在Bigtable上,当我调用gcloud pubsub时也会出现相同的问题。

--- 更新2 ---

createBigtable在init函数中被调用(在主函数之前):

func init() {
    createBigTable()
}

--- 更新3 ---

sigquit的输出可以在此处找到:

https://pastebin.com/fzixqmiA

英文:

I'm creating a simple udp client that listens on multiple ports and saves the request to bigtable.

It's essential to listen on different ports before you ask.

Everything was working nicely until I included bigtable. After doing so, the listeners block completely.

My stripped down code, without bigtable, looks like this:

func flow(port string) {

	protocol := &quot;udp&quot;
	udpAddr, err := net.ResolveUDPAddr(protocol, &quot;0.0.0.0:&quot;+port)
	if err != nil {
		fmt.Println(&quot;Wrong Address&quot;)
		return
	}

	udpConn, err := net.ListenUDP(protocol, udpAddr)
	if err != nil {
		fmt.Println(err)
	}
	defer udpConn.Close()

	for {
		Publish(udpConn, port)
	}
}

func main() {
    
	fmt.Print(&quot;Starting server.........&quot;)
	for i := *Start; i &lt;= *End; i++ {
		x := strconv.Itoa(i)
		go flow(x)
	}
}

This works fine however, as soon as I add the following for bigtable, the whole thing blocks. If I remove the go routine that creates the listener (which means I can't listen on multiple ports) it works.

func createBigTable() {
	ctx := context.Background()

	client, err := bigtable.NewClient(ctx, *ProjectID, *Instance)
	if err != nil {
		log.Fatal(&quot;Bigtable NewClient:&quot;, err)
	}

	Table = client.Open(&quot;x&quot;)

}

I managed to get it working by adding a query in the createBigTable func but the program still blocks later on.

I have no idea if this is an issue with bigtable, grpc or just the way I'm doing it.

Would really appreciate some advise about how to fix.

--- UPDATE ---

I've discovered the issue isn't just with BigTable - I also have the same issue when I call gcloud pubsub.

--- UPDATE 2 ---

createBigtable is called in the init function (BEFORE THE MAIN FUNCTION):

func init() {
    createBigTable
}

--- Update 3 ---

Output from sigquit can be found here:

https://pastebin.com/fzixqmiA

答案1

得分: 0

在你的示例中,你使用for {}来使服务器永远运行。这似乎会导致goroutine永远无法运行。尝试使用WaitGroup来从main()例程中释放控制权,并让flow()例程处理传入的UDP数据包。

import (
    ...
    "sync"
    ...
)

...

func main() {
    fmt.Print("Starting server.")
    for i := *Start; i <= *End; i++ {
        x := strconv.Itoa(i)
        go flow(x)
    }

    var wg sync.WaitGroup
    wg.Add(1)
    wg.Wait()
}

请注意,这只是一个示例代码片段,你需要根据你的实际需求进行适当的修改。

英文:

In your playground example, you're using for {} to keep the server running for forever.
This seems to deprive the goroutines from ever getting to run.
Try using e.g. a WaitGroup to yield control from the main() routine and let the flow() routines handle the incoming UDP packets.

import (
    ...
    &quot;sync&quot;
    ...
)

...

func main() {

    fmt.Print(&quot;Starting server.&quot;)
	for i := *Start; i &lt;= *End; i++ {
		x := strconv.Itoa(i)
		go flow(x)
	}

	var wg sync.WaitGroup
	wg.Add(1)
	wg.Wait()
}

huangapple
  • 本文由 发表于 2017年7月3日 03:57:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/44874705.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定