เกริ่นนำกันก่อนนะครับ หลายๆคนที่เริ่มทำ Web Scale พวก Load Balancer , HA ต่างๆ ปัญหาแรกๆที่เจอเลยก็น่าจะเป็นเรื่องของ Session หลุดเพราะลืมนึกถึง Application ที่มีการใช้งาน Session โดย default แล้ว session ก็จะเกาะอยู่ใน Web Server ของใครของมัน พอเวลา Load Balancer ทำการกระจายโหลดไปยัง Web Server เครื่องอื่นๆก็จะทำให้ session หลุด วิธีแก้ที่ผมพบเจอก็มีอยู่ 2 ทางคือ
1 ) ทำ Load Balance ในโหมด Sticky หรือพูดง่ายๆคือหากมี Client เชื่อมมาแล้ว server load balance เลือกให้เลยว่าคนนี้เข้าเครื่องไหน ก็จะเข้า web server เครื่องเดิมตลอดทำให้ session ไม่หลุด แต่ในความเห็นส่วนตัวของผมนั้นมองว่าไม่ค่อยเวิร์ค เพราะ Load Balance จะต้องเพิ่มกระบวนการเช็คในส่วนนี้ทำให้มี Overhead ต่างๆเข้ามาอีก
2) แชร์ session ไว้ที่เดียวและให้ Web Server เข้ามาอ่าน Session ที่เดียวกันวิธีนี้ผมจะมานำเสนอในบทความนี้ครับ ซึ่งช่วงแรกๆผมเคยทำการ Share ผ่าน NFS และ mount path Session มาใช้งาน ปัญหาก็คือไฟล์ session ถูกเก็บบน Disk และไหนจะมีเรื่องของ Overhead ของ NFS อีกมันก็เลยช้าครับ เลยเปลี่ยนมาเป็น Redis ซึ่งเป็น key value Storage ข้อมูลจะถูก Store ไว้บนแรมทำให้เร็วกว่า NFS หลายเท่า ผมเลยเปลี่ยนมาเป็น Redis จนถึงปัจุบันก็ยังใช้ redis เก็บ session เป็นหลักครับ
เครื่อสำหรับการทดลอง
การติดตั้ง Redis Server (SV2)
ตั้ง Password เพื่อความปลอดภัยโดยค้นหา requirepass ปกติถ้าติดตั้งผ่าน Package Install ไฟล์ config จะอยู่ที่ /etc/redis.conf และตั้ง Password ได้เลยครับ ในที่นี้ผมตั้ง Password ว่า Putter และตั้งค่า Bind เพื่อให้รอ connect จากเครื่องอื่นๆ ในที่นี้ผมใส่ 0.0.0.0 ไว้เพื่อทดสอบเท่านั้น หากใช้งานใน Production จริงควร Allow เฉพาะ IP Addess ของเครื่องที่จะมา connect เท่านั้น
หลังจากนั้น start service และทดสอบ access เข้า redis server
ตั้งค่า php.ini เพื่อเก็บ Session ไว้ที่ Redis (SV1)
ติดตั้ง redis extension
2) แชร์ session ไว้ที่เดียวและให้ Web Server เข้ามาอ่าน Session ที่เดียวกันวิธีนี้ผมจะมานำเสนอในบทความนี้ครับ ซึ่งช่วงแรกๆผมเคยทำการ Share ผ่าน NFS และ mount path Session มาใช้งาน ปัญหาก็คือไฟล์ session ถูกเก็บบน Disk และไหนจะมีเรื่องของ Overhead ของ NFS อีกมันก็เลยช้าครับ เลยเปลี่ยนมาเป็น Redis ซึ่งเป็น key value Storage ข้อมูลจะถูก Store ไว้บนแรมทำให้เร็วกว่า NFS หลายเท่า ผมเลยเปลี่ยนมาเป็น Redis จนถึงปัจุบันก็ยังใช้ redis เก็บ session เป็นหลักครับ
เครื่อสำหรับการทดลอง
- sv1@172.16.209.136 : Web Server (NGINX+PHP-FPM)
- sv2@172.16.209.137 : Redis Server
การติดตั้ง Redis Server (SV2)
yum -y install epel-release yum -y update yum -y install redis
ตั้ง Password เพื่อความปลอดภัยโดยค้นหา requirepass ปกติถ้าติดตั้งผ่าน Package Install ไฟล์ config จะอยู่ที่ /etc/redis.conf และตั้ง Password ได้เลยครับ ในที่นี้ผมตั้ง Password ว่า Putter และตั้งค่า Bind เพื่อให้รอ connect จากเครื่องอื่นๆ ในที่นี้ผมใส่ 0.0.0.0 ไว้เพื่อทดสอบเท่านั้น หากใช้งานใน Production จริงควร Allow เฉพาะ IP Addess ของเครื่องที่จะมา connect เท่านั้น
หลังจากนั้น start service และทดสอบ access เข้า redis server
redis-cli -h 172.16.209.137 redis 172.16.209.137:6379> keys * (error) ERR operation not permitted redis 172.16.209.137:6379> AUTH Putter OK redis 172.16.209.137:6379> keys * (empty list or set) redis 172.16.209.137:6379>จากการทดสอบจะเห็นว่าสามารถ Access เข้าเซิฟเวอร์ของ redis ได้และผมได้ AUTH ด้วย password ที่ผมตั้งไว้หลังจากนั้นลองโชว์ข้อมูลด้วยคำสั่ง keys * เสร็จสิ้นการติดตั้ง Redis Server สำหรับเก็บ Session
ตั้งค่า php.ini เพื่อเก็บ Session ไว้ที่ Redis (SV1)
ติดตั้ง redis extension
pecl install redisและนำ extension=redis.so ไปใส่ไว้ใน php.ini ด้วย หลังจากนั้นทดสอบเข้า phpinfo เพื่อเช็ค extension
โดยปกติ php จะเก็บ session ไว้ที่ /var/lib/php/session
ต่อไปเป็นการเปลี่ยนการเก็บ Session ให้ไปฝากไว้ที่ Redis ครับ แก้ไฟล์ php.ini ตามนี้
ต่อไปเป็นการเปลี่ยนการเก็บ Session ให้ไปฝากไว้ที่ Redis ครับ แก้ไฟล์ php.ini ตามนี้
session.save_handler = redis session.save_path = "tcp://172.16.209.137:6379?auth=Putter"เสร็จแล้วให้ restart web server ครับ ทดสอบใช้งาน session
หากนำไปใช้งานใน Production ควรวาง Redis Server ไว้เป็น Private Zone และ Allow เฉพาะ IP Web Server ที่จะ access เท่านั้นนะครับ และต้องเพิ่มในส่วนของการทำ fail over ป้องกัน redis เสียหายครับ ไว้บทความหน้าจะมาเขียนรายละเอียดการทำ Redis Cluster ต่อให้อีกทีครับ