aViệ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 :
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 )
$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 .
(i-php.net)