antara muka permintaan serentak golang

WBOY
Lepaskan: 2023-05-10 11:58:06
asal
1311 orang telah melayarinya

Bahasa Go ialah bahasa pengaturcaraan yang sangat sesuai untuk pengaturcaraan serentak Prestasinya digunakan dengan baik apabila melaksanakan perkhidmatan atau aplikasi konkurensi tinggi. Dalam pembangunan harian, kami mungkin menghadapi senario yang memerlukan antara muka permintaan serentak atau pemprosesan serentak sejumlah besar data Artikel ini akan memperkenalkan cara melaksanakan antara muka permintaan serentak dalam golang.

Senario antara muka permintaan serentak

Dalam pembangunan sebenar, kita mungkin menghadapi senario di mana kita perlu meminta antara muka dan mendapatkan data tindak balas, seperti:

  • Dapatkan produk data pada laman web.
  • Dapatkan data daripada antara muka API yang berbeza dan tunjukkannya dalam ringkasan.
  • Minta berbilang sumber data serentak untuk pengumpulan data yang cepat.

Dalam satu urutan, jika anda perlu meminta berbilang antara muka, anda perlu melengkapkan satu permintaan antara muka sebelum meminta antara muka lain, yang akan menyebabkan keseluruhan proses menjadi perlahan. Sebaliknya, menggunakan antara muka permintaan serentak boleh memulakan berbilang permintaan pada masa yang sama, meningkatkan kecekapan permintaan.

Pemprosesan Serentak Goroutine

Goroutine ialah fungsi khas dalam bahasa go yang boleh dijalankan dalam utas khas selari dengan utas utama. Berbilang goroutine berjalan pada masa yang sama boleh meminta berbilang antara muka pada masa yang sama, dan kemudian melaksanakan pemprosesan penyepaduan data selepas permintaan selesai. Penggunaan serentak goroutine agak mudah untuk dilaksanakan dan boleh dicapai melalui kata kunci pergi.

WaitGroup mengawal goroutine

Dalam pembangunan sebenar, kami mungkin mendapati bahawa sesetengah coroutine mungkin lebih memakan masa dan mungkin mengambil lebih banyak masa untuk mengembalikan hasil. Dalam kes ini, kita perlu menunggu coroutine mengembalikan hasilnya dan melakukan pemprosesan seterusnya. Pada masa ini, kita perlu menggunakan sync.WaitGroup untuk mengawal bilangan goroutine bagi memastikan semua permintaan menerima hasil respons.

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "sync"
)

var wg sync.WaitGroup // 声明一个sync.WaitGroup实例,用于协程控制

func main() {
    urls := []string{"https://www.baidu.com", "https://www.qq.com", "https://www.taobao.com", "https://www.jd.com", "https://www.mi.com"}

    // 通过遍历urls,启动goroutine
    for _, url := range urls {
        wg.Add(1) // 添加一个goroutine
        go getBody(url)
    }

    wg.Wait() // 等待所有goroutine结束
}

// getBody用于获取传入url的响应结果,并打印。
func getBody(url string) {
    resp, err := http.Get(url) // 发起http GET请求
    if err != nil {
        fmt.Println(err)
        return
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("url: %s, contents:
%s
", url, string(body))
    wg.Done() // 相当于wg.Add(-1),标志该goroutine已经结束
}
Salin selepas log masuk

Dalam kod di atas, kami mula-mula mengisytiharkan penyegerakan.WaitGroup contoh untuk mengawal bilangan coroutine. Kemudian, dalam fungsi main(), berbilang coroutine dimulakan dengan merentasi url Pada masa yang sama, setiap kali coroutine dimulakan, kaedah wg.Add(1) dipanggil, menunjukkan bahawa seseorang perlu menunggu coroutine untuk. lengkap. Dalam kes ini, bilangan coroutine menunggu yang direkodkan dalam WaitGroup akan menjadi bilangan url dalam url. Kemudian dalam baris go getBody(url), kami memulakan coroutine yang meminta URL, dan kemudian memanggil kaedah wg.Done() apabila coroutine tamat, menunjukkan bahawa coroutine telah tamat.

Akhir sekali, panggilan wg.Wait() menyebabkan coroutine utama menunggu sehingga semua coroutine selesai.

Amalan terbaik untuk permintaan serentak

Dalam pembangunan sebenar, kami perlu memberi perhatian kepada beberapa butiran, yang boleh membantu kami menggunakan antara muka permintaan serentak dengan lebih baik.

1. Kawalan bilangan mata wang

Apabila meminta antara muka secara serentak, kita perlu mengawal bilangan mata wang, terutamanya apabila bilangan permintaan antara muka agak besar, untuk mengelakkan satu- permintaan masa daripada menyebabkan terlalu banyak kerosakan pada pelayan. Kami boleh menetapkan nilai maksimum untuk memastikan bilangan mata wang tertinggi. Kita boleh menggunakan saluran penimbal dalam golang untuk mengawal bilangan mata wang maksimum.

ch := make(chan struct{}, 5) // 声明一个缓冲通道,大小为5,控制并发数量为5

for _, url := range urls {
    ch <- struct{}{} // 把协程数量放在通道里
    wg.Add(1)  // 添加一个goroutine
    go func(url string) {
        defer wg.Done()
        getBody(url)
        <-ch // 从通道里取出一个值,表示这个协程已经结束
    }(url)
}
Salin selepas log masuk

Dalam proses mengisytiharkan saluran penimbal, kami menetapkan saiz penimbal kepada 5, yang bermaksud sehingga 5 goroutine boleh dijalankan pada masa yang sama Kemudian kami melintasi url dan menambah nilai struktur ke saluran.

Apabila memulakan goroutine, kami mengisytiharkan func(url string) sebagai fungsi pemprosesan untuk mengelakkan bilangan maksimum goroutine berjalan pada masa yang sama melebihi 5, dan kemudian memanggil kaedah getBody(url). Apabila goroutine tamat, kami mengeluarkan isyarat melalui saluran, menunjukkan bahawa goroutine telah tamat - <-ch.

2. Elakkan permintaan menyekat

Apabila membuat antara muka permintaan serentak, kita perlu mengelakkan penyekatan permintaan, yang biasanya berlaku apabila permintaan tidak bertindak balas untuk masa yang lama. Kita boleh menyelesaikan masalah ini menggunakan konteks.Konteks di Golang. Jika permintaan tamat, batalkan permintaan yang disekat.

url := "https://httpstat.us/200?sleep=8000"

ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*5000) // 告诉请求,5秒之后自动取消

defer cancel()

req, err := http.NewRequestWithContext(ctx, "GET", url, nil) // 使用请求上下文

if err != nil {
    log.Fatal(err)
}

client := http.DefaultClient
resp, err := client.Do(req) // 发起请求
if err != nil {
    log.Fatal(err)
}

if resp.StatusCode == http.StatusOK {
    contents, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s
", contents)
}
Salin selepas log masuk

Dalam kod di atas, kami menggunakan kaedah context.WithTimeout untuk mencipta konteks permintaan dengan tamat masanya ditetapkan kepada 5 saat, seperti http://httpstat.us/200?sleep=8000, permintaan ini Ia mengambil masa 8 saat untuk mengembalikan data. Kami kemudian membuat permintaan menggunakan konteks permintaan menggunakan kaedah http.NewRequestWithContext. Apabila menghantar permintaan, kami menggunakan http.DefaultClient untuk memulakan permintaan. Akhir sekali, jika kod status respons ialah 200, data respons adalah output.

Apabila permintaan tamat, pautan permintaan akan ditutup terus. Pada masa ini kami akan digesa dengan ralat "tempoh akhir konteks melebihi".

3. Elakkan permintaan berulang

Apabila meminta antara muka, anda mungkin menghadapi permintaan berulang untuk antara muka yang sama masa dan sumber yang berharga. Kami boleh menyelesaikan masalah ini menggunakan penyegerakan.Peta di Golang.

var m = sync.Map{}

url := "https://httpbin.org/get"

wg.Add(2)
go doGet(url, &m, &wg)
go doGet(url, &m, &wg)

wg.Wait()

func doGet(url string, m *sync.Map, wg *sync.WaitGroup) {
    _, loaded := m.LoadOrStore(url, true) // 表示url已经被请求过,如果已存在,则直接返回,否则返回false并储存

    if loaded {
        fmt.Printf("url %s already requested.
", url)
        wg.Done()
        return
    }

    resp, err := http.Get(url)
    if err != nil {
        log.Fatal(err)
    }

    defer resp.Body.Close()
    contents, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s
", contents)
    wg.Done()
}
Salin selepas log masuk

Dalam kod di atas, kami menggunakan penyegerakan.Peta untuk memastikan bahawa url hanya diminta sekali. Dalam doGet coroutine, kami menggunakan m.LoadOrStore(url, true) untuk menentukan sama ada url telah diminta Jika ia telah diminta, return keluar terus dari coroutine. Jika tidak, kami memulakan permintaan http.Get dan mencetak data respons dalam log. Akhir sekali, kami menggunakan kaedah wg.Done() untuk menandakan coroutine telah tamat.

Ringkasan

Artikel ini memperkenalkan cara menggunakan golang untuk melaksanakan antara muka permintaan serentak. Kawal bilangan mata wang dengan menggunakan pemprosesan serentak goroutine, kawalan coroutine WaitGroup dan saluran penimbal. Elakkan penyekatan permintaan dengan menetapkan tamat masa dalam konteks permintaan dan gunakan sync.Map untuk mengelakkan pertindihan permintaan. Dengan menggunakan teknologi ini, kami boleh meningkatkan kecekapan antara muka permintaan, meningkatkan kecekapan pengekodan dan pengalaman pengaturcaraan.

Atas ialah kandungan terperinci antara muka permintaan serentak golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!