เอกสารนี้แปลโดย AI หากมีข้อมูลที่ไม่ถูกต้อง โปรดดูเวอร์ชันภาษาอังกฤษ
ในสภาพแวดล้อมแบบโหนดเดี่ยว ปลั๊กอินมักจะสามารถตอบสนองความต้องการได้ผ่านสถานะภายในโปรเซส, เหตุการณ์ หรืองานต่าง ๆ ครับ/ค่ะ แต่ในโหมดคลัสเตอร์ ปลั๊กอินเดียวกันอาจทำงานพร้อมกันบนหลายอินสแตนซ์ ซึ่งนำไปสู่ปัญหาทั่วไปดังต่อไปนี้:
NocoBase core ได้เตรียมอินเทอร์เฟซมิดเดิลแวร์หลายประเภทไว้ล่วงหน้าในเลเยอร์แอปพลิเคชัน เพื่อช่วยให้ปลั๊กอินสามารถนำความสามารถที่รวมเป็นหนึ่งเดียวกลับมาใช้ซ้ำได้ในสภาพแวดล้อมแบบคลัสเตอร์ ส่วนต่อไปนี้จะแนะนำวิธีการใช้งานและแนวทางปฏิบัติที่ดีที่สุดสำหรับแคช, การส่งข้อความแบบซิงโครนัส, คิวข้อความ และ Distributed Lock พร้อมอ้างอิงโค้ดต้นฉบับประกอบครับ/ค่ะ
สำหรับข้อมูลที่ต้องการจัดเก็บในหน่วยความจำ ขอแนะนำให้ใช้คอมโพเนนต์แคชที่มาพร้อมกับระบบในการจัดการครับ/ค่ะ
app.cacheCache มีการดำเนินการพื้นฐาน เช่น set/get/del/reset และยังรองรับ wrap กับ wrapWithCondition เพื่อห่อหุ้มตรรกะการแคช รวมถึงเมธอดแบบกลุ่ม (batch methods) เช่น mset/mget/mdel ด้วยครับ/ค่ะttl (time-to-live) ให้เหมาะสม เพื่อป้องกันการสูญหายของแคชเมื่ออินสแตนซ์รีสตาร์ทครับ/ค่ะตัวอย่าง: การเริ่มต้นและการใช้งานแคชใน ปลั๊กอิน-auth
หากสถานะในหน่วยความจำไม่สามารถจัดการด้วย Distributed Cache ได้ (เช่น ไม่สามารถ Serialize ได้) เมื่อสถานะมีการเปลี่ยนแปลงจากการดำเนินการของผู้ใช้ จำเป็นต้องแจ้งการเปลี่ยนแปลงนั้นไปยังอินสแตนซ์อื่น ๆ ผ่านสัญญาณซิงค์ เพื่อรักษาความสอดคล้องของสถานะครับ/ค่ะ
sendSyncMessage ไว้แล้ว ซึ่งภายในจะเรียกใช้ app.syncMessageManager.publish และเพิ่ม Prefix ระดับแอปพลิเคชันให้กับ Channel โดยอัตโนมัติ เพื่อหลีกเลี่ยงข้อขัดแย้งของ Channel ครับ/ค่ะpublish สามารถระบุ transaction ได้ ข้อความจะถูกส่งหลังจากที่ Database Transaction ได้รับการ Commit แล้ว เพื่อให้มั่นใจว่าสถานะและข้อความมีความสอดคล้องกันครับ/ค่ะhandleSyncMessage โดยสามารถ Subscribe ได้ในช่วง beforeLoad ซึ่งเหมาะอย่างยิ่งสำหรับสถานการณ์เช่น การเปลี่ยนแปลงการกำหนดค่า หรือการซิงค์ Schema ครับ/ค่ะตัวอย่าง: ปลั๊กอิน-data-source-main ใช้ข้อความซิงค์เพื่อรักษาความสอดคล้องของ Schema ในหลายโหนด
การกระจายข้อความเป็นคอมโพเนนต์พื้นฐานของสัญญาณซิงค์ และยังรองรับการใช้งานโดยตรงด้วยครับ/ค่ะ เมื่อต้องการกระจายข้อความระหว่างอินสแตนซ์ สามารถทำได้ผ่านคอมโพเนนต์นี้ครับ/ค่ะ
app.pubSubManager.subscribe(channel, handler, { debounce }) สามารถใช้เพื่อ Subscribe Channel ระหว่างอินสแตนซ์ได้ ตัวเลือก debounce ใช้สำหรับการลดการสั่นไหว (debouncing) เพื่อป้องกันการเรียก Callback ซ้ำบ่อยครั้งที่เกิดจากการกระจายข้อความซ้ำซ้อนครับ/ค่ะpublish รองรับ skipSelf (ค่าเริ่มต้นคือ true) และ onlySelf เพื่อควบคุมว่าข้อความจะถูกส่งกลับไปยังอินสแตนซ์ปัจจุบันหรือไม่ครับ/ค่ะตัวอย่าง: ปลั๊กอิน-async-task-manager ใช้ PubSub เพื่อกระจายเหตุการณ์ยกเลิกงาน
คิวข้อความใช้สำหรับจัดกำหนดการงานแบบอะซิงโครนัส เหมาะสำหรับการจัดการการดำเนินการที่ใช้เวลานานหรือสามารถลองใหม่ได้ครับ/ค่ะ
app.eventQueue.subscribe(channel, { idle, process, concurrency }) โดย process จะคืนค่าเป็น Promise และสามารถใช้ AbortSignal.timeout เพื่อควบคุมการหมดเวลาได้ครับ/ค่ะpublish จะเพิ่ม Prefix ชื่อแอปพลิเคชันโดยอัตโนมัติ และรองรับตัวเลือกต่าง ๆ เช่น timeout, maxRetries โดยค่าเริ่มต้นจะใช้ Adapter ของคิวในหน่วยความจำ แต่สามารถเปลี่ยนไปใช้ Adapter แบบขยาย เช่น RabbitMQ ได้ตามความต้องการครับ/ค่ะตัวอย่าง: ปลั๊กอิน-async-task-manager ใช้ EventQueue เพื่อจัดกำหนดการงาน
เมื่อต้องการหลีกเลี่ยง Race Condition สามารถใช้ Distributed Lock เพื่อทำการดำเนินการแบบอนุกรม (serialize) ในการเข้าถึงทรัพยากรได้ครับ/ค่ะ
local ที่อิงตาม Process ให้ใช้งาน และสามารถลงทะเบียนการใช้งานแบบ Distributed เช่น Redis ได้ สามารถควบคุม Concurrency ได้ผ่าน app.lockManager.runExclusive(key, fn, ttl) หรือ acquire/tryAcquire ครับ/ค่ะttl ใช้สำหรับเป็นกลไกสำรองในการปลดล็อก เพื่อป้องกันไม่ให้ Lock ถูกถือครองตลอดไปในกรณีที่เกิดข้อผิดพลาดครับ/ค่ะตัวอย่าง: ปลั๊กอิน-data-source-main ใช้ Distributed Lock เพื่อป้องกันกระบวนการลบฟิลด์
app.cache, app.syncMessageManager เพื่อหลีกเลี่ยงการนำตรรกะการสื่อสารข้ามโหนดมาใช้งานซ้ำในปลั๊กอินครับ/ค่ะtransaction.afterCommit (ซึ่ง syncMessageManager.publish มีมาให้ในตัวแล้ว) เพื่อรับประกันความสอดคล้องของข้อมูลและข้อความครับ/ค่ะtimeout, maxRetries, และ debounce ให้เหมาะสม เพื่อป้องกันไม่ให้เกิด Traffic Peak ใหม่ในสถานการณ์ที่ผิดปกติครับ/ค่ะด้วยความสามารถข้างต้น ปลั๊กอินจะสามารถแชร์สถานะ, ซิงค์การกำหนดค่า, และจัดกำหนดการงานระหว่างอินสแตนซ์ต่าง ๆ ได้อย่างปลอดภัย ตอบสนองความต้องการด้านความเสถียรและความสอดคล้องในสถานการณ์การ Deploy แบบคลัสเตอร์ครับ/ค่ะ