Pattern: Communication Through Common Data (รูปแบบ: การสื่อสารผ่านข้อมูลร่วม)

รูปแบบ communication ที่ครอบคลุม implementation มากมายคือ communication through common data pattern นี้ใช้เมื่อ microservice ตัวหนึ่งวางข้อมูลไว้ในตำแหน่งที่กำหนดไว้ และอีก microservice หนึ่ง (หรืออาจหลาย microservice) นำข้อมูลนั้นไปใช้ อาจง่ายเพียงแค่ microservice ตัวหนึ่งวางไฟล์ไว้ในตำแหน่งหนึ่ง แล้วในภายหลัง microservice อีกตัวหนึ่งมาหยิบไฟล์นั้นไปทำอะไรบางอย่าง integration style นี้เป็น asynchronous โดยธรรมชาติ

ตัวอย่างของ style นี้ดูได้ใน Figure 4-6 ที่ New Product Importer สร้างไฟล์ที่จะถูกอ่านโดย Inventory และ Catalog microservice ที่ downstream

bms2 0406

Figure 4-6. microservice ตัวหนึ่งเขียนไฟล์ออกมาให้ microservice อื่น ๆ นำไปใช้

pattern นี้ในบางแง่เป็น inter-process communication pattern ทั่วไปที่พบบ่อยที่สุดที่คุณจะเห็น แต่บางครั้งเราก็ไม่ได้มองว่ามันเป็น communication pattern เลย ผมคิดว่าส่วนใหญ่เป็นเพราะการสื่อสารระหว่างโปรเซสนั้นมักอ้อมจนสังเกตได้ยาก

Implementation (การ Implement)

ในการ implement pattern นี้ คุณต้องมี persistent store สำหรับข้อมูลบางแบบ filesystem ในหลาย ๆ กรณีก็เพียงพอแล้ว ผมเคยสร้างระบบมากมายที่แค่ scan filesystem เป็นระยะ สังเกตว่ามีไฟล์ใหม่ปรากฏขึ้น แล้วตอบสนองตามนั้น คุณจะใช้ distributed memory store ที่แข็งแกร่งบางแบบก็ได้เช่นกัน สิ่งที่ควรสังเกตคือ microservice downstream ใด ๆ ที่จะทำงานบนข้อมูลนี้จะต้องมีกลไกของตัวเองในการระบุว่ามีข้อมูลใหม่พร้อมใช้งาน polling เป็นวิธีแก้ปัญหาที่พบบ่อยสำหรับเรื่องนี้

ตัวอย่างทั่วไปสองแบบของ pattern นี้คือ data lake และ data warehouse ทั้งสองแบบนี้มักถูกออกแบบมาเพื่อช่วยประมวลผลข้อมูลปริมาณมาก แต่ก็อาจกล่าวได้ว่าอยู่คนละขั้วกันในเรื่อง coupling ด้วย data lake แหล่งข้อมูลต่าง ๆ อัปโหลด raw data ในรูปแบบใดก็ได้ตามที่เห็นสมควร และ consumer ปลายทางของ raw data นี้คาดว่าจะรู้วิธีประมวลผลข้อมูลเอง ส่วน data warehouse ตัว warehouse เองเป็น structured data store microservice ที่ push ข้อมูลไปยัง data warehouse ต้องรู้โครงสร้างของ data warehouse ถ้าโครงสร้างเปลี่ยนไปแบบ backward-incompatible producer เหล่านี้ก็ต้องถูกอัปเดตตาม

ทั้ง data warehouse และ data lake มีสมมติฐานว่า flow ของข้อมูลเป็นทิศทางเดียว microservice ตัวหนึ่ง publish ข้อมูลไปยัง common data store และ consumer downstream อ่านข้อมูลนั้นแล้วดำเนินการที่เหมาะสม unidirectional flow แบบนี้ช่วยให้คิดตาม flow ของ ข้อมูล ได้ง่ายขึ้น implementation ที่มีปัญหามากกว่าคือการใช้ shared database ที่ microservice หลายตัวทั้งอ่านและเขียนไปยัง data store เดียวกัน ซึ่งเป็นตัวอย่างที่เราพูดถึงใน Chapter 2 ตอนที่เราสำรวจ common coupling — Figure 4-7 แสดงทั้ง Order Processor และ Warehouse ที่อัปเดต record เดียวกัน

Order Processor and Warehouse both update the same row in the order table

Figure 4-7. ตัวอย่างของ common coupling ที่ทั้ง Order Processor และ Warehouse อัปเดต order record เดียวกัน

Advantages (ข้อดี)

pattern นี้ implement ได้ง่ายมาก โดยใช้เทคโนโลยีที่เข้าใจกันทั่วไป ถ้าคุณอ่านหรือเขียนไฟล์ได้ หรืออ่านและเขียน database ได้ คุณก็ใช้ pattern นี้ได้ การใช้เทคโนโลยีที่แพร่หลายและเข้าใจกันดียังช่วยให้เกิด interoperability ระหว่างระบบประเภทต่าง ๆ ได้ รวมถึงแอปพลิเคชัน mainframe รุ่นเก่าหรือผลิตภัณฑ์ซอฟต์แวร์แบบ customizable off-the-shelf (COTS) ปริมาณข้อมูลก็ไม่ค่อยเป็นปัญหาเช่นกัน ถ้าคุณกำลังส่งข้อมูลจำนวนมากในครั้งเดียว pattern นี้ก็ทำงานได้ดี

Disadvantages (ข้อเสีย)

microservice ที่ consume downstream มักจะรู้ว่ามีข้อมูลใหม่ต้องประมวลผลผ่านกลไก polling บางแบบ หรือไม่ก็ผ่าน timed job ที่ trigger เป็นระยะ นั่นหมายความว่ากลไกนี้ไม่น่าจะมีประโยชน์ในสถานการณ์ที่ต้องการ low-latency แน่นอนว่าคุณสามารถผสม pattern นี้กับการ call แบบอื่นเพื่อแจ้ง microservice downstream ว่ามีข้อมูลใหม่พร้อมใช้งานได้ เช่น ผมอาจเขียนไฟล์ไปยัง shared filesystem แล้วส่ง call ไปยัง microservice ที่สนใจเพื่อแจ้งว่ามีข้อมูลใหม่ที่มันอาจต้องการ วิธีนี้ช่วยลดช่องว่างระหว่างการ publish ข้อมูลกับการประมวลผลข้อมูลได้ แต่โดยทั่วไปแล้ว ถ้าคุณใช้ pattern นี้กับข้อมูลปริมาณมาก low latency ก็ไม่น่าจะเป็นสิ่งที่คุณให้ความสำคัญสูงในรายการความต้องการอยู่แล้ว ถ้าคุณสนใจส่งข้อมูลปริมาณมากและให้ประมวลผลแบบ "real time" มากขึ้น การใช้เทคโนโลยี streaming อย่าง Kafka จะเหมาะสมกว่า

ข้อเสียใหญ่อีกอย่างหนึ่ง และเป็นสิ่งที่น่าจะเห็นได้ชัดถ้าคุณจำการสำรวจ common coupling ใน Figure 4-7 ได้ คือ common data store กลายเป็นแหล่งของ coupling ที่อาจเกิดขึ้น ถ้า data store นั้นเปลี่ยนโครงสร้างในรูปแบบใดรูปแบบหนึ่ง มันสามารถทำให้การสื่อสารระหว่าง microservice พังได้

ความแข็งแกร่งของการสื่อสารยังขึ้นอยู่กับความแข็งแกร่งของ data store เบื้องหลังด้วย นี่ไม่ใช่ข้อเสียโดยตรง แต่เป็นสิ่งที่ควรตระหนักถึง ถ้าคุณวางไฟล์ไว้บน filesystem คุณอาจต้องมั่นใจว่า filesystem เองจะไม่ล้มเหลวในรูปแบบแปลก ๆ

Where to Use It (ควรใช้เมื่อไหร่)

จุดที่ pattern นี้โดดเด่นจริง ๆ คือการช่วยให้เกิด interoperability ระหว่างโปรเซสที่อาจมีข้อจำกัดว่าใช้เทคโนโลยีอะไรได้บ้าง การให้ระบบเก่าคุยกับ GRPC interface ของ microservice คุณหรือ subscribe Kafka topic ของมันอาจสะดวกกว่าจากมุมมองของ microservice แต่ไม่ใช่จากมุมมองของ consumer ระบบเก่าอาจมีข้อจำกัดว่าใช้เทคโนโลยีอะไรได้บ้าง และอาจมีต้นทุนการเปลี่ยนแปลงสูง ในทางกลับกัน แม้แต่ระบบ mainframe เก่า ๆ ก็ควรอ่านข้อมูลจากไฟล์ได้ แน่นอนว่าทั้งหมดนี้ขึ้นอยู่กับการใช้เทคโนโลยี data store ที่รองรับกันอย่างแพร่หลาย ผมอาจ implement pattern นี้โดยใช้อะไรอย่าง Redis cache ก็ได้เช่นกัน แต่ mainframe เก่าของคุณคุยกับ Redis ได้ไหมล่ะ?

จุดแข็งสำคัญอีกอย่างของ pattern นี้คือการแชร์ข้อมูลปริมาณมาก ถ้าคุณต้องส่งไฟล์ขนาดหลายกิกะไบต์ไปยัง filesystem หรือโหลดข้อมูลหลายล้านแถวเข้า database pattern นี้คือทางเลือกที่ใช่