Saya baru mengenal Go dan sedang mencari cara yang benar untuk menggunakan net/http atau fasthttp dengan goroutine. Sayangnya tidak banyak contoh klien fasthttp di luar sana.

Saya menemukan kode berikut: (Contoh1)

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()
}

Dalam kode ini pengembang membuat instance fasthttp.Client dalam fungsi main() dan meneruskannya ke goroutine menggunakan go grabPage(c, ...). Untuk pemahaman saya, dengan cara ini Anda membuat satu instance dan semua permintaan menggunakan satu instance ini untuk melakukan pekerjaan itu.

Di laman lain, pengembang menggunakan sesuatu seperti itu: (Contoh2)

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)
}

Pertanyaan besarnya adalah, apakah kedua solusi itu benar? Atau apakah solusi Example2 benar-benar membuat instance baru dan menggunakan banyak memori untuk setiap goroutine?

Saya membuat contoh dari cuplikan untuk pertanyaan saya, di Example2 pasti defer tidak ada. Ini bukan bagian dari pertanyaan.

Sebuah pertanyaan sampingan kecil: (fastClient *fasthttp.Client, i int, wg *sync.WaitGroup) -> fastClient dan wg adalah pointer, jadi mengapa memanggil grabPage(c, index, &wg) dan bukan grabPage(&c, index, &wg)?

3
ChrisG 2 Juni 2020, 12:21

1 menjawab

Jawaban Terbaik

Jawaban besarnya: keduanya benar (karena keduanya berfungsi dengan baik), hanya berbeda.

Per dokumen, fasthttp.Client aman untuk penggunaan bersamaan sehingga berbagi satu contoh baik-baik saja. Ini mungkin mengalami batas koneksi bersamaan tetapi itu mungkin tidak menjadi masalah.

Contoh kedua memang memiliki beberapa overhead dan tidak akan dapat menggunakan kembali koneksi atau parameter, tetapi sekali lagi ini bisa menjadi kasus penggunaan yang tidak masalah (jika saya hanya melakukan dua operasi, menghemat overhead mungkin tidak layak untuk dioptimalkan) .

Untuk bagian kedua dari pertanyaan:

  • c sudah menjadi *fasthttp.Client, jadi tidak perlu mengambil alamatnya (&fasthttp.Client mengembalikan pointer ke fasthttp.Client baru)
  • wg adalah sync.WaitGroup biasa jadi alamat harus diambil
4
Marc 2 Juni 2020, 09:37