Saya baru saja menemukan bahwa setiap permintaan dalam aplikasi web ASP.Net mendapat kunci Sesi di awal permintaan, dan kemudian melepaskannya di akhir permintaan!
Jika implikasi ini hilang pada Anda, seperti bagi saya pada awalnya, ini pada dasarnya berarti sebagai berikut:
Kapan saja situs web ASP.Net membutuhkan waktu lama untuk memuat (mungkin karena panggilan basis data yang lambat atau apa pun), dan pengguna memutuskan mereka ingin menavigasi ke halaman yang berbeda karena mereka lelah menunggu, MEREKA TIDAK BISA! Kunci sesi ASP.Net memaksa permintaan halaman baru untuk menunggu sampai permintaan asli selesai dengan lambat memuatnya. Arrrgh.
Kapan saja UpdatePanel memuat dengan lambat, dan pengguna memutuskan untuk menavigasi ke halaman yang berbeda sebelum UpdatePanel selesai memperbarui ... MEREKA TIDAK BISA! Kunci sesi ASP.net memaksa permintaan halaman baru untuk menunggu sampai permintaan asli selesai memuat dengan sangat lambat. Arrrgh Ganda!
Jadi apa saja pilihannya? Sejauh ini saya telah menemukan:
- Menerapkan Custom SessionStateDataStore, yang didukung oleh ASP.Net. Saya belum menemukan terlalu banyak untuk disalin, dan sepertinya beresiko tinggi dan mudah kacau.
- Pantau terus semua permintaan yang sedang berlangsung, dan jika ada permintaan dari pengguna yang sama, batalkan permintaan asli. Agak ekstrim, tapi itu akan berhasil (saya pikir).
- Jangan gunakan Sesi! Ketika saya membutuhkan semacam status untuk pengguna, saya bisa menggunakan Cache saja, dan item kunci pada nama pengguna yang diautentikasi, atau semacamnya. Lagi-lagi sepertinya agak ekstrim.
Saya benar-benar tidak percaya bahwa tim Microsoft ASP.Net akan meninggalkan hambatan kinerja yang sangat besar dalam kerangka kerja pada versi 4.0! Apakah saya kehilangan sesuatu yang jelas? Seberapa sulitkah menggunakan koleksi ThreadSafe untuk Sesi?
Jawaban:
Jika halaman Anda tidak mengubah variabel sesi apa pun, Anda dapat menyisih dari sebagian besar kunci ini.
Jika halaman Anda tidak membaca variabel sesi apa pun, Anda dapat memilih keluar dari kunci ini sepenuhnya, untuk halaman itu.
Jika tidak ada halaman Anda menggunakan variabel sesi, matikan saja status sesi di web.config.
Saya ingin tahu, apa yang Anda pikir "koleksi ThreadSafe" akan lakukan untuk menjadi thread-safe, jika tidak menggunakan kunci?
Sunting: Saya mungkin harus menjelaskan dengan apa yang saya maksud dengan "menyisih dari sebagian besar kunci ini". Sejumlah halaman read-only-session atau no-session dapat diproses untuk sesi yang diberikan secara bersamaan tanpa memblokir satu sama lain. Namun, halaman baca-tulis-sesi tidak dapat mulai memproses sampai semua permintaan read-only telah selesai, dan saat sedang berjalan itu harus memiliki akses eksklusif ke sesi pengguna itu untuk menjaga konsistensi. Mengunci nilai individual tidak akan berfungsi, karena bagaimana jika satu halaman mengubah satu set nilai terkait sebagai grup? Bagaimana Anda memastikan bahwa halaman lain yang berjalan pada saat yang sama akan mendapatkan tampilan yang konsisten dari variabel sesi pengguna?
Saya menyarankan agar Anda mencoba meminimalkan memodifikasi variabel sesi setelah mereka ditetapkan, jika memungkinkan. Ini akan memungkinkan Anda untuk membuat sebagian besar halaman Anda hanya baca-sesi-sesi, meningkatkan kemungkinan bahwa beberapa permintaan simultan dari pengguna yang sama tidak akan memblokir satu sama lain.
sumber
<pages enableSessionState="ReadOnly" />
di web.config dan gunakan @Page untuk mengaktifkan penulisan pada halaman tertentu saja.OK, Props begitu besar untuk Joel Muller untuk semua masukannya. Solusi utama saya adalah menggunakan Custom SessionStateModule yang dirinci di akhir artikel MSDN ini:
http://msdn.microsoft.com/en-us/library/system.web.sessionstate.sessionstateutility.aspx
Ini:
Ini telah membuat perbedaan besar pada perasaan "kekaburan" aplikasi kita. Saya masih tidak percaya implementasi kustom Sesi ASP.Net mengunci sesi untuk seluruh permintaan. Ini menambah jumlah kelesuan yang sangat besar ke situs web. Menilai dari jumlah riset online yang harus saya lakukan (dan percakapan dengan beberapa pengembang ASP.Net yang benar-benar berpengalaman), banyak orang telah mengalami masalah ini, tetapi sangat sedikit orang yang pernah sampai ke dasar penyebabnya. Mungkin saya akan menulis surat kepada Scott Gu ...
Saya harap ini membantu beberapa orang di luar sana!
sumber
ReaderWriterLock
sudah tidak digunakan lagiReaderWriterLockSlim
- Anda harus menggunakannya. Kedua,lock (typeof(...))
juga sudah usang - Anda harus mengunci bukan pada contoh objek statis pribadi. Ketiga, frasa "Aplikasi ini tidak mencegah permintaan Web simultan dari menggunakan pengidentifikasi sesi yang sama" adalah peringatan, bukan fitur.SessionStateItemCollection
dalam kode sampel dengan kelas aman-benang (mungkin berdasarkanConcurrentDictionary
) jika Anda ingin menghindari kesalahan yang sulit untuk mereproduksi di bawah beban.ISessionStateItemCollection
membutuhkanKeys
properti menjadi tipeSystem.Collections.Specialized.NameObjectCollectionBase.KeysCollection
- yang tidak memiliki konstruktor publik. Astaga, terima kasih kawan. Itu sangat nyaman.Saya mulai menggunakan AngiesList.Redis.RedisSessionStateModule , yang selain menggunakan server Redis (sangat cepat) untuk penyimpanan (saya menggunakan port windows - meskipun ada juga port MSOpenTech ), tidak ada penguncian pada sesi. .
Menurut pendapat saya, jika aplikasi Anda disusun dengan cara yang masuk akal, ini bukan masalah. Jika Anda benar-benar membutuhkan data yang terkunci dan konsisten sebagai bagian dari sesi, Anda harus secara khusus menerapkan pemeriksaan kunci / konkurensi sendiri.
MS memutuskan bahwa setiap sesi ASP.NET harus dikunci secara default hanya untuk menangani desain aplikasi yang buruk adalah keputusan yang buruk, menurut pendapat saya. Terutama karena sepertinya sebagian besar pengembang tidak / bahkan tidak menyadari sesi dikunci, apalagi bahwa aplikasi tampaknya perlu disusun sehingga Anda dapat melakukan status sesi baca-saja sebanyak mungkin (menyisih, jika mungkin) .
sumber
Saya menyiapkan perpustakaan berdasarkan tautan yang dipasang di utas ini. Ini menggunakan contoh-contoh dari MSDN dan CodeProject. Terima kasih untuk James.
Saya juga membuat modifikasi yang disarankan oleh Joel Mueller.
Kode ada di sini:
https://github.com/dermeister0/LockFreeSessionState
Modul HashTable:
Modul ScaleOut StateServer:
Modul khusus:
Jika Anda ingin menerapkan dukungan Memcached atau Redis, instal paket ini. Kemudian mewarisi kelas LockFreeSessionStateModule dan mengimplementasikan metode abstrak.
Beberapa penyedia sesi tanpa kunci menggunakan Redis:
sumber
Kecuali jika aplikasi Anda memiliki kebutuhan khusus, saya pikir Anda memiliki 2 pendekatan:
Sesi tidak hanya thread-safe tetapi juga state-safe, dengan cara yang Anda tahu bahwa sampai permintaan saat ini selesai, setiap variabel sesi tidak akan berubah dari permintaan aktif lainnya. Agar hal ini terjadi, Anda harus memastikan bahwa sesi AKAN DIKUNCI sampai permintaan saat ini selesai.
Anda dapat membuat perilaku seperti sesi dengan banyak cara, tetapi jika itu tidak mengunci sesi saat ini, itu tidak akan menjadi 'sesi'.
Untuk masalah spesifik yang Anda sebutkan, saya pikir Anda harus memeriksa HttpContext.Current.Response.IsClientConnected . Ini dapat berguna untuk mencegah eksekusi dan menunggu yang tidak perlu pada klien, meskipun tidak dapat menyelesaikan masalah ini sepenuhnya, karena ini dapat digunakan hanya dengan cara penyatuan dan bukan asinkron.
sumber
Jika Anda menggunakan pembaruan
Microsoft.Web.RedisSessionStateProvider
(mulai dari3.0.2
) Anda dapat menambahkan ini ke Andaweb.config
untuk memungkinkan sesi bersamaan.Sumber
sumber
Untuk ASPNET MVC, kami melakukan hal berikut:
SessionStateBehavior.ReadOnly
semua tindakan pengontrol dengan mengesampingkanDefaultControllerFactory
SessionStateBehavior.Required
Buat kustom ControllerFactory dan ganti
GetControllerSessionBehavior
.AcquireSessionLockAttribute
Hubungkan pabrik pengontrol yang dibuat di
global.asax.cs
Sekarang, kita dapat memiliki keduanya
read-only
danread-write
status sesi dalam satuController
.sumber
Menandai status sesi pengontrol sebagai hanya baca atau dinonaktifkan akan menyelesaikan masalah.
Anda dapat menghias pengontrol dengan atribut berikut untuk menandainya hanya-baca:
yang System.Web.SessionState.SessionStateBehavior enum memiliki nilai-nilai berikut:
sumber
Hanya untuk membantu siapa saja dengan masalah ini (mengunci permintaan saat mengeksekusi yang lain dari sesi yang sama) ...
Hari ini saya mulai memecahkan masalah ini dan, setelah beberapa jam penelitian, saya menyelesaikannya dengan menghapus
Session_Start
metode (bahkan jika kosong) dari file Global.asax .Ini bekerja di semua proyek yang saya uji.
sumber
Session_Start
metode dan masih terkunciSetelah berjuang dengan semua opsi yang tersedia, saya akhirnya menulis penyedia SessionStore berbasis token JWT (sesi berjalan di dalam cookie, dan tidak ada penyimpanan backend diperlukan).
http://www.drupalonwindows.com/en/content/token-sessionstate
Keuntungan:
sumber