สรุปสั้น ๆ
API หรือ Application Programming Interface คือช่องทางที่แอปพลิเคชันใช้ในการติดต่อกัน เพื่อเข้าถึงข้อมูลหรือบริการที่ต้องการเรียกใช้ อย่างในการทำเว็บไซต์หรือแอปพลิเคชันก็จะมี API ที่ Frontend ใช้ติดต่อ Backend อย่างเช่น REST API และ GraphQL
เขียนโดย
Sutthinai Boonyingyongchai
MidLevel Software Developer
บทความนี้ตีพิมพ์ และ เผยแพร่เมื่อ 11 สิงหาคม 2566
API Caching
Caching คือการเก็บข้อมูลที่ถูกสร้างหรือคำนวณเอาไว้เพื่อเรียกในครั้งถัด ๆ ไปได้เร็วขึ้น โดยข้อมูลที่เก็บเอาไว้นี้เรียกว่า Cache ซึ่งในกรณีของ API ก็สามารถทำ Caching ได้เหมือนกัน ซึ่งจะช่วยลดการใช้ทรัพยากรเพื่อสร้างหรือคำนวณซ้ำ ๆ ลงได้
ก่อนมี Cache ต้อง Query จาก Database ทุกครั้ง
พอมี Cache เพิ่มมา ลดการ Query จาก Database เหลือแค่ครั้งที่ยังไม่มี Cache เก็บไว้เท่านั้น
Express.js API Caching
เพื่อให้เห็นภาพชัดขึ้น ในบทความนี้เราจะมาลองทำ Caching แบบง่าย ๆ ใน Express.js ที่เป็น Web Framework สำหรับ Node.js ตัวนึง โดเราจะโฟกัสไปที่การสร้าง Cache ให้กับ API แบบไว ๆ
เริ่มจากสร้าง Project ใหม่
โดยใช้คำสั่ง
npm init -y
ใส่ -y เพื่อบอกให้ npm ใช้ Default Config ให้หมดทุกอย่างโดยไม่ต้องถามเรา
จากนั้นติดตั้ง Express ด้วยคำสั่ง
npm install express
แล้วก็ติดตั้ง nodemon ไว้เพื่อความสะดวก จะได้ไม่ต้องรันใหม่เวลาแก้โค้ด
npm install --save-dev nodemon
เสร็จแล้วก็ไปแก้ไฟล์ package.json เพิ่มคำสั่งรันด้วย nodemon เข้าไปใน “scripts” ไฟล์ก็จะออกมาหน้าตาแบบนี้
"start:dev": "nodemon index.js"
สร้างไฟล์ index.js
ใส่โค้ด Express “Hello World” เข้าไป
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
เซฟให้เรียบร้อยแล้วรันด้วยคำสั่ง
npm run start:dev
แอปของเราก็จะถูกรันไว้ที่ Port 3000
ลองเปิดดู http://localhost:3000/ ผ่านเบราเซอร์หรือ Postman ก็ได้ จะเจอกับข้อความ “Hello World!”
Algorithm อันแสนซับซ้อน
สมมติว่ามี API ที่ต้องใช้เวลาประมวลผลนานมาก ๆ กว่าจะส่งข้อมูลกลับออกไปได้ โดยจะใช้การหน่วงด้วย setTimeout เป็นเวลา 5 วินาที สร้างเป็นฟังก์ชันชื่อว่า “getMagicWord” ที่ API ของเราต้องไปเรียกใช้เพื่อรีเทิร์นค่ากลับออกไป
const express = require('express')
const app = express()
const port = 3000
async function getMagicWord(param) {
await new Promise(resolve => setTimeout(resolve, 5000));
return 'Hello borntoDev!'
}
app.get('/', async (req, res) => {
const magicWord = await getMagicWord()
res.send(magicWord)
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
อย่าลืมกดเซฟโค้ดที่แก้ แล้วลองยิง API ดูอีกครั้งจะเห็นว่าใช้เวลากว่าจะได้รับ Response กลับมา เพิ่มจาก 10 ms ไปเป็น 5.02 s
ใส่ Caching แบบไว ๆ
อย่างที่พูดถึงไปก่อนนี้ว่าการเก็บ Cache ก็คือการเอาข้อมูลที่ถูกสร้างหรือประมวลผลแล้ว เก็บเอาไว้รอการเรียกใช้ในครั้งต่อ ๆ ไปโดยไม่ต้องประมวลผลซ้ำ เพื่อความชัดเจนเราจะสร้าง API ใหม่ GET /with-cache เพื่อทำ Caching
โดยการเก็บข้อมูล Cache นั้นแบบง่ายที่สุดก็คือสร้างเป็นตัวแปรขึ้นมาเก็บค่านั้นไว้ เวลาที่มี Request มาที่ API ก็เช็คว่าตัวแปรนั้นมีค่ารึเปล่าถ้ามีก็ส่งออกไปได้ทันที ถ้าไม่มีถึงค่อยไปเรียกฟังก์ชันที่ใช้ประมวลผลและเซ็ตค่าเก็บเข้าตัวแปร Cache
คราวนี้เปลี่ยนจากข้อความเป็น JSON เพื่อให้ดูข้อมูลง่ายขึ้น โดยที่
- “requestTimestamp” คือเวลาตอนที่ Server ได้รับ Request
- “getMagicWordTimestamp” คือเวลาตอนที่ฟังก์ชัน “getMagicWord” ทำงานเสร็จ
- “magicWord” คือข้อมูลที่เราต้องการ Cache
const express = require('express')
const app = express()
const port = 3000
let myMagicCache = null
async function getMagicWord(param) {
await new Promise(resolve => setTimeout(resolve, 5000));
return {
magicWord: 'Hello borntoDev!',
getMagicWordTimestamp: new Date().toTimeString()
}
}
app.get('/', async (req, res) => {
const magicWord = await getMagicWord()
res.send(magicWord)
})
app.get('/with-cache', async (req, res) => {
const requestTimestamp = new Date().toTimeString();
if (myMagicCache) {
res.send({ ...myMagicCache, requestTimestamp })
} else {
const magicWord = await getMagicWord()
myMagicCache = magicWord
res.send({ ...myMagicCache, requestTimestamp })
}
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
พอเราทำการยิงไปที่ http://localhost:3000/with-cache ในครั้งแรก จะสังเกตได้ว่าใช้เวลารอ 5.02 s โดย “getMagicWordTimestamp” จะเป็นเวลาหลังจาก “requestTimestamp” ประมาณ 5 วินาที
ลองยิงรอบที่ 2 เวลาจะลดลงเหลือเพียง 3 ms
ลองยิ่งรอบที่ 3 อีกซักครั้ง ก็จะเห็นว่าเวลายังเป็น 3 ms
จะเห็นว่าในครั้งที่ 2 และ 3 นั้น ไม่ว่าจะยิงตอนไหน (“requestTimestamp”) ค่าของ Cache ที่ได้ก็เป็นค่าแรกค่าเดิมอยู่ ยืนยันได้จาก “getMagicWordTimestamp” ที่เป็นค่าเดิมตลอดเลยนั่นเอง เพียงแค่นี้ก็พอจะนับได้ว่า API ของเรามีการใช้ Cache แบบเบื้องต้นสุด ๆ แล้วนั่นเอง
คำถามก่อนทำ Cache
ก่อนตัดสินใจลงมือทำ API Caching ลองดู 3 คำถามสั้น ๆ นี้ น่าจะช่วยให้มีแนวทางการพัฒนาที่ชัดเจนขึ้นได้
1) Cache อะไร ?
เพราะว่าการเก็บ Cache ก็ต้องใช้ทรัพยาของระบบเหมือนกัน เราควรดูจากความสำคัญของ API แต่ละเส้น รวมถึงความถี่ในการถูกเรียกใช้งาน จะได้ไม่ต้องเก็บ Cache ในเส้นที่ไม่จำเป็น
2) Cache ที่ไหน ?
เมื่อเราได้ลิสต์ของ API ที่เราต้องการ Cache แล้ว ก็มาดูกันต่อว่าเราจะเก็บข้อมูลไว้ที่ไหนดี
หลัก ๆ แล้วจะมีแบบ
- Memory: ก็คือเก็บใน RAM เพื่อความเร็วในการเรียกใช้
- Disk: ก็คือเก็บลง Database เพื่อให้มีพื้นที่สำหรับเก็บข้อมูลใหญ่ ๆ
3) Cache ยังไง ?
สุดท้ายที่เราต้องคิดก็คือจะเก็บ Cache ยังไง ให้เหมาะกับระบบเราที่สุด
- ขนาด/จำนวน: ของ Cache มีผลโดยตรงต่อ Server ของเรา ถ้าเก็บ Cache ขนาดใหญ่หรือเยอะเกินไป ก็ส่งผลต่อความเร็วในการเรียก Cache นั้นออกมาใช้งาน และต้องใช้ทรัพยากรของระบบเยอะในการเก็บ Cache
- การหมดอายุ: จะทำให้ Cache ที่เก่าถึงจุดนึงถูกลบออกไป เพื่อให้ระบบสร้างข้อมูลใหม่มาใส่แทน ซึ่งจะช่วยทั้งเรื่องความสดใหม่ของข้อมูล และลดการเก็บ Cache เก่า ๆ เอาไว้โดยไม่จำเป็นลงได้
หวังว่าบทความนี้จะช่วยให้ได้รู้จักกับ API Caching มากขึ้นนะครับ
ระบบฝึกทักษะ การเขียนโปรแกรม
ที่พร้อมตรวจผลงานคุณ 24 ชั่วโมง
- โจทย์ปัญหากว่า 200 ข้อ ที่รอท้าทายคุณอยู่
- รองรับ 9 ภาษาโปรแกรมหลัก ไม่ว่าจะ Java, Python, C ก็เขียนได้
- ใช้งานได้ฟรี ! ครบ 20 ข้อขึ้นไป รับ Certificate ไปเลย !!