Pada artikel kali ini saya akan membahas apa yang terjadi pada permasalahan dan cara mengatasi kegagalan PHP Sesion Hang disini saya akan mencoba memeriksa kenapa itu bisa terjadi dan bagaimana menyelesaikan masalah jika terjadi seperti ini.
kita akan mulai dengan mencoba membuat masalah sesason hang.
Bisa di coba Saat aplikasi tidak digunakan
Tulis skirp Php berikut.
<?php function useful_function() { sleep(1); } useful_function(); ?>
Kemudian gunakan ab perintah untuk mengirim 10 permintaan silmutan ke server.
ab -c 10 -n 10 http://localhost:8999/first.php
Hasilnya akan terlihat seperti berikut
... Concurrency Level: 10 Time taken for tests: 1.003 seconds Complete requests: 10 ...
Karena saya telah mengirim 10 permintaan simultan per detik, waktu eksekusi dari perintah di atas tentu saja 1 detik. Sekarang mari tambahkan fungsi untuk menunjukkan jumlah kunjungan halaman menggunakan PHP Session.
<?php //session_test1.php function useful_function(){ sleep(1); } session_start(); if(isset($_SESSION['visit_count'])===FALSE){ $_SESSION['visit_count'] = 1; } else{ $_SESSION['visit_count'] += 1; } $visit_count = 'visit_count = '.$_SESSION['visit_count']; echo $visit_count; aries_add_message_profile($visit_count); //add 'visit_count' to jennifer profiles useful_function(); ?>
Mengirim satu permintaan melalui url, hasilnya akan terlihat seperti berikut:
curl -v http://localhost:8999/session_test1.php * Trying 127.0.0.1... ... < HTTP/1.1 200 OK < Date: Wed, 05 Dec 2018 05:34:53 GMT < Server: Apache/2.2.22 (Ubuntu) < Set-Cookie: PHPSESSID=lmrfduhgfm6oik62fi2c9q4ek7; expires=Wed, 05-Dec-2018 13:34:53 GMT; path=/ < Expires: Thu, 19 Nov 1981 08:52:00 GMT ... visit_count = 1%
Didalam respon kita dapat melihat bahwa jumlah kunjungan adalah 1(visit_count=1) Karena PHPSESSID telah ditambahkan ke cookie respons HTTP, pengendali sesi default PHP menggunakan cookie, dan nilai cookie PHPSESSID digunakan sebagai pengenal Sesi.
Mari kita kirim permintaan lain dengan curl, kali ini kita akan menambahkan PHPSESSID di cookie.
curl --cookie "PHPSESSID=lmrfduhgfm6oik62fi2c9q4ek7" http://localhost:8999/session_test1.php ... visit_count = 2%
Kali ini kita dapat melihat bahwa visit_count=2 . Jadi fitur kunjungan halaman yang baru ditambahkn berfungsi dengan baik. kita lihat apa yang terjadi di server web. Jika mencantumkan isi direktori /tmp, Anda akan melihat bahwa file lmrfd… . coba periksa konten file, Anda akan melihat bagaimana sesi disimpan:
visit_count|i:2;
Kasus Kegagalan Sesi PHP 1 (Mengatasi Kegagalan)
saya akan mengirim lagi mengirim 10 permintaan simultan lagi menggunakan ab perintah, kali ini kita akan menentukan PHPSESSID sebagai cookie.
Hasil dari perintah tersebut akan terlihat seperti berikut.
ab -c 10 -n 10 -C PHPSESSID=lmrfduhgfm6oik62fi2c9q4ek7 http://localhost:8999/session_test1.php ... Concurrency Level: 10 Time taken for tests: 10.006 seconds Complete requests: 10 ...
Anda dapat segera melihat bahwa ketika tidak menggunakan fungsi Sesi, waktu eksekusi perintah ab adalah 1 detik, namun, setelah menggunakan sesi, 10 permintaan yang sama membutuhkan waktu 10 detik.
Apm Jennifer X-View menunjukkan pola berikut.
X-View memplot waktu permintaan pada sumbu X dan waktu respons pada sumbu Y. Kita dapat melihat bahwa semua 10 permintaan datang pada saat yang sama, tetapi waktu pemrosesannya berbeda.
Jika kita memeriksa detail transaksi, kita dapat melihat bahwa waktu mulai sama untuk 10 permintaan, 16:12:52. Namun, waktu responsnya adalah 1 detik, 2 detik, 3 detik … 10 detik untuk masing-masing dari 10 permintaan. Selain itu, fungsi session_start dari permintaan yang diproses terakhir membutuhkan waktu 9 detik untuk dieksekusi. Ini karena file session handler mengunci file session.
Kasus Kegagalan Sesi PHP 2
Kali ini saya akan membuat masalahnya sedikit lebih serius. Misalkan kita memperbarui fungsi_berguna kita menambahkan koneksi database untuk fungsi itu.
<?php //session_test2.php function useful_function($db){ sleep(1); } $db = mysql_connect('...'); session_start(); if(isset($_SESSION['visit_count'])===FALSE){ $_SESSION['visit_count'] = 1; } else{ $_SESSION['visit_count'] += 1; } $visit_count = 'visit_count = '.$_SESSION['visit_count']; echo $visit_count; aries_add_message_profile($visit_count); useful_function($db);
mysql_connect dipanggil sebelum session_start (). Dalam hal ini, jika permintaan satu Sesi dipanggil N pada saat yang sama, nomor koneksi DB juga bertambah N, untuk menghindari ini, anda tidak boleh memperoleh sumber daya sebelum session_start.
Pada saat anda mengubah kode untuk mendapatkan sumber daya DB setelah memanggil session_start (), bagan Koneksi DB Aktif terlihat seperti ini: Perhatikan bahwa jumlah koneksi DB disimpan di 1.
Pemecahan masalah dengan session_write_close
PHP .net memperingatkan masalah di atas dan menyarankan solusi berikut. Gunakan fungsi session_start dengan opsi read_and_close (Opsi ini hanya tersedia untuk PHP 7.0 dan yang lebih baru.)
Setelah memodifikasi data sesi, gunakan session_commit atau session_write_close untuk melepaskan kunci sesi sesegera mungkin. Saya akan mencoba menyelesaikan masalah dengan mengambil metode kedua.
<?php function useful_function($db){ sleep(1); } session_start(); if(isset($_SESSION['visit_count'])===FALSE){ $_SESSION['visit_count'] = 1; } else{ $_SESSION['visit_count'] += 1; } session_write_close(); //release session lock $visit_count = 'visit_count = '.$_SESSION['visit_count']; echo $visit_count; $db=mysql_connect('...'); aries_add_message_profile($visit_count); //Change _SESSION['visit_count'] $_SESSION['visit_count'] = 'write data after session_write_close()'; aries_add_message_profile($_SESSION['visit_count']); useful_function($db); ?>
Setelah memodifikasi kode, seperti yang ditunjukkan di atas, saya akan mengirimkan 10 permintaan sekaligus.
ab -c 10 -n 10 -C PHPSESSID=lmrfduhgfm6oik62fi2c9q4ek7 http://localhost:8999/session_test3.php ... Concurrency Level: 10 Time taken for tests: 1.007 seconds ...
Masalah teratasi. Semua permintaan diproses secara bersamaan. Namun, harus berhati-hati. Kode di atas telah mengubah $_SESSION ['visit_count'] setelah panggilan session_write_close().
Bagaimana cara kerjanya? Mari kita lihat profil APM Jennifer.
Nilai $_SESSION['visit_count'] adalah 'tulis data setelah session_write_close()' . Anda dapat melihat bahwa itu telah dimodifikasi. Sekarang mari kita periksa isi file sess yang disimpan di direktori /tmp.
cat /tmp/sess_lmrfduhgfm6oik62fi2c9q4ek7 visit_count|i:40;
Anda dapat melihat bahwa nilai visit_count adalah 40 'tulis data setelah session_write_close ()'. Ini berarti bahwa nilai variabel $_SESSION diubah karena panggilan valid selama durasi permintaan, tetapi tidak dicatat dalam data Sesi. Ini adalah salah satu kelemahan dari session_write_close solusi.
Jika Anda mengubah sesi. Jika anda membuat kesalahan, nilai yang anda lihat dan nilai yang disimpan dalam Sesi mungkin akan berbeda.
Pemecahan masalah dengan Redis Session Handler
Kita akan menggunakan pengendali sesi Redis yang tidak mengunci sesi untuk menyelesaikan masalah. (Anda juga dapat menggunakan Kunci sebagai opsi.) Panggil session_test2.php (skrip yang tidak menggunakan session_write_close) yang ditentukan di atas 10 kali secara bersamaan.
ab -c 10 -n 10 -C PHPSESSID=lmrfduhgfm6oik62fi2c9q4ek7 http://localhost:8999/session_test2.php ... Concurrency Level: 10 Time taken for tests: 1.006 seconds
Masalah telah hilang. semua permintaan diproses secara bersamaan. Juga, periksa Data Sesi.
# redis-cli 127.0.0.1:6379> KEYS * 1) "PHPREDIS_SESSION:lmrfduhgfm6oik62fi2c9q4ek7" 127.0.0.1:6379> GET "PHPREDIS_SESSION:lmrfduhgfm6oik62fi2c9q4ek7" "visit_count|i:6;" 127.0.0.1:6379>
visit_count dicatat sebagai 6 bukan10. Jika Anda memutuskan untuk menggunakan Redis Session Handler tanpa mengunci, Anda harus menyadari hal ini dan jangan berharap bahwa nilai yang disimpan dalam Session akan tetap utuh. Data yang membutuhkan integritas dan tidak boleh disimpan dalam Sesi.
Di atas adalah profil yang dapat diperiksa ketika database ditetapkan sebagai sesi di CodeIgniter. coba periksa SQL Query, pemanggilan metode session_start () membutuhkan waktu lebih dari 2 detik, yang menunjukkan bahwa kunci menyebabkan masalah. Kode CodeIgniter Controller yang digunakan untuk mereproduksi di atas ditunjukkan di bawah ini.
<?php class Welcome extends CI_Controller { function __construct(){ parent::__construct(); $this->load->library('session'); } public function index() { sleep(1); $this->load->view('welcome_message'); } }
Kodenya session_start dan session_write_close tersembunyi.
Kesimpulan (Dalam Mengatasi Kegagalan)
Sejauh ini, saya mencoba membuat dan memecahkan masalah yang disebabkan oleh Session Lock. Melalui proses ini, Anda dapat memperoleh rekomendasi berikut:
- Anda perlu mengetahui kebijakan penguncian yang digunakan oleh pengendali sesi anda.
- Pengendali sesi default PHP adalah file, yang mengunci Data Sesi.
- Penanganan Sesi Redis tidak menglock. Opsi memungkinkan Anda mengubah lock.
- Handler Sesi Memcached terlock. Opsi memungkinkan Anda mengubah kebijakan lock.
- Jika pengendali sesi menggunakan lock, Anda harus membuka locknya setelah memodifikasi Sesi. (session_write_close).
- Anda harus menyadari bahwa masalah konkurensi dapat terjadi jika pengendali sesi tidak menglock, dan Anda tidak boleh menyimpan data yang memerlukan integritas dalam Sesi.
Tutorial Membuat Dan Mengatasi Kegagalan Sesi PHP
Typography
- Smaller Small Medium Big Bigger
- Default Helvetica Segoe Georgia Times
- Reading Mode