ล่าสุด

Cache จัดการเองไม่ต้องใช้ plugin สำหรับ WordPress

Cache จัดการเองไม่ต้องใช้ plugin สำหรับ WordPress

สำหรับคนที่ทำเว็บไซท์โดยใช้ WordPress แล้วละก็คงทราบดีว่า หากเว็บได้รับความนิยมสูงแต่ตัวเองลง plugin ไว้เยอะปัญหาคือ server จะทำงานช้ามาก จนบางครั้งถึงกับ out of memory ไปเลย แม้จะเพิ่มหน่วยความจำหรือ RAM มากขึ้นแค่ไหน อีกไม่นานก็เจอปัญหานี้อีก

เนื่องจากการทำงานของ WordPress นั้น ทุกอย่างจะอาศัย Database เป็นหลัก มีการใช้ตารางฐานข้อมูล (table) เก็บค่าตัวแปรทักอย่าง ที่หนักหนาสาหัสก็คงเป็น table wp_post และ wp_postmeta (wp_ คือค่า prefix ที่ตั้งมาให้หากไม่มีการเปลี่ยนแปลงระหว่างติดตั้ง)

แค่บทความเพียง 1 บทความ ใน wp_post จะมีข้อมูลอยู่หลาย record แถมใน wp_postmeta จะมีไม่ต่ำกว่า 10 record นี่ไม่นับ wp_user กับ wp_usermata ก็ออกมาในทำนองเดียวกัน แถมหากมีการนับสถิติผู้ชมสำหรับบางธีม จะพบฐานข้อมูลในลักษณะเดียวกันอีกมากมาย

ดังนั้นจะเห็นได้ว่าแค่มีผู้เยี่ยมชมหนึ่งคน การประมวลผลจะต้องมีการเข้าถึงฐานข้อมูลตั้งแต่ส่วนหัว (Header) ส่วนหน้าแรก (index_standard แล้วแต่ธีม) ไปถึง sidebar จนกระทั่งถึง footer ซึ่งแต่ละส่วนจะมีการเรียกฟังก์ชั่นเพื่อการเข้าถึงฐานข้อมูลจำนวนมาก

ยิ่งหากมีการแสดงหมวดหมู่พร้อมจำนวนโพสท์ หรือตามแต่ละเดือนแล้วแสดงจำนวนโพสท์ ยิ่งต้องคำนวนมหาศาล หากมี menu แบบ drop down ไม่ว่าจะตรงส่วนหัวหรือส่วน footer ก็ยิ่งต้องประมวลผลจำนวนมาก เซอฟเฟอร์ไม่อืดก็ให้มันรู้ไป

แก้ปัญหาได้ด้วย cache

การใช้งาน cache ก็คือ หากมีผู้เยี่ยมชมเข้ามาก่อนหน้านี้ หลังจากประมวลผลต่างๆจากฐานข้อมูลแล้ว ก็เก็บผลต่างๆนั้นไว้ในรูปของ HTML แล้วถ้าบุคคลที่สองเข้ามาก็ไม่ต้องประมวลผลอีกแล้ว ส่ง HTML ตะกี้ไปให้ ถือเป็นการลดภาระหน่วยความจำและการเข้าถึงฐานข้อมูลไปอย่างมหาศาล

สำหรับเว็บใหญ่ๆแล้วคงไม่ต้องห่วงประเด็นนี้เพราะมีการทำ load balancing กันเรียบร้อย แต่ก็ต้องลงทุนสูงหน่อย แต่เว็บเพิ่งโตรายได้ไม่เยอะ อาจจะไม่มีกำลังทรัพย์พอที่จะทำแบบนั้น ก็ต้องพึ่ง cache แบบ plugin ที่มีให้เลือกมากมายหลายเจ้า อันไหนดีอันไหนเด่นก็ต้องลองกันไป

แต่ปัญหาหนึ่งที่พบของการใช้ cache ก็คือ ข้อมูลบางชนิดเพิ่ง update ไปก็อยากให้เห็นผลทันที ปรากฏว่าต้องรอให้ cache มันหมดอายุก่อน ซึ่งบางทีเราเองก็ไม่รู้ว่า cache แต่ละตัวจะบริหารจัดการอย่างไร บางทีเขียนบทความใหม่ไปแล้ว ยังเจอหน้าเก่าๆอยู่เป็นวันๆ พอจะปิด cache ก็ต้องไป update ไฟล์ .htacess กันให้วุ่นวาย

บางครั้ง uninstall plugin นั้นไปแล้ว ก็ยังเจอปัญหาเว็บไม่อัพเดท ไม่รู้ว่ามันเก็บไฟล์ cache ไว้ที่ไหน จะได้ตามไปลบทิ้ง หากันทั่ว server แล้วก็ไม่เจอ ดังนั้นบางทีการสร้าง cache แบบ manual อาจจะเป็นวิธีหนึ่งที่จะแก้ปัญหาคนที่พอมีความสามารถงมโค้ดเองได้บ้าง

Manual cache แก้ปัญหาได้ตรงจุดกว่า

การทำ cache เองในนั้นมึจุดเด่นคือ
– กำหนดเวลาการ refresh ได้เองได้ตามความต้องการ จุดไหน update บ่อยก็ตั้งเวลาน้อยๆ จุดไหนไม่ค่อยเปลี่ยนแปลงก็ตั้งเวลานานๆ
– กำหนดการสร้าง cache เฉพาะที่ได้ ไม่ต้องทำคลุมทุกไฟล์ หรือทุก request ที่เข้ามา สังเกตุจาก stat ว่าคนเข้าตรงไหนเยอะก็หา cache ไปครอบตรงส่วนที่มีการเข้าถึงฐานข้อมูลเยอะๆซะ
– อยากจะให้มัน refresh ทันที ก็แค่ลบไฟล์ cache ผ่าน ftp ที่เราเองรู้ว่าไฟล์อยู่ไหน พอมีผู้เยี่ยมชมเข้ามา cache ก็จะถูกสร้างทันที

จะสร้าง Cache แบบ Manual ให้ WordPress จะทำอย่างไร

อันดับแรกต้องกำหนดตำแหน่งการเก็บ cache ไฟล์ของเราก่อนว่าจะเก็บไว้ที่ไหน
โดยการเพิ่มตัวแปรระบุตำแหน่งที่จะเก็บ cache ของเราไว้ในไฟล์ wp-config.php ซึ่งอยู่ที่ public_html directoryดังนี้

/** Absolute path to the WordPress directory. */    <— หาให้เจอ
if ( !defined(‘ABSPATH’) )                <– ของเดิม
define(‘ABSPATH’, dirname(__FILE__) . ‘/’);    <— ของเดิม
define(‘MY_CACHEPATH’,ABSPATH.”/wp-content/themes/ชื่อ theme/my_cache/”);

จากนั้นไปที่ public_html/wp-content/themes/ชื่อ theme/ แล้วสร้าง directory ใหม่ชื่อว่า

my_cache

แล้วอย่าลืมตั้งค่าให้ directory attribute ให้สามารถเขียนอ่านไฟล์ได้ (777) โดยสามารถทำได้ง่ายๆผ่าน โปรแกรม FTP ทั่วๆ ไป

ถึงขั้นตอนนี้ก็ upload ไฟล์ wp-config.php กลับไปยัง server ทดสอบว่าทุกอย่างยังทำงานได้ปกติหรือไม่ หากมีข้อผิดพลาดเว็บไซท์ของคุณอาจจะไม่แสดงข้อมูลอะไรเลย ให้กลับมาตรวจสอบการพิมพ์ว่าถูกต้องครบถ้วนหรือไม่

อันดับต่อมาก็เลือกไฟล์ที่เราคิดว่ามีการประมวลผลหนักๆ และไม่มีเงื่อนไขอะไรที่แตกต่างกันสำหรับผู้เยี่ยมชมแต่ละคน ตัวอย่างเช่นหาก sidebar ของเรามีการแสดงบทความล่าสุด บทความยอดนิยม แสดงหมวดหมู่ต่างๆ พร้อมจำนวนโพสท์ในแต่ละโพส รวมทั้ง archive ต่างๆ นั่นแสดงว่ามีการประมวลผลข้อมูลเยอะ และไม่จำเป็นต้องไปอ่านข้อมูลในฐานข้อมูลทุกครั้งเพื่อนำมาแสดง เราก็อาจจะเลือก cache ให้ครอบคลุมทั้ง sidebar เลยก็ได้

ในที่นี้จะยกต้วอย่าง theme ของเว็บไซท์นี้ ซึ่งเนื้อหาของแต่ละบทความจะอยู่ในไฟล์ content-single.php ดังตัวอย่างนี้

 <?php /* Default template for displaying post content. */ ?>
<article <?php post_class(); ?>>
<header class=”post-header”>
<h1 class=”entry-title”>
<?php the_title(); ?>
</h1>
<?php mh_post_header(); ?>
</header>
<?php dynamic_sidebar(‘posts-1’); ?>
<div class=”entry clearfix”>
<?php mh_post_content_top(); ?>
<?php mh_post_content(); ?>
<?php mh_post_content_bottom(); ?>
</div>
<?php if (has_tag()) : ?>
<div class=”post-tags clearfix”>
<?php the_tags(‘<ul><li>’,'</li><li>’,'</li></ul>’); ?>
</div>
<?php endif; ?>
<?php dynamic_sidebar(‘posts-2’); ?>
</article>

สังเกตได้ว่า sideber ด้านขวามือ จะมีการเรียก function dynamic_sidebar(‘posts-2’); ซึ่งทดสอบง่ายๆ ด้วยการเขียนข้อความบางอย่างเข้าไปเช่น “test” แล้วลอง upload ดูว่าปรากฏคำนั้นๆ ตรงตำแหน่งหรือไม่ วิธีการนี้เหมาะสำหรับคนที่ต้องการทดสอบกับ server จริงๆเลย ไม่ต้องการลงโปรแกรมอะไรต่างๆเพื่อทดสอบที่เครื่องตัวเองเหมือนโปรแกรมเมอร์ทั่วไป

หลังจากเราได้ตำแหน่งฟังก์ชั่นที่เราต้องการประหยัดทรัพยากรการประมวลผลแล้ว เราก็ทำการใส่ cache ครอบให้กับคำสั่งบรรทัดนี้ ตามตัวอย่างด้านล่าง

<? $cacheFile = MY_CACHEPATH.’post_sidebar.cache’;
$gencache = true;
if(file_exists($cacheFile))
{ $gencache = false;
$nTime = $_SERVER[‘REQUEST_TIME’] – 1800;
$cTime = filemtime($cacheFile);
if($nTime > $cTime)
{
$gencache = true;
}else
{
include $cacheFile;
}
}
if($gencache)
{
ob_start();

dynamic_sidebar(‘posts-2’);     <– code เดิม

$fp = fopen($cacheFile, ‘w+’);
fwrite($fp, ob_get_contents());
fclose($fp);
ob_end_flush();
}

หลักการทำงานก็คือ เมื่อถึงหน้านี้ จะมีการไปเช็คว่ามีไฟล์ cache ของหน้านี้หรือไม่ ถ้ามีก็ให้ตรวจสอบว่าถึงเวลาต้องสร้างใหม่หรือยัง ถ้ายังไม่ถึงเวลา ก็เอาของเก่าที่ประมวลผลแล้วส่งไปให้ผู้เยี่ยมชม

แต่หากถึงเวลาต้องประมวลผลใหม่ ก็เรียกไปยังฟังก์ชั่นนั้นๆ ส่งไปให้ผู้เยี่ยมชมและบันทึกลงไฟล์ไว้ด้วย ดังนั้นประเด็นสำคัญจึงอยู่ที่การตั้งเวลาให้เหมาะสม เนื้อหาไหนต้อง update บ่อยๆ ก็อาจจะตั้งซัก 5 นาที บางอย่างก็ทุกๆ 10 นาที บางเนื้อหาก็ทุกๆ 1 ชั่วโมง หรือบางอย่างไม่ค่อย update ก็ทำวันละครั้งเป็นต้น

เราสามารถปรับเปลี่ยนการตั้งเวลาได้เองให้เหมาะสมกับงาน โดยตัวเลขสีน้ำเงินด้านบนจะมีหน่วยเป็นวินาที ดังนั้น

300 = 5 นาที
600 = 10 นาที
1800 = 30 นาที

3600 = 1 ชั่วโมง
21,000 = 6 ชั่วโมง
86,400 = 24 ชั่วโมง

การตั้งเวลาไม่ต้องไปสนใจว่าหากทุกอย่างตั้งเป็นตัวเลขกลมๆ แล้วในบางจังหวะต้องมีการสร้าง cache ใหม่พร้อมๆกันแล้ว server จะทำงานหนัก เนื่องจาก cache จะสร้างใหม่หรือไม่จะขึ้นอยู่กับว่า ในตอนนั้นมีผู้เยี่ยมชมเข้ามาตรงกับ cache ไฟล์นั้นๆหรือไม่ เพราะบางครั้งอาจจะเลยเวลาไปนานแล้ว แต่ยังไม่มีผู้เยี่ยมชม cache ใหม่ก็จะยังไม่มีการสร้างจนกว่าจะมีผู้เยี่ยมชมคนต่อไปเข้ามา

การตั้งชื่อ cache ไฟล์ (ตัวอักษรสีชมพูตามตัวอย่าง) ก็ควรจะระบุได้ว่าคือไฟล์ไหน กรณีไหน เพื่อความสะดวกในการทดสอบ หรือบางครั้งเราต้องการสร้าง cache ใหม่ในทันที เช่นอาจจะตั้งชื่อว่า main_header สำหรับ header.php หรือตั้งว่า main_sidebar post_sidebar เป็นต้น โดยไม่ควรจะมีชื่อซ้ำกัน อาจจะมีการตั้งชื่อโดยใส่ตัวแปรเข้าไปสำหรับกรณีที่มีการประมวลผลหลายๆหน้าด้วยก็ได้

การครอบ cache ก็ไม่จำเป็นต้องครอบเฉพาะส่วนที่เป็นโค้ดอย่างเดียว เราอาจจะครอบรวม HTML ไปด้วยเลยก็ได้เช่นตัวอย่างนี้

 <?php global $cp_options; ?>

<div class=”footer”>

<?             $cacheFile = MY_CACHEPATH.’footer_manu.cache’;
$gencache = true;
if(file_exists($cacheFile)) {
$gencache = false;
$nTime = $_SERVER[‘REQUEST_TIME’] – 7200;
$cTime = filemtime($cacheFile);
if($nTime > $cTime)
{
$gencache = true;
}else
{
include $cacheFile;
}

}
if($gencache)
{
ob_start();

?>

<div class=”footer_menu”>

<div class=”footer_menu_res”>

<?php wp_nav_menu( array( ‘theme_location’ => ‘secondary’, ‘container’ => false, ‘menu_id’ => ‘footer-nav-menu’, ‘depth’ => 1, ‘fallback_cb’ => false ) ); ?>

<div class=”clr”></div>

</div><!– /footer_menu_res –>

</div><!– /footer_menu –>

<?
$fp = fopen($cacheFile, ‘w+’);
fwrite($fp, ob_get_contents());
fclose($fp);
ob_end_flush();
}

?>

<div class=”footer_main”>

ตัวอย่างข้างต้นเป็นการใส่ cache ให้กับ menu บริเวณในส่วนของ footer เนื่องจากมีการประมวลผมเมนูที่ซับซ้อน หลายชั้นซึ่งต้องมีการอ่านข้อมูลจากฐานข้อมูลจำนวนมาก

จากนั้นก็ upload ไฟล์ขึ้นไปทดสอบ เรียกหน้าเว็บที่มีโค้ดนี้อยู่ผ่าน browser แล้วท่านจะเห็นไฟล์ cache โผล่มาใน directory ที่เก็บ cache ไฟล์เหล่านี้ไว้ หากยังไม่โผล่ให้ตรวจสอบว่าได้เปิดโหมด เขียนให้กับ directory และไฟล์ใน directory นี้แล้วหรือยัง

หากท่านต้องการให้ cache update ทันทีโดยไม่ต้องการรอรอบเวลาที่ตั้งเอาไว้ ทำได้ง่ายๆ เพียงลบไฟล์ cache นั้นทิ้ง ระบบก็จะประมวลผลใหม่ในทันทีที่มีผู้เยี่ยมชมรายใหม่เข้ามา

หากลองใช้จนชำนาญแล้ว ท่านจะพบว่าจะใส่ cache ให้ส่วนไหนก็แค่เพียงแค่ดำเนินการ 3 ขั้นตอนคือ
– copy โค้ดส่วนหัว และส่วนท้ายมาครอบ
– เปลี่ยนชื่อ cache ให้สอดคล้อง
– ตั้งเวลา (เปลี่ยนตัวเลข)

เราสามารถลดเวลาในการเข้าถึงฐานข้อมูลได้อย่างมหาศาลสำหรับเว็บขนาดปานกลาง แต่หากเว็บมี traffic มากกว่านี้ โหลดจะไปตกอยู่กับการเขียนอ่านไฟล์ cache เพิ่มขึ้น ซึ่งคงต้องหาวิธีอื่นต่อไป

Advertisment

Leave a comment