Pendahuluan
Dalam lingkungan tanpa kewarganegaraan seperti aplikasi Web, memahami konsep status sesi tidak memiliki arti sebenarnya. Meskipun demikian, manajemen negara yang efektif adalah fitur yang harus dimiliki oleh sebagian besar aplikasi Web. Microsoft ASP.NET, serta banyak lingkungan pemrograman sisi server lainnya, menyediakan lapisan abstraksi yang memungkinkan aplikasi menyimpan data persisten berdasarkan per pengguna dan per aplikasi.
Penting untuk dicatat bahwa status sesi aplikasi web adalah data yang di-cache dan diambil oleh aplikasi di berbagai permintaan. Sesi mewakili semua permintaan yang dikirim oleh pengguna saat terhubung ke situs, dan status sesi adalah kumpulan data persisten yang dihasilkan dan dikonsumsi oleh pengguna selama sesi tersebut. Status setiap sesi tidak bergantung satu sama lain dan tidak ada lagi saat sesi pengguna berakhir.
Status sesi tidak memiliki korespondensi dengan entitas logis mana pun yang membentuk protokol dan spesifikasi HTTP. Sesi adalah lapisan abstraksi yang dibangun oleh lingkungan pengembangan sisi server seperti ASP tradisional dan ASP.NET. Cara ASP.NET menampilkan status sesi dan bagaimana status sesi diimplementasikan secara internal bergantung pada infrastruktur platform. Oleh karena itu, ASP tradisional dan ASP.NET mengimplementasikan status sesi dengan cara yang sangat berbeda, dan perbaikan serta penyempurnaan lebih lanjut diharapkan terjadi pada versi ASP.NET berikutnya.
Artikel ini membahas cara mengimplementasikan status sesi di ASP.NET 1.1 dan cara mengoptimalkan manajemen status sesi di aplikasi Web yang dikelola.
Ikhtisar Status Sesi ASP.NET
Status sesi bukan bagian dari infrastruktur HTTP. Artinya, harus ada komponen struktural yang mengikat status sesi dengan setiap permintaan masuk. Lingkungan runtime (ASP tradisional atau ASP.NET) dapat menerima kata kunci seperti Sesi dan menggunakannya untuk menunjukkan blok data yang disimpan di server. Agar berhasil menyelesaikan panggilan ke objek Sesi, lingkungan runtime harus menambahkan status sesi ke konteks panggilan dari permintaan yang sedang diproses. Cara melakukan hal ini berbeda-beda antar platform, namun hal ini penting untuk aplikasi web stateful.
Dalam ASP tradisional, status sesi diimplementasikan sebagai objek COM berulir bebas yang terdapat di perpustakaan asp.dll. (Apakah Anda penasaran? CLSID objek ini sebenarnya adalah D97A6DA0-A865-11cf-83AF-00A0C90C2BD8.) Objek ini menyimpan data yang disusun sebagai kumpulan pasangan nama/nilai. Placeholder "nama" mewakili kunci yang digunakan untuk mengambil informasi, sedangkan placeholder "nilai" mewakili apa yang disimpan dalam status sesi. Pasangan nama/nilai dikelompokkan berdasarkan ID sesi sehingga setiap pengguna hanya melihat pasangan nama/nilai yang dia buat.
Di ASP.NET, antarmuka pemrograman untuk status sesi hampir sama dengan ASP tradisional. Namun implementasi dasarnya sangat berbeda. Sebelum kita mempelajari status sesi ASP.NET, mari kita tinjau secara singkat beberapa kemampuan struktural infrastruktur sesi ASP.NET.
Di ASP.NET, setiap permintaan HTTP yang masuk disalurkan melalui modul HTTP. Setiap modul dapat menyaring dan mengubah sejumlah besar informasi yang dibawa oleh permintaan. Informasi yang terkait dengan setiap permintaan disebut "konteks panggilan", yang diwakili oleh objek HttpContext dalam pemrograman. Kita tidak boleh menganggap konteks permintaan sebagai wadah informasi negara lainnya, meskipun kumpulan Item yang disediakannya hanyalah wadah data. Objek HttpContext berbeda dari semua objek status lainnya (misalnya, Sesi, Aplikasi, dan Cache) karena memiliki masa pakai terbatas melebihi waktu yang diperlukan untuk menangani permintaan. Ketika permintaan melewati serangkaian modul HTTP terdaftar, objek HttpContext-nya akan berisi referensi ke objek status. Ketika permintaan akhirnya dapat diproses, konteks panggilan terkait terikat ke sesi tertentu (Sesi) dan objek status global (Aplikasi dan Cache).
Modul HTTP yang bertanggung jawab untuk mengatur status sesi setiap pengguna adalah SessionStateModule. Struktur modul ini dirancang berdasarkan antarmuka IHttpModule, yang menyediakan sejumlah besar layanan terkait status sesi untuk aplikasi ASP.NET. Termasuk pembuatan ID sesi, pengelolaan sesi tanpa cookie, pengambilan data sesi dari penyedia status eksternal, dan pengikatan data ke konteks panggilan permintaan.
Modul HTTP tidak menyimpan data sesi secara internal. Status sesi selalu disimpan dalam komponen eksternal yang disebut "penyedia status". Penyedia negara sepenuhnya merangkum data status sesi dan berkomunikasi dengan bagian lain melalui metode antarmuka IStateClientManager. Modul HTTP status sesi memanggil metode pada antarmuka ini untuk membaca dan menyimpan status sesi. ASP.NET 1.1 mendukung tiga penyedia negara yang berbeda, seperti yang ditunjukkan pada Tabel 1.
Tabel 1:Deskripsi Penyedia
Penyedia Klien Status
Nilai sesi InProc tetap menjadi objek aktif dalam memori proses pekerja ASP.NET (aspnet_wp.exe atau w3wp.exe di Microsoft® Windows Server® 2003). Ini adalah opsi default.
Nilai sesi StateServer diserialkan dan disimpan dalam memori dalam proses terpisah (aspnet_state.exe). Prosesnya juga dapat berjalan di komputer lain.
Nilai sesi SQLServer diserialkan dan disimpan dalam tabel Microsoft® SQL Server®. Contoh SQL Server dapat dijalankan secara lokal atau jarak jauh.
Modul HTTP status sesi membaca penyedia status yang dipilih saat ini dari bagian
Kode di atas sebenarnya mengakses nilai sesi yang dibuat oleh modul HTTP di memori lokal Replika membaca data dari penyedia negara tertentu (lihat Gambar 1). Apa yang terjadi jika halaman lain juga mencoba mengakses status sesi secara sinkron? Dalam hal ini, permintaan saat ini mungkin berhenti memproses data yang tidak konsisten atau basi. Untuk menghindari hal ini, modul status sesi akan menerapkan mekanisme penguncian pembaca/penulis dan akses antrean ke nilai status. Halaman dengan izin menulis pada status sesi akan mempertahankan kunci penulis untuk sesi tersebut hingga permintaan dihentikan. Sebuah halaman dapat meminta izin menulis untuk status sesi dengan mengatur properti EnableSessionState dari direktif @Page ke true. (Ini adalah pengaturan default). Namun, halaman juga dapat memiliki akses baca-saja ke status sesi, misalnya, ketika properti EnableSessionState diatur ke ReadOnly. Dalam hal ini, modul akan mempertahankan kunci pembaca untuk sesi tersebut hingga permintaan untuk halaman tersebut berakhir. Akibatnya pembacaan bersamaan akan terjadi. Jika permintaan halaman menyetel kunci pembaca, permintaan bersamaan lainnya dalam sesi yang sama tidak akan dapat memperbarui status sesi, namun setidaknya dapat membaca. Artinya, jika permintaan baca-saja sedang diproses untuk suatu sesi, permintaan hanya-baca yang tertunda akan memiliki prioritas lebih tinggi daripada permintaan yang memerlukan akses penuh. Jika permintaan halaman menetapkan kunci penulis untuk status sesi, semua halaman lainnya akan diblokir terlepas dari apakah mereka ingin membaca atau menulis konten. Misalnya, jika dua frame mencoba menulis ke Sesi pada saat yang sama, satu frame harus menunggu hingga frame lainnya selesai sebelum dapat menulis. Membandingkan Penyedia Negara Secara default, aplikasi ASP.NET menyimpan status sesi dalam memori proses pekerja, khususnya di slot khusus objek Cache. Ketika mode InProc dipilih, status sesi disimpan dalam slot di dalam objek Cache. Slot ini ditandai sebagai slot pribadi dan tidak dapat diakses secara terprogram. Dengan kata lain, jika Anda menghitung semua item dalam cache data ASP.NET, tidak ada objek yang serupa dengan status sesi tertentu yang akan dikembalikan. Objek cache menyediakan dua jenis slot: slot pribadi dan slot publik. Pemrogram dapat menambahkan dan menangani slot publik, namun slot pribadi hanya dapat digunakan oleh sistem (khususnya, kelas yang ditentukan di bagian system.web). Status setiap sesi aktif menempati slot khusus di cache. Slot diberi nama berdasarkan ID sesi, dan nilainya adalah turunan dari kelas internal yang tidak dideklarasikan bernama SessionStateItem. Penyedia status InProc mendapatkan ID sesi dan mengambil elemen terkait di cache. Isi dari objek SessionStateItem kemudian dimasukkan ke dalam objek kamus HttpSessionState dan diakses oleh aplikasi melalui properti Session. Perhatikan bahwa ada bug di ASP.NET 1.0 yang membuat slot pribadi objek Cache dapat dihitung secara terprogram. Jika Anda menjalankan kode berikut di bawah ASP.NET 1.0, Anda akan dapat menghitung item yang sesuai dengan objek yang terdapat dalam setiap status sesi yang sedang aktif. foreach(Elemen Entri Kamus di Cache) Bug ini telah diatasi di ASP.NET 1.1 dan ketika Anda menghitung konten cache, tidak ada slot sistem yang akan dicantumkan lagi. InProc mungkin merupakan opsi akses tercepat sejauh ini. Namun perlu diingat bahwa semakin banyak data yang disimpan dalam satu sesi, semakin banyak memori yang dikonsumsi server web, sehingga berpotensi meningkatkan risiko penurunan kinerja. Jika Anda berencana menggunakan solusi di luar proses, Anda harus mempertimbangkan dengan cermat kemungkinan efek serialisasi dan deserialisasi. Solusi di luar proses menggunakan layanan Windows NT (aspnet_state.exe) atau tabel SQL Server untuk menyimpan nilai sesi. Oleh karena itu, status sesi tetap berada di luar proses pekerja ASP.NET, dan lapisan kode tambahan diperlukan untuk membuat serialisasi dan deserialisasi antara status sesi dan media penyimpanan sebenarnya. Hal ini terjadi setiap kali permintaan diproses dan kemudian harus dioptimalkan hingga tingkat tertinggi. Karena data sesi perlu disalin dari repositori eksternal ke kamus sesi lokal, permintaan tersebut mengakibatkan penurunan kinerja mulai dari 15% (di luar proses) hingga 25% (SQL Server). Perlu diingat bahwa meskipun ini hanya perkiraan kasar, namun harus mendekati dampak minimum, dan dampak maksimum akan jauh lebih tinggi dari perkiraan tersebut. Faktanya, perkiraan ini tidak sepenuhnya memperhitungkan kompleksitas tipe yang sebenarnya disimpan dalam status sesi. Dalam skenario penyimpanan di luar proses, status sesi bertahan lebih lama, membuat aplikasi lebih kuat karena melindungi terhadap kegagalan Microsoft® Internet Information Services (IIS) dan ASP.NET. Dengan memisahkan status sesi dari aplikasi, Anda juga dapat dengan lebih mudah memperluas aplikasi yang ada ke dalam arsitektur Web Farm dan Web Garden. Selain itu, status sesi disimpan dalam proses eksternal, yang pada dasarnya menghilangkan risiko kehilangan data berkala karena perulangan proses. Berikut cara menggunakan layanan Windows NT. Seperti disebutkan di atas, layanan NT adalah proses bernama aspnet_state.exe, biasanya terletak di folder C:WINNTMicrosoft.NETFrameworkv1.1.4322. Direktori sebenarnya bergantung pada versi Microsoft® .NET Framework yang sebenarnya Anda jalankan. Sebelum menggunakan server negara, Anda harus memastikan bahwa layanan sudah siap dan berjalan di komputer lokal atau jarak jauh yang digunakan sebagai perangkat penyimpanan sesi. Layanan negara adalah bagian dari dan diinstal dengan ASP.NET, jadi Anda tidak perlu menjalankan penginstal tambahan. Secara default, layanan status tidak berjalan dan perlu dimulai secara manual. Aplikasi ASP.NET akan mencoba membuat sambungan ke server negara segera setelah dimuat. Oleh karena itu, layanan harus siap dan berjalan, jika tidak, pengecualian HTTP akan dilempar. Gambar berikut menunjukkan kotak dialog properti untuk layanan tersebut. Aplikasi ASP.NET perlu menentukan alamat TCP/IP komputer tempat layanan keadaan sesi berada. Pengaturan berikut harus dimasukkan ke dalam file web.config aplikasi. <konfigurasi>; Atribut stateConnectionString berisi alamat IP komputer dan port yang digunakan untuk pertukaran data. Alamat komputer default adalah 127.0.0.1 (localhost) dan port default adalah 42424. Anda juga dapat menunjukkan komputer berdasarkan namanya. Menggunakan komputer lokal atau jarak jauh sepenuhnya transparan terhadap kode. Perhatikan bahwa karakter non-ASCII tidak dapat digunakan dalam nama, dan nomor port wajib diisi. Jika Anda menggunakan penyimpanan sesi di luar proses, status sesi akan tetap ada dan tersedia untuk penggunaan di masa mendatang, apa pun yang terjadi pada proses pekerja ASP.NET. Jika layanan terganggu, data akan disimpan dan diambil secara otomatis saat layanan dipulihkan. Namun jika layanan penyedia status berhenti atau gagal, data akan hilang. Jika Anda ingin aplikasi Anda kuat, gunakan mode SQLServer, bukan mode StateServer. <konfigurasi>; Anda dapat menentukan string koneksi melalui atribut sqlConnectionString. Perhatikan bahwa string atribut harus berisi ID pengguna, kata sandi, dan nama server. Itu tidak boleh berisi tag seperti Database dan Katalog Awal karena informasi ini defaultnya adalah nama tetap. ID pengguna dan kata sandi dapat diganti dengan pengaturan keamanan terintegrasi. Bagaimana cara membuat database? ASP.NET menyediakan dua pasang skrip untuk mengkonfigurasi lingkungan database. Pasangan skrip pertama diberi nama InstallSqlState.sql dan UninstallSqlState.sql dan terletak di folder yang sama dengan layanan Session State NT. Mereka membuat database bernama ASPState dan beberapa prosedur tersimpan. Namun, data disimpan di tempat penyimpanan sementara database TempDB SQL Server. Artinya jika komputer SQL Server di-restart, data sesi akan hilang. Untuk mengatasi keterbatasan ini, gunakan skrip kedua. Pasangan skrip kedua diberi nama InstallPersistSqlState.sql dan UninstallPersistSqlState.sql. Dalam hal ini, database ASPState dibuat, tetapi tabel dibuat dalam database yang sama dan juga bersifat persisten. Saat Anda menginstal dukungan SQL Server untuk sesi, pekerjaan juga dibuat untuk menghapus sesi yang kedaluwarsa di database status sesi. Pekerjaan tersebut diberi nama ASPState_Job_DeleteExpiredSessions dan selalu berjalan. Harap dicatat bahwa agar pekerjaan ini berfungsi dengan baik, layanan SQLServerAgent harus berjalan. Apa pun mode yang Anda pilih, cara operasi status sesi dikodekan tidak berubah. Anda selalu dapat mengerjakan properti Session dan membaca serta menulis nilai seperti biasa. Semua perbedaan perilaku ditangani pada tingkat abstraksi yang lebih rendah. Serialisasi status mungkin merupakan perbedaan paling penting antara mode sesi. Serialisasi dan Deserialisasi Status Saat menggunakan mode dalam proses, objek disimpan dalam status sesi sebagai instance aktif dari kelasnya masing-masing. Jika tidak terjadi serialisasi dan deserialisasi nyata, berarti Anda sebenarnya dapat menyimpan objek apa pun yang Anda buat di Sesi (termasuk objek yang tidak dapat diserialisasi dan objek COM), dan mengaksesnya tidak akan terlalu mahal. Jika Anda memilih penyedia negara yang tidak sedang diproses, lain ceritanya. Dalam arsitektur di luar proses, nilai sesi disalin dari media penyimpanan lokal (database AppDomain eksternal) ke memori AppDomain yang menangani permintaan tersebut. Lapisan serialisasi/deserialisasi diperlukan untuk menyelesaikan tugas ini dan mewakili salah satu biaya utama penyedia status di luar proses. Dampak utama situasi ini terhadap kode Anda adalah hanya objek serial yang dapat disimpan dalam kamus sesi. ASP.NET menggunakan dua metode untuk membuat serialisasi dan deserialisasi data, bergantung pada tipe data yang terlibat. Untuk tipe dasar, ASP.NET menggunakan serializer internal yang dioptimalkan; untuk tipe lain, termasuk objek dan kelas yang ditentukan pengguna, ASP.NET menggunakan formatter biner .NET. Tipe dasar mencakup string, waktu tanggal, nilai Boolean, byte, karakter, dan semua tipe numerik. Untuk jenis ini, menggunakan serializer yang dibuat khusus lebih cepat daripada menggunakan formatter biner .NET umum default. Serializer yang dioptimalkan tidak dirilis atau didokumentasikan secara publik. Ini hanyalah pembaca/penulis biner dan menggunakan arsitektur penyimpanan yang sederhana namun efektif. Serializer menggunakan kelas BinaryWriter untuk menulis representasi byte dari tipe tersebut, dan kemudian menulis representasi byte dari nilai yang sesuai dengan tipe tersebut. Saat membaca byte berseri, kelas pertama-tama mengekstrak satu byte, mendeteksi tipe data yang akan dibaca, dan kemudian memanggil metode Readxxx tipe spesifik pada kelas BinaryReader. Perhatikan bahwa ukuran tipe boolean dan numerik sudah diketahui dengan baik, tetapi tidak untuk string. Pada aliran data yang mendasarinya, string selalu diawali dengan panjang tetap (kode bilangan bulat 7-bit yang ditulis sekaligus), dan pembaca menggunakan fakta ini untuk menentukan ukuran string yang benar. Nilai tanggal disimpan dengan menuliskan jumlah total token yang membentuk tanggal saja. Oleh karena itu, untuk membuat serial sesi, tanggalnya harus bertipe Int64. Anda dapat menggunakan kelas BinaryFormatter untuk melakukan operasi serialisasi pada objek yang lebih kompleks (serta objek khusus) selama kelas yang memuatnya ditandai sebagai dapat serial. Semua tipe non-dasar diidentifikasi oleh ID tipe yang sama dan disimpan dalam aliran data yang sama dengan tipe dasar. Secara keseluruhan, operasi serialisasi dapat mengakibatkan penurunan kinerja sebesar 15% hingga 25%. Namun perlu diperhatikan bahwa ini adalah perkiraan kasar berdasarkan asumsi bahwa tipe dasar digunakan. Semakin kompleks jenis yang digunakan, semakin besar biaya overhead. Penyimpanan data sesi yang efisien sulit diterapkan tanpa penggunaan tipe primitif secara ekstensif. Jadi, setidaknya secara teori, menggunakan tiga slot sesi untuk menyimpan tiga properti string berbeda dari suatu objek lebih baik daripada membuat serial seluruh objek. Namun bagaimana jika objek yang ingin Anda serialkan berisi 100 properti? Mau pakai 100 slot atau 1 slot saja? Dalam banyak kasus, pendekatan yang lebih baik adalah dengan mengubah tipe kompleks menjadi beberapa tipe yang lebih sederhana. Pendekatan ini didasarkan pada tipe konverter. Sebuah "konverter tipe" adalah serializer ringan yang mengembalikan properti kunci suatu tipe sebagai kumpulan string. Pengonversi tipe adalah kelas eksternal yang terikat ke kelas dasar menggunakan atribut. Terserah kepada penulis ketik untuk memutuskan properti mana yang disimpan dan bagaimana caranya. Konverter tipe juga berguna untuk penyimpanan ViewState dan mewakili metode penyimpanan sesi yang lebih efisien dibandingkan pemformat biner. Siklus Hidup Sesi Poin penting tentang manajemen sesi ASP.NET adalah bahwa siklus hidup objek keadaan sesi dimulai hanya ketika item pertama ditambahkan ke kamus dalam memori. Sesi ASP.NET dianggap dimulai hanya setelah cuplikan kode berikut dijalankan. Session["MySlot"] = "Beberapa data"; Kamus Sesi biasanya berisi tipe Objek. Untuk membaca data mundur, nilai yang dikembalikan perlu dikonversi ke tipe yang lebih spesifik. string data = (string) Session["MySlot"]; Ketika halaman menyimpan data ke Sesi, nilainya akan dimuat ke dalam kelas kamus yang dibuat khusus yang terdapat dalam kelas HttpSessionState. Isi kamus dimuat ke penyedia negara ketika permintaan yang sedang diproses selesai. Jika status sesi kosong karena data tidak dimasukkan ke dalam kamus secara terprogram, data tidak akan diserialkan ke media penyimpanan dan, yang lebih penting, tidak akan disajikan di ASP.NET Cache, SQL Server, atau NT State Services Create slot untuk melacak sesi saat ini. Hal ini karena alasan kinerja, namun memiliki dampak penting pada cara ID sesi ditangani: ID sesi baru akan dibuat untuk setiap permintaan hingga beberapa data disimpan dalam kamus sesi. Ketika perlu untuk menghubungkan status sesi dengan permintaan yang sedang diproses, modul HTTP mengambil ID sesi (jika ini bukan permintaan awal) dan mencarinya di penyedia status yang dikonfigurasi. Jika tidak ada data yang dikembalikan, modul HTTP menghasilkan ID sesi baru untuk permintaan tersebut. Hal ini dapat dengan mudah diuji dengan halaman berikut: <%@ Page Language="C#" Trace="true" %>;
{
Response.Write(elem.Key + ": " + elem.Value.ToString());
}
Gambar 2: Kotak dialog Properti Server Negara ASP.NET
stateConnectionString="tcpip=expoware:42424" />;
</system.web>;
;
sqlConnectionString="server=127.0.0.1;uid=<id pengguna>;;pwd=<kata sandi>;;" />;
</system.web>;
;
</html>;