


Goroutine bocor apabila mencuba `ReadAll(response.Body)` di mana `response` dikembalikan oleh http `client.Do(...)`
Editor PHP Baicao menemui kebocoran goroutine biasa semasa menyelesaikan masalah pengaturcaraan. Apabila kami cuba menggunakan `ReadAll(response.Body)`, objek `response` dikembalikan oleh kaedah `client.Do(...)` bagi pakej `http`. Walau bagaimanapun, operasi ini boleh menyebabkan masalah kebocoran goroutine. Untuk mengelakkan perkara ini berlaku, kami perlu mengambil beberapa langkah untuk mengendalikan respons http dengan betul.
Kandungan soalan
Soalan ini datang daripada senario yang sangat biasa di mana semua bait dibaca daripada badan respons selepas panggilan kaedah http.
Dengan bantuan https://github.com/uber-go/goleak, saya menemui kebocoran goroutine yang menarik.
Untuk menunjukkan masalah, gunakan go test
运行以下测试代码,这会导致 found 出现意外的 goroutine
:
package main import ( "io" "net/http" "testing" "go.uber.org/goleak" "gotest.tools/v3/assert" ) func testleak(t *testing.t) { defer goleak.verifynone(t) request, err := http.newrequest(http.methodget, "https://google.com", nil) assert.nilerror(t, err) client := http.client{} response, err := client.do(request) assert.nilerror(t, err) defer response.body.close() _, err = io.readall(response.body) assert.nilerror(t, err) }
Keluaran ujian penuh:
$ go test --- FAIL: TestLeak (1.26s) main_test.go:28: found unexpected goroutines: [Goroutine 14 in state IO wait, with internal/poll.runtime_pollWait on top of the stack: goroutine 14 [IO wait]: internal/poll.runtime_pollWait(0x7f945c1e0398, 0x72) /home/wxh/.local/go/src/runtime/netpoll.go:305 +0x89 internal/poll.(*pollDesc).wait(0xc000154280?, 0xc0000ca000?, 0x0) /home/wxh/.local/go/src/internal/poll/fd_poll_runtime.go:84 +0x32 internal/poll.(*pollDesc).waitRead(...) /home/wxh/.local/go/src/internal/poll/fd_poll_runtime.go:89 internal/poll.(*FD).Read(0xc000154280, {0xc0000ca000, 0x2000, 0x2000}) /home/wxh/.local/go/src/internal/poll/fd_unix.go:167 +0x25a net.(*netFD).Read(0xc000154280, {0xc0000ca000?, 0xc00017edd8?, 0xc0004d5808?}) /home/wxh/.local/go/src/net/fd_posix.go:55 +0x29 net.(*conn).Read(0xc00009c000, {0xc0000ca000?, 0xc0000c68f0?, 0x2c?}) /home/wxh/.local/go/src/net/net.go:183 +0x45 crypto/tls.(*atLeastReader).Read(0xc0002d4138, {0xc0000ca000?, 0x0?, 0x29f6540f238f2947?}) /home/wxh/.local/go/src/crypto/tls/conn.go:787 +0x3d bytes.(*Buffer).ReadFrom(0xc0000a0278, {0x7c3860, 0xc0002d4138}) /home/wxh/.local/go/src/bytes/buffer.go:202 +0x98 crypto/tls.(*Conn).readFromUntil(0xc0000a0000, {0x7c3b80?, 0xc00009c000}, 0xc0000a41c0?) /home/wxh/.local/go/src/crypto/tls/conn.go:809 +0xe5 crypto/tls.(*Conn).readRecordOrCCS(0xc0000a0000, 0x0) /home/wxh/.local/go/src/crypto/tls/conn.go:616 +0x116 crypto/tls.(*Conn).readRecord(...) /home/wxh/.local/go/src/crypto/tls/conn.go:582 crypto/tls.(*Conn).Read(0xc0000a0000, {0xc0001cf000, 0x1000, 0x11?}) /home/wxh/.local/go/src/crypto/tls/conn.go:1287 +0x16f bufio.(*Reader).Read(0xc0001af1a0, {0xc0001aad60, 0x9, 0xc0004d5d18?}) /home/wxh/.local/go/src/bufio/bufio.go:237 +0x1bb io.ReadAtLeast({0x7c3760, 0xc0001af1a0}, {0xc0001aad60, 0x9, 0x9}, 0x9) /home/wxh/.local/go/src/io/io.go:332 +0x9a io.ReadFull(...) /home/wxh/.local/go/src/io/io.go:351 net/http.http2readFrameHeader({0xc0001aad60?, 0x9?, 0xc0004d5df0?}, {0x7c3760?, 0xc0001af1a0?}) /home/wxh/.local/go/src/net/http/h2_bundle.go:1565 +0x6e net/http.(*http2Framer).ReadFrame(0xc0001aad20) /home/wxh/.local/go/src/net/http/h2_bundle.go:1829 +0x95 net/http.(*http2clientConnReadLoop).run(0xc0004d5f98) /home/wxh/.local/go/src/net/http/h2_bundle.go:8875 +0x130 net/http.(*http2ClientConn).readLoop(0xc00009e180) /home/wxh/.local/go/src/net/http/h2_bundle.go:8771 +0x6f created by net/http.(*http2Transport).newClientConn /home/wxh/.local/go/src/net/http/h2_bundle.go:7478 +0xaaa Goroutine 37 in state IO wait, with internal/poll.runtime_pollWait on top of the stack: goroutine 37 [IO wait]: internal/poll.runtime_pollWait(0x7f945c1e02a8, 0x72) /home/wxh/.local/go/src/runtime/netpoll.go:305 +0x89 internal/poll.(*pollDesc).wait(0xc0003ca000?, 0xc000202000?, 0x0) /home/wxh/.local/go/src/internal/poll/fd_poll_runtime.go:84 +0x32 internal/poll.(*pollDesc).waitRead(...) /home/wxh/.local/go/src/internal/poll/fd_poll_runtime.go:89 internal/poll.(*FD).Read(0xc0003ca000, {0xc000202000, 0x1300, 0x1300}) /home/wxh/.local/go/src/internal/poll/fd_unix.go:167 +0x25a net.(*netFD).Read(0xc0003ca000, {0xc000202000?, 0xc0004e6798?, 0xc0004c0808?}) /home/wxh/.local/go/src/net/fd_posix.go:55 +0x29 net.(*conn).Read(0xc000014028, {0xc000202000?, 0xc000136630?, 0x2c?}) /home/wxh/.local/go/src/net/net.go:183 +0x45 crypto/tls.(*atLeastReader).Read(0xc000276288, {0xc000202000?, 0x0?, 0x150fbb8ccb566149?}) /home/wxh/.local/go/src/crypto/tls/conn.go:787 +0x3d bytes.(*Buffer).ReadFrom(0xc0000a0978, {0x7c3860, 0xc000276288}) /home/wxh/.local/go/src/bytes/buffer.go:202 +0x98 crypto/tls.(*Conn).readFromUntil(0xc0000a0700, {0x7c3b80?, 0xc000014028}, 0xc0004cc2c0?) /home/wxh/.local/go/src/crypto/tls/conn.go:809 +0xe5 crypto/tls.(*Conn).readRecordOrCCS(0xc0000a0700, 0x0) /home/wxh/.local/go/src/crypto/tls/conn.go:616 +0x116 crypto/tls.(*Conn).readRecord(...) /home/wxh/.local/go/src/crypto/tls/conn.go:582 crypto/tls.(*Conn).Read(0xc0000a0700, {0xc00023c000, 0x1000, 0x11?}) /home/wxh/.local/go/src/crypto/tls/conn.go:1287 +0x16f bufio.(*Reader).Read(0xc00022a2a0, {0xc00020e2e0, 0x9, 0xc0004c0d18?}) /home/wxh/.local/go/src/bufio/bufio.go:237 +0x1bb io.ReadAtLeast({0x7c3760, 0xc00022a2a0}, {0xc00020e2e0, 0x9, 0x9}, 0x9) /home/wxh/.local/go/src/io/io.go:332 +0x9a io.ReadFull(...) /home/wxh/.local/go/src/io/io.go:351 net/http.http2readFrameHeader({0xc00020e2e0?, 0x9?, 0xc0004c0df0?}, {0x7c3760?, 0xc00022a2a0?}) /home/wxh/.local/go/src/net/http/h2_bundle.go:1565 +0x6e net/http.(*http2Framer).ReadFrame(0xc00020e2a0) /home/wxh/.local/go/src/net/http/h2_bundle.go:1829 +0x95 net/http.(*http2clientConnReadLoop).run(0xc0004c0f98) /home/wxh/.local/go/src/net/http/h2_bundle.go:8875 +0x130 net/http.(*http2ClientConn).readLoop(0xc00019e300) /home/wxh/.local/go/src/net/http/h2_bundle.go:8771 +0x6f created by net/http.(*http2Transport).newClientConn /home/wxh/.local/go/src/net/http/h2_bundle.go:7478 +0xaaa ] FAIL exit status 1
Ada sesiapa tahu bagaimana untuk menyelesaikan masalah ini?
Terima kasih!
Penyelesaian
In Go, http.Client menggunakan Transport (http.RoundTripper antara muka). http.Transport ialah pelaksanaan lalainya. http.Transfer lalai mengekalkan kumpulan sambungan yang memegang sambungan yang kekal aktif atau melahu atas sebab tertentu.
Pada asasnya, apa yang anda perlu lakukan ialah memastikan tiada sambungan di kolam semasa memanggil goleak.Sahkan*
Ini boleh dilakukan dengan:
-
Lumpuhkan keep-alive untuk semua pelanggan http sebelum melaksanakan sebarang permintaan:
client := http.Client{Transport: &http.Transport{DisableKeepAlive: true}}
-
Tutup sambungan melahu * sebelum memanggil goleak.Sahkan:
client.CloseIdleConnections()
// Tersedia sejak Go 1.12
Atas ialah kandungan terperinci Goroutine bocor apabila mencuba `ReadAll(response.Body)` di mana `response` dikembalikan oleh http `client.Do(...)`. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



OpenSSL, sebagai perpustakaan sumber terbuka yang digunakan secara meluas dalam komunikasi yang selamat, menyediakan algoritma penyulitan, kunci dan fungsi pengurusan sijil. Walau bagaimanapun, terdapat beberapa kelemahan keselamatan yang diketahui dalam versi sejarahnya, yang sebahagiannya sangat berbahaya. Artikel ini akan memberi tumpuan kepada kelemahan umum dan langkah -langkah tindak balas untuk OpenSSL dalam sistem Debian. Debianopenssl yang dikenal pasti: OpenSSL telah mengalami beberapa kelemahan yang serius, seperti: Kerentanan Pendarahan Jantung (CVE-2014-0160): Kelemahan ini mempengaruhi OpenSSL 1.0.1 hingga 1.0.1f dan 1.0.2 hingga 1.0.2 versi beta. Penyerang boleh menggunakan kelemahan ini untuk maklumat sensitif baca yang tidak dibenarkan di pelayan, termasuk kunci penyulitan, dll.

Artikel ini menerangkan cara menggunakan alat PPROF untuk menganalisis prestasi GO, termasuk membolehkan profil, mengumpul data, dan mengenal pasti kesesakan biasa seperti CPU dan isu memori.

Artikel ini membincangkan ujian unit menulis di GO, meliputi amalan terbaik, teknik mengejek, dan alat untuk pengurusan ujian yang cekap.

Masalah Threading Giliran di GO Crawler Colly meneroka masalah menggunakan Perpustakaan Colly Crawler dalam bahasa Go, pemaju sering menghadapi masalah dengan benang dan permintaan beratur. � ...

Perpustakaan yang digunakan untuk operasi nombor terapung dalam bahasa Go memperkenalkan cara memastikan ketepatannya ...

Artikel ini memperkenalkan pelbagai kaedah dan alat untuk memantau pangkalan data PostgreSQL di bawah sistem Debian, membantu anda memahami pemantauan prestasi pangkalan data sepenuhnya. 1. Gunakan PostgreSQL untuk membina pemantauan PostgreSQL sendiri menyediakan pelbagai pandangan untuk pemantauan aktiviti pangkalan data: PG_STAT_ACTIVITY: Memaparkan aktiviti pangkalan data dalam masa nyata, termasuk sambungan, pertanyaan, urus niaga dan maklumat lain. PG_STAT_REPLITI: Memantau status replikasi, terutamanya sesuai untuk kluster replikasi aliran. PG_STAT_DATABASE: Menyediakan statistik pangkalan data, seperti saiz pangkalan data, masa komitmen/masa rollback transaksi dan petunjuk utama lain. 2. Gunakan alat analisis log pgbadg

Artikel ini membincangkan perintah Go FMT dalam pengaturcaraan GO, yang format kod untuk mematuhi garis panduan gaya rasmi. Ia menyoroti kepentingan GO FMT untuk mengekalkan konsistensi kod, kebolehbacaan, dan mengurangkan perdebatan gaya. Amalan terbaik untuk

Laluan Pembelajaran Backend: Perjalanan Eksplorasi dari Front-End ke Back-End sebagai pemula back-end yang berubah dari pembangunan front-end, anda sudah mempunyai asas Nodejs, ...
