简体   繁体   English

正确使用 fasthttp.Client 结合 goroutines

[英]Correct use of fasthttp.Client combined with goroutines

I am new to Go and am looking for the correct way of using net/http or fasthttp with goroutines.我是 Go 的新手,正在寻找将net/httpfasthttp与 goroutine 一起使用的正确方法。 Unfortunately there are not many fasthttp client examples out there.不幸的是,没有很多fasthttp客户端示例。

I found the following code: ( Example1 )我找到了以下代码:( Example1

package main

import (
    "bufio"
    "fmt"
    "github.com/valyala/fasthttp"
    "log"
    "net"
    "os"
    "sync"
    "time"
)

func grabPage(fastClient *fasthttp.Client, i int, wg *sync.WaitGroup) {
    defer wg.Done()
    _, body, err := fastClient.GetTimeout(nil, "https://en.wikipedia.org/wiki/Immanuel_Kant", time.Duration(time.Second*20))
    if err != nil {
        log.Fatal(err)
    }
    f, err := os.Create(fmt.Sprintf("./data/%d.txt", i))
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()
    w := bufio.NewWriter(f)
    w.Write(body)
}

func main() {
    var wg sync.WaitGroup
    total := 500

    c := &fasthttp.Client{
        Dial: func(addr string) (net.Conn, error) {
            return fasthttp.DialTimeout(addr, time.Second*10)
        },
        MaxConnsPerHost: total,
    }

    wg.Add(total)
    for index := 0; index < total; index++ {
        go grabPage(c, index, &wg)
    }
    wg.Wait()
}

In this code the developer creates a fasthttp.Client instance in the main() function and passes it to the goroutine using go grabPage(c, ...) .在此代码中,开发人员在main() function 中创建了一个fasthttp.Client实例,并使用go grabPage(c, ...)将其传递给 goroutine。 For my understanding, this way you create one instance and all the requests use this one instance to do the job.据我了解,这样您创建一个实例,所有请求都使用这个实例来完成这项工作。

On another page, a developer uses something like that: ( Example2 )在另一个页面上,开发人员使用了类似的东西:( Example2

func grabPage(i int, wg *sync.WaitGroup) {
    defer wg.Done()

    fastClient := &fasthttp.Client{
        Dial: func(addr string) (net.Conn, error) {
            return fasthttp.DialTimeout(addr, time.Second*10)
        },
        MaxConnsPerHost: 500,
    }

    _, body, err := fastClient.GetTimeout(nil, "https://en.wikipedia.org/wiki/Immanuel_Kant", time.Duration(time.Second*20))
    if err != nil {
        log.Fatal(err)
    }
    f, err := os.Create(fmt.Sprintf("./data/%d.txt", i))
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()
    w := bufio.NewWriter(f)
    w.Write(body)
}

The big question is, are both solutions correct?最大的问题是,两种解决方案都正确吗? Or does the Example2 solution really create a new instance and use a lot of memory for every goroutine?还是 Example2 解决方案真的创建了一个新实例并为每个 goroutine 使用了大量的 memory?

I made the examples out of snippets for my question, in the Example2 for sure defer are missing.我为我的问题从片段中制作了示例,在 Example2 中肯定缺少defer This is not part of the question.这不是问题的一部分。

A small side question: (fastClient *fasthttp.Client, i int, wg *sync.WaitGroup) -> fastClient and wg are pointers, so why call grabPage(c, index, &wg) and not grabPage(&c, index, &wg) ?一个小问题: (fastClient *fasthttp.Client, i int, wg *sync.WaitGroup) -> fastClient 和 wg 是指针,所以为什么要调用grabPage(c, index, &wg)而不是grabPage(&c, index, &wg) ?

The big answer: both are correct (as in they work just fine), just different.大答案:两者都是正确的(因为它们工作得很好),只是不同。

Per the docs , a fasthttp.Client is safe for concurrent use so sharing one instance is fine.根据文档fasthttp.Client对于并发使用是安全的,因此共享一个实例很好。 It may run into concurrent connection limits but that might not be an issue.它可能会遇到并发连接限制,但这可能不是问题。

The second example does have some overhead and will not be able to reuse connections or parameters, but again this could be a use case where it does not matter (if I only perform two operations, saving on the overhead might not be worth optimizing for).第二个示例确实有一些开销,并且无法重用连接或参数,但这可能是一个无关紧要的用例(如果我只执行两个操作,节省开销可能不值得优化) .

For the second part of the question:对于问题的第二部分:

  • c is already a *fasthttp.Client , so there's not need to take its address ( &fasthttp.Client returns a pointer to a new fasthttp.Client ) c已经是一个*fasthttp.Client ,所以不需要获取它的地址( &fasthttp.Client返回一个指向新fasthttp.Client的指针)
  • wg is a plain sync.WaitGroup so the address must be taken wg是一个普通的sync.WaitGroup所以地址必须取

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM