Tutorial Berdasarkan Kategori

Grid List

Pada artikel kali ini saya akan membahas apa yang terjadi pada permasalahan 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 curl, 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

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.

Tutorial Membuat dan Mengatasi Kegagalan Sesi PHP

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.

Tutorial Membuat dan Mengatasi Kegagalan Sesi PHP

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);

 Tutorial Membuat dan Mengatasi Kegagalan Sesi PHP

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.

Tutorial Membuat dan Mengatasi Kegagalan Sesi PHP

 

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.

Tutorial Membuat dan Mengatasi Kegagalan Sesi PHP

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

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

Tutorial Membuat dan Mengatasi Kegagalan Sesi PHP

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

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.

sumber

Analisis Kinerja Berbasis Sampling Stacktrace

Tutorial APM

Pada artikel sebelumnya saya membahas, tentang Analisis Kinerja Berbasis Sampling Stacktrace karena transaksi menjalankan tugas yang relatif sederhana, daftar stacktrace dapat membantu anda memahami semua yang terjadi dalam sebuah method. Namun jika kita beramsusi bahwa transaksi yang berjalan untuk beberapa waktu yang lama dan memiliki sekitar 100 stacktrace yang dikumpulkan, maka akan sangat memakan waktu untuk memeriksa setiap stacktrace.
Apm Jennifer menyediakan dua pungsi tampilan yang berbeda dan dapat menampilkan analisis yang mudah dalam situasi seperti itu.

Summary Viewing
Summary Viewing dan menganalisis, meringkas panggilan dari setiap method yang menampilkan hasil dari chart setiap transaksi, ditampilkan sebagai chart mewakili method dalam stacktrace dan memiliki informasi sebagai berikut.

 Flame chart memiliki karakteristik sebagai berikut

  • Setiap warna menunjukkan  itu adalah method dari paket yang sama.
  • Ukuran luas persegi panjang adalah jumlah koleksi.
  • method di bagian bawah grafik adalah titik awal stacktrace.
  • method di bagian atas grafik adalah method yang sedang berjalan.

Berdasarkan fakta diatas, untuk menemukan method yang paling sering dipanggil selama periode tersebut, anda harus menemukan area dengan ukuran terbesar. kemungkinan method yang anda temukan merupakan penyebab utama selama ini (penggunaan CPU, penundaan waktu respons).

Sekarang, mari kita menganalisis keadaan dengan menggunakan fungsi stacktrace yang ditingkatkan oleh APM JENNIFER. dan mari kita periksa informasi detail transaksi yang lambat di jendela pop-up X-View.

Node yang tidak diprofilkan menempati sebagian besar waktu proses. Kita dapat melihat bahwa node yang tidak diprofile memiliki sub node yang disebut STACK-TRACE. Ini adalah tampilan dari kumpulan stacktrace berdasarkan setiap profil dan informasi waktu. gambar di atas menunjukkan bahwa 95 tumpukan jejak dikumpulkan di area tidak diprofilkan. sekarang, klik node STACK-TRACE untuk pindah ke tab stacktrace di mana grup tumpukan yang cocok dipilih secara otomatis.