Sessions: Buka 1.7: http.Request.Context memecah penggunaan gorila/konteks

Dibuat pada 4 Jun 2016  ·  22Komentar  ·  Sumber: gorilla/sessions

http.Request.Context() di Go 1.7 membuat salinan dangkal dari permintaan asli yang mengharuskan pemanggil untuk menyimpannya di hulu. Salinan ini memiliki alamat yang berbeda dan oleh karena itu memiliki kunci peta yang berbeda dalam peta konteks yang disediakan oleh gorila/konteks.

Untuk memperbaikinya di gorila/sesi, kami perlu membuat perubahan besar untuk pengguna Go 1.7+:

- func GetRegistry(r *http.Request) *Registry {
+ func GetRegistry(r *http.Request) (*Registry, *http.Request)
- sessions.GetRegistry(r).Get(s, name)
+ var reg *sessions.Registry
+ reg, r = sessions.GetRegistry(r)
+ sess, err := reg.Get(store, name)

Itu harus tentang itu. Sayangnya, ini tidak dapat dihindari, tetapi (untungnya) merupakan perubahan yang melanggar waktu kompilasi yang dapat kami dokumentasikan dengan jelas.

Ref: https://github.com/gorilla/mux/issues/168

breaking change enhancement

Komentar yang paling membantu

k, baiklah saya akan menjelaskan apa yang membingungkan saya (sebodoh kedengarannya), karena mungkin menjelaskan apa yang dialami orang lain. :senyum:

Ketika saya (pengguna pemula) membaca dokumen sesi, tampaknya cukup mudah hingga bagian ini:

Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with
context.ClearHandler or else you will leak memory! An easy way to do this is to wrap
the top-level mux when calling http.ListenAndServe:

    http.ListenAndServe(":8080", context.ClearHandler(http.DefaultServeMux))

The ClearHandler function is provided by the gorilla/context package.

Dengan aplikasi yang saya kembangkan, menggunakan Go 1.8 dan tidak menggunakan gorila/mux. Jadi, peringatan itu terdengar seperti sesuatu yang perlu kita lakukan. Membocorkan memori jelas buruk. Dengan demikian:

  1. Segera menambahkan "konteks" ke impor kami

    • Tidak berhasil. Setelah membaca ulang paragraf di atas, ia menyebutkan paket gorilla/context . Jadi, itu harus yang tepat untuk digunakan.

  2. Lihatlah halaman gorila/konteks. Yang itu memiliki peringatan ini sebagai gantinya:
Note: gorilla/context, having been born well before context.Context existed, does not
play well with the shallow copying of the request that http.Request.WithContext
(added to net/http Go 1.7 onwards) performs. You should either use just gorilla/context,
or moving forward, the new http.Request.Context().

Yang membuatnya terdengar sangat usang. Basis kode kami tidak memiliki context dalam bentuk apa pun di bagian impor mana pun, jadi sekarang saya bingung harus pergi ke mana. misalnya paket sessions mengatakan untuk mengimpor context , tetapi paket context sepertinya sudah usang

  1. Waktu untuk bertanya.

Anda telah membantu menjawab:

If you are using Go 1.8 only and not importing gorilla/context (which includes
packages you are using), gorilla/mux defaults to the Go 1.7 http.Request.Context
implementation.

... tapi itu tidak menjelaskan banyak hal (bagi saya). Dalam kasus (pemula) kami, kami tidak menggunakan gorila/mux. Kami ingin menggunakan gorila/sesi. Jadi, tidak heran bagaimana gorilla/mux defaulting di sana ikut bermain.

Bagaimanapun, saya kira yang saya maksud adalah bahwa perlu ada pernyataan yang jelas tentang ini. Yang saat ini tampaknya tidak membahas hal-hal untuk pengguna pemula (99,9% yang akan menggunakan Go 1.7+) yang belum menggunakan paket gorilla .

Semoga saya tidak memperkeruh suasana. :senyum:

Semua 22 komentar

FWIW, saat ini saya menggunakan cabang @shawnps sambil menunggu penggabungan ini dan akan melaporkan masalah apa pun yang saya temukan.

Kami secara tidak sengaja mengalami masalah ini ketika kami meningkatkan ke Go 1.7.3 baru-baru ini. Efek utamanya adalah tumpukan kami menghabiskan semua memori yang tersedia dan aplikasi kami mogok. Mungkin ide yang baik untuk menambahkan catatan peringatan ke file README utama.

Diagram di bawah adalah ruang yang digunakan setelah menjalankan benchmark 30 detik terhadap salah satu rute/penangan di aplikasi kami yang menyimpan berbagai variabel sesi dalam cookie.

session-leak

cc @jawnsy

Terima kasih atas petunjuknya, Solusinya adalah menyimpan sesi di request.context() secara manual dan masih membersihkan konteks gorialla di akhir permintaan.

Saya bingung dengan temuan @jbrook di atas , dan apakah aman menggunakan paket ini dengan Go 1.8.

Jika seseorang mengikuti saran untuk membungkus http.Handler dengan context.ClearHandler , apakah kita aman dari mengakumulasi instance sessions.Registry di memori?

context.ClearHandler menggunakan permintaan untuk membersihkan data terkait dan mungkin tidak benar-benar berfungsi dalam beberapa kasus dan membocorkan beberapa data (tergantung pada salinan permintaan yang mungkin dibuat). Tetapi ada metode dalam paket konteks yang dapat membantu:

// Purge removes request data stored for longer than maxAge, in seconds.
// It returns the amount of requests removed.
//
// If maxAge <= 0, all request data is removed.
//
// This is only used for sanity check: in case context cleaning was not
// properly set some request data can be kept forever, consuming an increasing
// amount of memory. In case this is detected, Purge() must be called
// periodically until the problem is fixed.
func Purge(maxAge int) int {

Cukup buat contextPurgeMiddleware yang memanggil context.Purge(-1) setelah setiap permintaan. Selain itu Anda harus memastikan bahwa Anda tidak bergantung pada gorilla.context karena middleware ini akan menghapus konteks semua permintaan. Anda hanya boleh menggunakan konteks go than.

Dengan membaca context.Purge , terutama ketika dipanggil dengan argumen nonpositif , itu menghapus _all_ data yang terkait dengan _all_ http.Request s yang telah kita simpan sesinya. Itu berarti sessions.(* CookieStore).Get membuat session.Registry s, tetapi setiap kali kami menyelesaikan permintaan yang diberikan, kami menghapus _semua_ registri ini, beberapa di antaranya dapat digunakan dalam permintaan yang masih kami proses secara bersamaan . Kami kemudian secara efektif membuat cache yang kami buang tanpa pandang bulu, mungkin sebelum kami dapat menggunakannya.

Bukankah saran yang lebih masuk akal adalah menghindari semua penggunaan sessions.GetRegistry ? Ternyata kami tidak bisa, jika pernah berniat untuk menelepon sessions.Save . Kita harus menghindari fungsi dan penggunaan itu, katakanlah, sessions.(*CookieStore).Save secara langsung, yang jauh lebih tidak praktis.

Berantakan sekali. Kami memiliki upaya pengoptimalan yang ternyata menjadi masalah yang lebih besar, seperti yang sering terjadi pada penyembunyian variabel global, dan kami sekarang mengalami kesulitan mengerjakan ulang agar kompatibel ke belakang. Saya tidak memiliki aplikasi sebelumnya yang menggunakan paket ini, jadi saya lebih tertarik pada cara memecahkannya untuk memperbaikinya.

Proposal asli di sini oleh @elithrar terdengar masuk akal, meskipun saya belum yakin bagaimana penelepon GetRegistry yang saya minati— sessions.(* CookieStore).Get dan sessions.Save —akan melakukannya untuk berubah juga.

Registri kemungkinan bisa dirampingkan jika kita pindah ke context.Context
secara internal. Itu akan bertindak sebagai "shim" yang sangat tipis ketika Anda mengakses
session.Values ​​atau panggil session.Save (yang sebagian besar seperti sekarang).

Konteks yang terkait dengan http.Request via Request.WithContext akan
secara otomatis menjadi GC'ed dan dengan demikian kita tidak memerlukan mekanisme "pembersihan".

Pada Jumat, 21 Juli 2017 pukul 19:12 Steven E. Harris [email protected]
menulis:

Dengan membaca konteks saya. Bersihkan, terutama ketika dipanggil dengan nonpositif
argumen
https://sourcegraph.com/github.com/gorilla/context/-/blob/context.go#L119-123 ,
itu menghapus semua data yang terkait dengan semua http.Permintaan yang
kami telah menyimpan sesi. Itu berarti sesi itu.(* CookieStore).Dapatkan
membuat session.Registrys, tetapi setiap kali kita selesai dengan permintaan yang diberikan,
kami menghapus semua registry ini, beberapa di antaranya dapat digunakan di
permintaan yang masih kami proses secara bersamaan. Kami kemudian secara efektif
membuat cache yang kita buang sembarangan, mungkin sebelum kita bisa
pernah memanfaatkan mereka.

Bukankah saran yang lebih masuk akal adalah menghindari semua penggunaan
session.GetRegistry? Ternyata kami tidak bisa, jika pernah berniat untuk menelepon
sesi.Simpan
https://sourcegraph.com/github.com/gorilla/sessions/-/blob/sessions.go#L189-190 .
Kita harus menghindari fungsi itu dan menggunakan, katakanlah, sesi.(*CookieStore).Simpan
langsung, yang jauh lebih praktis.

Berantakan sekali. Kami memiliki upaya pengoptimalan yang ternyata menjadi
masalah yang lebih besar, seperti yang sering terjadi pada variabel global,
dan kami sekarang mengalami kesulitan mengerjakan ulang agar menjadi mundur
kompatibel. Saya tidak memiliki aplikasi sebelumnya yang menggunakan paket ini, jadi saya lebih
tertarik bagaimana memecahkannya untuk memperbaikinya.

Proposal asli di sini oleh @elithrar https://github.com/elithrar
kedengarannya masuk akal, meskipun saya belum yakin bagaimana penelepon GetRegistry
di mana saya tertarik—sesi.(* CookieStore).Dapatkan dan sesi.Simpan—akan
harus berubah juga.


Anda menerima ini karena Anda disebutkan.

Balas email ini secara langsung, lihat di GitHub
https://github.com/gorilla/sessions/issues/80#issuecomment-317147378 ,
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/AABIcCHZxevsfN5aDaTCBTLIlyEVR9Ehks5sQVqigaJpZM4IuFUJ
.

Saya _berpikir_ Saya melihat cara untuk menghindari semua penggunaan tipe Registry dengan paket apa adanya, tetapi melakukannya memerlukan studi dan ketekunan yang cermat. Saya setuju bahwa menggunakan http.Request.WithContext adalah cara untuk melakukan caching hal-hal ini, tetapi itu memaksa penelepon untuk berurusan dengan nilai http.Request disalin.

Cara kerja http.Request.WithContext adalah retrofit yang aneh. Saya ingin menemukan alasan desain yang mengamanatkan bahwa bidang "ctx" http.Request tidak dapat diubah. Saya kira ketika seseorang menggunakan http.Request dalam konteks server—berlawanan dengan menyiapkan permintaan sebagai klien—masuk akal untuk memperlakukan permintaan sebagai hal yang tetap.

Artikel ini (saya minta maaf karena menautkan ke Medium) menunjukkan contoh satu penangan HTTP "luar" yang menyiapkan kontribusi untuk konteks permintaan, dan meneruskan hasil http.Request.WithContext langsung ke penangan "dalam" yang didelegasikan berikutnya. Itu terlihat alami. Upaya penggunaan paket ini canggung, karena tidak ada pembungkus handler atau delegasi dalam permainan yang menetapkan batas yang mengandung dan berisi untuk perubahan konteks.

Yang perlu diperhatikan: memfaktorkan ulang pustaka ini dan memecah API lebih mudah di
tingkat teknis daripada bekerja dalam kendala saat ini.

Namun ada sejumlah besar inersia pada pengguna yang ada yang
jangan gunakan alat penjaja—paket ini melanjutkannya + menarik banyak orang
baru di Go. Saya berharap "dep" akan menjadi v1 sekarang jadi setidaknya kami bisa
memandu pengguna ke solusi yang terbukti (vendor tag lama) tetapi sayangnya.
Pada Sabtu, 22 Juli 2017 pukul 06:53 Steven E. Harris [email protected]
menulis:

Saya pikir saya melihat cara untuk menghindari semua penggunaan jenis Registry dengan
paket apa adanya, tetapi melakukannya membutuhkan studi dan ketekunan yang cermat. saya setuju
bahwa menggunakan http.Request.WithContext adalah cara untuk melakukan caching ini
hal-hal, tapi itu memaksa penelepon untuk berurusan dengan http.Request . yang disalin
nilai-nilai.

Cara kerja http.Request.WithContext adalah retrofit yang aneh. saya ingin
untuk menemukan alasan desain yang mengamanatkan bahwa "ctx" http.Request
lapangan menjadi tidak berubah. Saya kira ketika seseorang menggunakan http.Request di
konteks server—berlawanan dengan menyiapkan permintaan sebagai klien—itu membuat
masuk akal untuk memperlakukan permintaan sebagai hal yang tetap.

Artikel ini
https://medium.com/@matryer/context-has-arrived-per-request-state-in-go-1-7-4d095be83bd8
(Saya minta maaf karena menautkan ke Medium) menunjukkan contoh satu HTTP "luar"
handler menyiapkan kontribusi untuk konteks permintaan, dan meneruskan
hasil dari http.Request.WithContext langsung ke yang didelegasikan berikutnya
pengendali "dalam". Itu terlihat alami. Percobaan penggunaan paket ini adalah
canggung, karena tidak ada pembungkus pawang atau delegasi dalam permainan itu
menetapkan batas yang mengandung dan terkandung untuk perubahan konteks.


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/gorilla/sessions/issues/80#issuecomment-317185062 ,
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/AABIcDCORtCLuB5h7xon9JTyZrie4ITlks5sQf7XgaJpZM4IuFUJ
.

Selama akhir pekan saya menulis perpustakaan ini untuk membantu menggunakan _gorilla/sessions_ tanpa menyentuh session.Registry . Ini membutuhkan dokumentasi dan contoh, tetapi saya harap Anda bisa mendapatkan inti dari dokumentasi tingkat fungsi yang ada di sana.

Hmmm, jadi sebagai programmer Golang pemula yang ingin menggunakan gorila/sesi untuk pertama kalinya... apakah ini memengaruhi basis kode yang saya kerjakan? (menggunakan Go 1.8, dan belum menggunakan paket konteks eksplisit apa pun)

Dokumen README saat ini mengatakan:

Important Note: If you aren't using gorilla/mux, you need to wrap your handlers
with context.ClearHandler ...

Yang ternyata berarti gorilla/context ( hanya ). :wink: Melihat berbagai masalah di sini dan PR terbuka tentang dokumen memori, sepertinya itu bertentangan dengan paket Go 1.7+ context .

Hmmm, apakah fragmen dokumen itu perlu diperbarui untuk mengatakan sesuatu yang lebih seperti:

Important Note: If you are using gorilla/content, but aren't using gorilla/mux, you
need to wrap your handlers with context.ClearHandler ...

Ini cukup membingungkan atm. :mengedip:

Jika Anda hanya menggunakan Go 1.8 dan tidak mengimpor gorila/konteks (yang
termasuk paket yang Anda gunakan), gorilla/mux default ke Go 1.7
http.Request.Context implementasi.

Pada Rabu, 2 Agustus 2017 pukul 07:42 Justin Clift [email protected]
menulis:

Hmmm, jadi sebagai programmer Golang pemula yang ingin menggunakan gorila/sesi
untuk pertama kalinya... apakah ini mempengaruhi basis kode yang saya kerjakan? (menggunakan
Buka 1.8, dan belum menggunakan paket konteks eksplisit apa pun)

Dokumen README saat ini mengatakan:

Catatan Penting: Jika Anda tidak menggunakan gorila/mux, Anda harus membungkus pawang Anda
dengan konteks.ClearHandler ...

Yang ternyata berarti gorila/konteks ( hanya ). Melihat berbagai
masalah di sini dan PR terbuka tentang dokumen memori sepertinya itu konflik
dengan paket konteks Go 1.7+.

Hmmm, apakah fragmen dokumen itu perlu diperbarui untuk mengatakan sesuatu yang lebih seperti:

Catatan Penting: Jika Anda menggunakan gorila/konten, tetapi tidak menggunakan gorila/mux, Anda
perlu membungkus penangan Anda dengan context.ClearHandler ...

Ini cukup membingungkan atm. 😉


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/gorilla/sessions/issues/80#issuecomment-319693852 ,
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/AABIcLwCza_i7Hm2BWqOC4EmNJKpHqOTks5sUIrdgaJpZM4IuFUJ
.

Dingin. Apa cara yang tepat untuk mengomunikasikannya kepada pengembang Go baru, sehingga mereka tahu jika/apa yang perlu mereka ubah? :senyum:

Sejujurnya: jika saya tahu saya sudah melakukannya. Apa yang tidak jelas tentang
ungkapan saat ini, mengingat itu menautkan paket gorila/konteks juga?

(Benda ini juga padat, jadi sulit bagi pengembang baru untuk
mengerti - bukan salah mereka, kita berurusan dengan utang teknologi)

Pada hari Rabu, 2 Agustus 2017 jam 8:45 Justin Clift [email protected]
menulis:

Dingin. Apa cara yang tepat untuk mengomunikasikannya kepada pengembang Go baru, jadi
mereka tahu jika/apa yang perlu mereka ubah? 😄


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/gorilla/sessions/issues/80#issuecomment-319712987 ,
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/AABIcHEAAbp0Q5-FGSbGzj3TgO7IJ42Qks5sUJmugaJpZM4IuFUJ
.

k, baiklah saya akan menjelaskan apa yang membingungkan saya (sebodoh kedengarannya), karena mungkin menjelaskan apa yang dialami orang lain. :senyum:

Ketika saya (pengguna pemula) membaca dokumen sesi, tampaknya cukup mudah hingga bagian ini:

Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with
context.ClearHandler or else you will leak memory! An easy way to do this is to wrap
the top-level mux when calling http.ListenAndServe:

    http.ListenAndServe(":8080", context.ClearHandler(http.DefaultServeMux))

The ClearHandler function is provided by the gorilla/context package.

Dengan aplikasi yang saya kembangkan, menggunakan Go 1.8 dan tidak menggunakan gorila/mux. Jadi, peringatan itu terdengar seperti sesuatu yang perlu kita lakukan. Membocorkan memori jelas buruk. Dengan demikian:

  1. Segera menambahkan "konteks" ke impor kami

    • Tidak berhasil. Setelah membaca ulang paragraf di atas, ia menyebutkan paket gorilla/context . Jadi, itu harus yang tepat untuk digunakan.

  2. Lihatlah halaman gorila/konteks. Yang itu memiliki peringatan ini sebagai gantinya:
Note: gorilla/context, having been born well before context.Context existed, does not
play well with the shallow copying of the request that http.Request.WithContext
(added to net/http Go 1.7 onwards) performs. You should either use just gorilla/context,
or moving forward, the new http.Request.Context().

Yang membuatnya terdengar sangat usang. Basis kode kami tidak memiliki context dalam bentuk apa pun di bagian impor mana pun, jadi sekarang saya bingung harus pergi ke mana. misalnya paket sessions mengatakan untuk mengimpor context , tetapi paket context sepertinya sudah usang

  1. Waktu untuk bertanya.

Anda telah membantu menjawab:

If you are using Go 1.8 only and not importing gorilla/context (which includes
packages you are using), gorilla/mux defaults to the Go 1.7 http.Request.Context
implementation.

... tapi itu tidak menjelaskan banyak hal (bagi saya). Dalam kasus (pemula) kami, kami tidak menggunakan gorila/mux. Kami ingin menggunakan gorila/sesi. Jadi, tidak heran bagaimana gorilla/mux defaulting di sana ikut bermain.

Bagaimanapun, saya kira yang saya maksud adalah bahwa perlu ada pernyataan yang jelas tentang ini. Yang saat ini tampaknya tidak membahas hal-hal untuk pengguna pemula (99,9% yang akan menggunakan Go 1.7+) yang belum menggunakan paket gorilla .

Semoga saya tidak memperkeruh suasana. :senyum:

Apakah layak untuk bergerak maju dengan perubahan v2 pada cabang alternatif di repo ini? Itu setidaknya akan memungkinkan pengguna dep dan alat serupa untuk bergerak maju dengan secara khusus memilih cabang/tag alternatif, tanpa memengaruhi pengguna alat non-vendor.

Ya, itulah yang kami rencanakan, tapi itu bagian yang mudah. Bagian yang sulit adalah melakukan semua pekerjaan untuk menulis kode, tes baru, memastikan API baru memiliki waktu untuk memanggang, dll :)

Apakah ditutup oleh PR # 175 baru-baru ini?

Benar.
Pada Sabtu, 2 Maret 2019 pukul 3:32, Wilk [email protected] menulis:

Apakah ditutup oleh PR # 175 baru-baru ini?
https://github.com/gorilla/sessions/pull/175 ?


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/gorilla/sessions/issues/80#issuecomment-468912351 ,
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/AABIcNJckK9bhN3R0GYa1XbQ4wkGGgtGks5vSmFngaJpZM4IuFUJ
.

Baik, apakah Anda berencana untuk membuat rilis kecil dengan perubahan ini atau masih melompat ke v2 untuk ini?

Saya akan segera memotong rilis minor baru untuk ini.

Pada Senin, 4 Maret 2019 pukul 1:37, Wilk [email protected] menulis:

Baik, apakah Anda berencana untuk membuat rilis kecil dengan perubahan ini atau tetap melompat
ke v2 untuk ini ?


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/gorilla/sessions/issues/80#issuecomment-469183709 ,
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/AABIcKKWgsG7MP9P1N8ZvaEtwlQuT_ebks5vTOlbgaJpZM4IuFUJ
.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat