Coding

Sử dụng session_set_save_handler để override session handle

 Việc scale (vertical) ứng dụng web sử dụng php  , có một vấn đề cần quan tâm hàng đầu là vấn đề sử lý session .

 
Khi scale php sẽ chạy trên các máy chủ khác nhau , vậy làm thế nào để các user khi login web app mà dùng chung được session trên nhiều server ?
 
Để làm được điều này chúng ta cần xử lý sao cho tất cả các máy chủ đều sử dụng chung một hệ thống quản lý session .
 
Hoặc đơn giản là sử dụng chung một session storage .
 
Mặc định trong php sẽ sử dụng file session handle các file chứa session sẽ nằm trong /tmp của mỗi server .
 
Điều này có thể gợi ý cho chúng ta việc share chung 1 vùng lưu trữ (ví dụ dùng NFS để share chung /tmp giữa các máy chủ).
 
Tuy nhiên cách này lại ảnh hưởng đến tốc độ truy xuất (vì phải qua mạng - sau đó là đến việc máy host session sẽ quá tải diskio).
 
Một hướng khác là sử dụng một db mysql chung để lưu session , thực tế thì cách này tạm được .
 
Để làm như vậy chúng ta cần override lại các hàm xử lý session của php
session_set_save_handler("open", "close", "read", "write", "destroy", "gc");
 
Sử dụng hàm session_set_save_handler để trỏ các call back function cần thiết , như vậy chúng ta cần viết lại 6 hàm open, close , read ,write ,destroy , gc .
 
tạm thời chúng ta viết tạm các hàm như sau :
<?php
function open($save_path, $session_name)
{
echo "open";
}
 
function close()
{
echo "close";
}
 
function read($id)
{
echo "read";
}
 
function write($id, $sess_data)
{
echo "write";
 
}
 
function destroy($id)
{
echo "destroy";
}
 
function gc($maxlifetime)
{
echo "gc";
}
 
session_set_save_handler("open", "close", "read", "write", "destroy", "gc");
// test thử phát
session_start();
 
?>
 
Chạy thử . kết quả : openread writeclose ...
 
Như vậy chúng ta thấy thứ tự của một quá trình đọc session .
 
Việc tiếp theo là implement mấy hàm trên vào mysql , memcached , file , hay bất kỳ một storage nào có thể dùng chung được là xong .
 
với file (cái này chỉ là làm lại những gì php đã làm :D )
<?php
$sess_save_path=".";
function open($save_path, $session_name)
{
global $sess_save_path;
 
$sess_save_path = $save_path;
return(true);
}
 
function close()
{
return(true);
}
 
function read($id)
{
global $sess_save_path;
 
$sess_file = "$sess_save_path/sess_$id";
return (string) @file_get_contents($sess_file);
}
 
function write($id, $sess_data)
{
global $sess_save_path;
 
$sess_file = "$sess_save_path/sess_$id";
if ($fp = @fopen($sess_file, "w")) {
$return = fwrite($fp, $sess_data);
fclose($fp);
return $return;
} else {
return(false);
}
 
}
 
function destroy($id)
{
global $sess_save_path;
 
$sess_file = "$sess_save_path/sess_$id";
return(@unlink($sess_file));
}
 
function gc($maxlifetime)
{
global $sess_save_path;
 
foreach (glob("$sess_save_path/sess_*") as $filename) {
if (filemtime($filename) + $maxlifetime < time()) {
@unlink($filename);
}
}
return true;
}
 
session_set_save_handler("open", "close", "read", "write", "destroy", "gc");
 
//test
session_start();
 
?>
 
Hay với mysql đại khái thế này :
function read($id)
{
$sql = "select * from `tb_session` where `session_id`=$id";
mysql_query($sql);
//....
}
 
function write($id, $sess_data)
{
$sql = "INSERT INTO `tb_session` (`session_id`, `updated_on`) VALUES ('{$this->session_id}', NOW())";
mysql_query($sql);
 
}
 
function destroy($id)
{
$sql = "Delete from `tb_session` where `session_id`=$id";
mysql_query($sql);
}
 
Hay với memcached :
function read($id)
{
return memcached::get("sessions/{$id}");
}
 
function write($id, $data)
{
return memcached::set("sessions/{$id}", $data, 3600);
}
 
function destroy($id)
{
return memcached::delete("sessions/{$id}");
}
 
Dùng memcache hay mysql cũng khá nhanh , mysql thì chạy bàng memory storage engine , bật query cache tướng đối lớn cho nhanh , có thể replication ra nhiều server để đẩy performed lên cao nữa nếu tải lớn .

0 Bình luận

Trở về
  • HTML5 Canvas
  • HTML5 Canvas

     The <canvas> element is used to draw graphics, on the fly, on a web page. Draw a red rectangle, a gradient rectangle,...