


Mari kita bincangkan tentang mekanisme tamat masa HttpClient Golang sendiri
Dalam proses menulis Go, saya sering membandingkan ciri-ciri dua bahasa yang telah saya pijak dan menemui banyak tempat menarik Dalam artikel ini, saya akan bercakap tentang mekanisme tamat masa HttpClient yang disertakan dengan Go. Saya harap Bermanfaat kepada semua orang.
Prinsip asas tamat masa Java HttpClient
Sebelum memperkenalkan mekanisme tamat masa HttpClient Go, mari kita lihat dahulu Java Bagaimana untuk melaksanakan tamat masa. [Cadangan berkaitan: Pergi tutorial video]
Tulis HttpClient asli Java, dan tetapkan tamat masa sambungan dan baca tamat masa yang sepadan dengan kaedah asas:
Berbalik kepada kod sumber JVM, saya mendapati bahawa ia adalah enkapsulasi panggilan sistem Malah, bukan sahaja Java, kebanyakan bahasa pengaturcaraanmenggunakan keupayaan tamat masa yang disediakan oleh sistem pengendalian.
Namun, Go's HttpClient menyediakan satu lagi mekanisme tamat masa, yang agak menarik Mari kita lihat. Tetapi sebelum kita bermula, mari kita fahami Konteks Go terlebih dahulu.
Pengenalan kepada Konteks Go
Apakah Konteks?
Menurut ulasan dalam kod sumber Go:
// Konteks membawa tarikh akhir, isyarat pembatalan dan nilai lain di seluruh // Sempadan API. // Kaedah konteks mungkin dipanggil oleh berbilang goroutin secara serentak.
Konteks hanyalah antara muka yang boleh membawa tamat masa, isyarat pembatalan dan data lain akan dipanggil oleh berbilang goroutin secara serentak.
Konteks agak serupa dengan ThreadLocal Java Ia boleh menghantar data dalam urutan, tetapi ia tidak sama persis, manakala ThreadLocal ialah pemindahan tersirat juga boleh menjalankan tamat masa, isyarat Batal.
Konteks hanya mentakrifkan antara muka dan beberapa pelaksanaan khusus disediakan dalam Go:
- Latar belakang: pelaksanaan kosong, tidak melakukan apa-apa
- TODO: Saya tidak tahu apa Konteks untuk digunakan lagi, jadi saya akan menggunakan TODO sebaliknya, yang merupakan Konteks kosong yang tidak melakukan apa-apa Untuk tiga ciri Konteks, anda boleh mengetahui lebih lanjut tentang pelaksanaan Konteks yang disediakan oleh Go dan contoh dalam sumber. kod.
- Konteks Tiga contoh ciri
Contoh dalam bahagian ini datang daripada kod sumber Go, terletak di Untuk membawa data
src/context/example_test.go
gunakan
untuk mendapatkan nilai Contoh dalam kod sumber adalah seperti berikut:
Batalcontext.WithValue
Value
// 来自 src/context/example_test.go func ExampleWithValue() { type favContextKey string f := func(ctx context.Context, k favContextKey) { if v := ctx.Value(k); v != nil { fmt.Println("found value:", v) return } fmt.Println("key not found:", k) } k := favContextKey("language") ctx := context.WithValue(context.Background(), k, "Go") f(ctx, k) f(ctx, favContextKey("color")) // Output: // found value: Go // key not found: color }
dan kemudian jana acara boleh dibatalkan melalui
Konteks, masukkan kaedah, sehingga ctx.Done()
mengembalikan 5, panggil
// 来自 src/context/example_test.go gen := func(ctx context.Context) <-chan int { dst := make(chan int) n := 1 go func() { for { select { case <-ctx.Done(): return // returning not to leak the goroutine case dst <- n: n++ } } }() return dst }
context.WithCancel
gen
Nampaknya ia boleh difahami secara ringkas sebagai membenamkan bendera akhir dalam gelung satu coroutine, dan coroutine lain menetapkan bendera akhir. gen
cancel
gen
Tamat masa
// 来自 src/context/example_test.go ctx, cancel := context.WithCancel(context.Background()) defer cancel() // cancel when we are finished consuming integers for n := range gen(ctx) { fmt.Println(n) if n == 5 { break } } // Output: // 1 // 2 // 3 // 4 // 5
Dengan bayangan awal pembatalan, tamat masa mudah difahami Pembatalan adalah pembatalan manual dan tamat masa adalah pembatalan automatik selagi coroutine yang dijadualkan dimulakan , Hanya laksanakan batal selepas masa.
Terdapat dua cara untuk menetapkan tamat masa: dan , WithTimeout ditetapkan selepas tempoh masa, WithDeadline ditetapkan kepada tarikh akhir dan WithTimeout akhirnya akan ditukar kepada WithDeadline.
Satu lagi mekanisme tamat masa Go HttpClient context.WithTimeout
context.WithDeadline
// 来自 src/context/example_test.go func ExampleWithTimeout() { // Pass a context with a timeout to tell a blocking function that it // should abandon its work after the timeout elapses. ctx, cancel := context.WithTimeout(context.Background(), shortDuration) defer cancel() select { case <-time.After(1 * time.Second): fmt.Println("overslept") case <-ctx.Done(): fmt.Println(ctx.Err()) // prints "context deadline exceeded" } // Output: // context deadline exceeded }
Pengenalan kepada mekanisme tamat masa
Lihat arahan konfigurasi tamat masa HttpClient Go: Terjemah ulasan: Termasuk masa untuk menyambung, mengubah hala dan membaca data Pemasa akan mengganggu bacaan data selepas masa tamat masa Jika ditetapkan kepada 0, tiada had tamat masa.
Maksudnya, tamat masa ini ialah
tamat masa keseluruhan permintaanclient := http.Client{ Timeout: 10 * time.Second, } // 来自 src/net/http/client.go type Client struct { // ... 省略其他字段 // Timeout specifies a time limit for requests made by this // Client. The timeout includes connection time, any // redirects, and reading the response body. The timer remains // running after Get, Head, Post, or Do return and will // interrupt reading of the Response.Body. // // A Timeout of zero means no timeout. // // The Client cancels requests to the underlying Transport // as if the Request's Context ended. // // For compatibility, the Client will also use the deprecated // CancelRequest method on Transport if found. New // RoundTripper implementations should use the Request's Context // for cancellation instead of implementing CancelRequest. Timeout time.Duration }
Timeout
Ini mungkin pilihan yang lebih baik untuk pengguna Dalam kebanyakan senario, pengguna tidak perlu mengambil berat tentang bahagian mana yang menyebabkan tamat masa, tetapi hanya ingin tahu bila permintaan HTTP secara keseluruhan boleh dikembalikan.
Prinsip asas mekanisme tamat masa
Menggunakan contoh paling mudah untuk menggambarkan prinsip asas mekanisme tamat masa. 这里我起了一个本地服务,用 Go HttpClient 去请求,超时时间设置为 10 分钟,建议使 Debug 时设置长一点,否则可能超时导致无法走完全流程。 这里返回的 stopTimer 就是可以手动 cancel 的方法,didTimeout 是判断是否超时的方法。这两个可以理解为回调方法,调用 stopTimer() 可以手动 cancel,调用 didTimeout() 可以返回是否超时。 设置的主要代码其实就是将请求的 Context 替换为 cancelCtx,后续所有的操作都将携带这个 cancelCtx: 同时,再起一个定时器,当超时时间到了之后,将 timedOut 设置为 true,再调用 doCancel(),doCancel() 是调用真正 RoundTripper (代表一个 HTTP 请求事务)的 CancelRequest,也就是取消请求,这个跟实现有关。 Go 默认 RoundTripper CancelRequest 实现是关闭这个连接 代码的开头监听 ctx.Done,如果超时则直接返回,使用 for 循环主要是为了请求的重试。 后续的 getConn 是阻塞的,代码比较长,挑重点说,先看看有没有空闲连接,如果有则直接返回 如果没有空闲连接,起个协程去异步建立,建立成功再通知主协程 再接着是一个 select 等待连接建立成功、超时或者主动取消,这就实现了在连接过程中的超时 在上一条连接建立的时候,每个链接还偷偷起了两个协程,一个负责往连接中写入数据,另一个负责读数据,他们都监听了相应的 channel。 其中 wirteLoop 监听来自主协程的数据,并往连接中写入 同理,readLoop 读取响应数据,并写回主协程。读与写的过程中如果超时了,连接将被关闭,报错退出。 超时机制小结 Go 的这种请求超时机制,可随时终止请求,可设置整个请求的超时时间。其实现主要依赖协程、channel、select 机制的配合。总结出套路是: 以循环任务为例 Java 能实现这种超时机制吗 直接说结论:暂时不行。 首先 Java 的线程太重,像 Go 这样一次请求开了这么多协程,换成线程性能会大打折扣。 其次 Go 的 channel 虽然和 Java 的阻塞队列类似,但 Go 的 select 是多路复用机制,Java 暂时无法实现,即无法监听多个队列是否有数据到达。所以综合来看 Java 暂时无法实现类似机制。 本文介绍了 Go 另类且有趣的 HTTP 超时机制,并且分析了底层实现原理,归纳出了这种机制的套路,如果我们写 Go 代码,也可以如此模仿,让代码更 Go。 原文地址:https://juejin.cn/post/7166201276198289445 更多编程相关知识,请访问:编程视频!! Atas ialah kandungan terperinci Mari kita bincangkan tentang mekanisme tamat masa HttpClient Golang sendiri. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP! client := http.Client{
Timeout: 10 * time.Minute,
}
resp, err := client.Get("http://127.0.0.1:81/hello")
1. 根据 timeout 计算出超时的时间点
// 来自 src/net/http/client.go
deadline = c.deadline()
2. 设置请求的 cancel
// 来自 src/net/http/client.go
stopTimer, didTimeout := setRequestCancel(req, rt, deadline)
// 来自 src/net/http/client.go
var cancelCtx func()
if oldCtx := req.Context(); timeBeforeContextDeadline(deadline, oldCtx) {
req.ctx, cancelCtx = context.WithDeadline(oldCtx, deadline)
}
// 来自 src/net/http/client.go
timer := time.NewTimer(time.Until(deadline))
var timedOut atomicBool
go func() {
select {
case <-initialReqCancel:
doCancel()
timer.Stop()
case <-timer.C:
timedOut.setTrue()
doCancel()
case <-stopTimerCh:
timer.Stop()
}
}()
// 位于 src/net/http/transport.go
// CancelRequest cancels an in-flight request by closing its connection.
// CancelRequest should only be called after RoundTrip has returned.
func (t *Transport) CancelRequest(req *Request) {
t.cancelRequest(cancelKey{req}, errRequestCanceled)
}
3. 获取连接
// 位于 src/net/http/transport.go
for {
select {
case <-ctx.Done():
req.closeBody()
return nil, ctx.Err()
default:
}
// ...
pconn, err := t.getConn(treq, cm)
// ...
}
// 位于 src/net/http/transport.go
// Queue for idle connection.
if delivered := t.queueForIdleConn(w); delivered {
// ...
return pc, nil
}
// 位于 src/net/http/transport.go
// Queue for permission to dial.
t.queueForDial(w)
// 位于 src/net/http/transport.go
// Wait for completion or cancellation.
select {
case <-w.ready:
// ...
return w.pc, w.err
case <-req.Cancel:
return nil, errRequestCanceledConn
case <-req.Context().Done():
return nil, req.Context().Err()
case err := <-cancelc:
if err == errRequestCanceled {
err = errRequestCanceledConn
}
return nil, err
}
4. 读写数据
// 位于 src/net/http/transport.go
go pconn.readLoop()
go pconn.writeLoop()
// 位于 src/net/http/transport.go
func (pc *persistConn) writeLoop() {
defer close(pc.writeLoopDone)
for {
select {
case wr := <-pc.writech:
startBytesWritten := pc.nwrite
err := wr.req.Request.write(pc.bw, pc.isProxy, wr.req.extra, pc.waitForContinue(wr.continueCh))
// ...
if err != nil {
pc.close(err)
return
}
case <-pc.closech:
return
}
}
}
总结

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



Membaca dan menulis fail dengan selamat dalam Go adalah penting. Garis panduan termasuk: Menyemak kebenaran fail Menutup fail menggunakan tangguh Mengesahkan laluan fail Menggunakan tamat masa konteks Mengikuti garis panduan ini memastikan keselamatan data anda dan keteguhan aplikasi anda.

Bagaimana untuk mengkonfigurasi pengumpulan sambungan untuk sambungan pangkalan data Go? Gunakan jenis DB dalam pakej pangkalan data/sql untuk membuat sambungan pangkalan data untuk mengawal bilangan maksimum sambungan serentak;

Cara menggunakan Gomega untuk penegasan dalam ujian unit Golang Dalam ujian unit Golang, Gomega ialah perpustakaan penegasan yang popular dan berkuasa yang menyediakan kaedah penegasan yang kaya supaya pembangun boleh mengesahkan keputusan ujian dengan mudah. Pasang Gomegagoget-ugithub.com/onsi/gomega Menggunakan Gomega untuk penegasan Berikut ialah beberapa contoh biasa menggunakan Gomega untuk penegasan: 1. Import penegasan kesamaan "github.com/onsi/gomega" funcTest_MyFunction(t*testing.T){

Perbezaan antara rangka kerja GoLang dan rangka kerja Go ditunjukkan dalam seni bina dalaman dan ciri luaran. Rangka kerja GoLang adalah berdasarkan perpustakaan standard Go dan meluaskan fungsinya, manakala rangka kerja Go terdiri daripada perpustakaan bebas untuk mencapai tujuan tertentu. Rangka kerja GoLang lebih fleksibel dan rangka kerja Go lebih mudah digunakan. Rangka kerja GoLang mempunyai sedikit kelebihan dalam prestasi dan rangka kerja Go lebih berskala. Kes: gin-gonic (rangka Go) digunakan untuk membina REST API, manakala Echo (rangka kerja GoLang) digunakan untuk membina aplikasi web.

Data JSON boleh disimpan ke dalam pangkalan data MySQL dengan menggunakan perpustakaan gjson atau fungsi json.Unmarshal. Pustaka gjson menyediakan kaedah kemudahan untuk menghuraikan medan JSON dan fungsi json.Unmarshal memerlukan penuding jenis sasaran kepada data JSON unmarshal. Kedua-dua kaedah memerlukan penyediaan pernyataan SQL dan melaksanakan operasi sisipan untuk mengekalkan data ke dalam pangkalan data.

Amalan terbaik: Cipta ralat tersuai menggunakan jenis ralat yang ditakrifkan dengan baik (pakej ralat) Sediakan lebih banyak butiran Log ralat dengan sewajarnya Sebarkan ralat dengan betul dan elakkan menyembunyikan atau menyekat ralat Balut seperti yang diperlukan untuk menambah konteks

Fungsi FindStringSubmatch mencari subrentetan pertama dipadankan dengan ungkapan biasa: fungsi mengembalikan hirisan yang mengandungi subrentetan yang sepadan, dengan elemen pertama ialah keseluruhan rentetan dipadankan dan elemen berikutnya ialah subrentetan individu. Contoh kod: regexp.FindStringSubmatch(teks,corak) mengembalikan sekeping subrentetan yang sepadan. Kes praktikal: Ia boleh digunakan untuk memadankan nama domain dalam alamat e-mel, contohnya: e-mel:="user@example.com", pattern:=@([^\s]+)$ untuk mendapatkan padanan nama domain [1].

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, ...
