หลังจากที่อ่านหนังสือ Building Microservices ไปหลายรอบ
จึงทำการสรุปภาพรวมของหนังสือไว้นิดหน่อย
มีทั้งเรื่องความรู้พื้นฐาน ข้อดี ข้อเสีย สิ่งที่ต้องจัดการและรับมือ
รวมไปถึง use case และประสบการณ์ต่าง ๆ ที่น่าสนใจ
มาเริ่มกันเลย

Microservices คืออะไร ?

ในหนังสือให้คำจำกัดความไว้ว่า
มีขนาดเล็ก Autonomous service นั่นคือ
ทำงานจบภายใน service เดียว (Stand-alone)
ที่สำคัญมักจะทำงานร่วมกันอีกด้วย

โดยหลาย ๆ องค์กรบอกว่า
แนวคิดนี้ทำให้ ส่งมอบระบบงานได้รวดเร็วขึ้น
ตลอดจนสามารถนำเทคโนโลยีใหม่ ๆ เข้ามาใช้ได้ง่ายอีกด้วย
เนื่องจากการแบ่งออกเป็น service เล็ก ๆ นั้น
ทำให้มีความเป็นอิสระ ทั้งการตัดสินใจ พัฒนาและ deploy

เมื่อมีขนาดเล็กแล้ว ทำให้เรา focus กับมันได้ง่ายขึ้น
ทั้งจำนวน code ที่น้อยลง
การจัดการต่อการเปลี่ยนแปลงต่าง ๆ ง่ายขึ้น
แต่คำว่าเล็กนั้น มีคำถามว่า เล็กอย่างไร ?
เท่าไรถึงบอกว่าเล็ก ?
เล็กแล้วมีประโยชน์หรือโทษอะไรบ้าง ?

สิ่งที่น่าคิดคือ ถ้าแบ่งแล้วทำให้ทำงานยากขึ้น ช้าลงไปอีก
นั่นคือ มีแต่โทษหรือข้อเสีย แสดงว่า
นั่นคือปัญหานะ หรือทำผิดทางนั่นเอง 
ลองหยุดดูปัญหา แล้วแก้ไขซะ

คำว่า Autonomous นั้นรวมทั้งทีมและ service
นั่นคือระบบงานทำงานจบในตัวเอง เป็นสิ่งที่ดีที่สุด
เพื่อลดการผูกมัดกับ service อื่น ๆ (Loose coupling)
รวมไปถึงการตัดสินใจต่าง ๆ
ส่งผลให้ง่ายต่อการพัฒนา deploy และ scaling ต่อไป

ประโยชน์หลัก ๆ ของ Microservices ประกอบไปด้วย

  • เลือกเครื่องมือให้เหมาะกับงาน ทั้งภาษาโปรแกรมและที่จัดเก็บข้อมูล เป็นต้น
  • ทำให้ระบบมีความน่าเชื่อถือมากขึ้น เพราะว่าถ้าเกิดปัญหา จะใช้ไม่ได้เพียงบางส่วน ไม่ใช่ล่มทั้งระบบเช่นเดิม
  • สามารถ scale ระบบได้ง่าย และ scale เฉพาะในส่วนงานที่ต้องการได้ ไม่จำเป็นต้อง scale ทั้งระบบ
  • ทำให้การพัฒนาและส่งมอบงานได้รวดเร็วขึ้น
  • ทำให้องค์กรต้องมีการปรับเปลี่ยนโครงสร้าง จากเดิมมีทีมขนาดใหญ่ ให้แบ่งเป็นทีมเล็ก ๆ ตามแต่ละ service
  • ทำให้เกิดการ reuse ที่ง่ายตามมา
  • สามารถเปลี่ยนแปลงการทำงานของแต่ละส่วนได้ง่าย เช่นการเปลี่ยนเทคโนโลยีเป็นต้น

มุมมองและเป้าหมายของ Architect และ Engineer ที่เปลี่ยนไป

จากเดิมจะให้ความสำคัญไปที่
การทำงานร่วมกันของ service หรือ boudary ต่าง ๆ
โดยไม่สนใจการทำงานภายในของแต่ละ service มักจะมีแผนภาพที่สวยงาม
ตามด้วยเอกสารจำนวนมาก
ซึ่งดู ๆ แล้วเป็นแผนการที่ดี perfect และแจ่มแมว
แล้วให้ทีมพัฒนาไปทำตาม โดยไม่ได้ใส่ใจว่าจะทำได้หรือไม่

แต่เมื่อมีความต้องการที่เปลี่ยนแปลง
สิ่งที่เกิดขึ้นคือ จะไม่ยอมเปลี่ยนแปลง ต้องทำตามที่ออกแบบไว้
ทำให้เรามักจะอยู่กับโครงสร้างเดิม ๆ
ทั้ง ๆ ที่หลายคนบอกว่าไม่ดี ทำไมยังทนละ ?

ดังนั้นในการพัฒนา software น่าจะย้อนกลับมาดูว่า
สิ่งที่เราทำกันอยู่ ไม่น่าจะถูกต้อง
เพราะว่าปัจจุบันการเปลี่ยนแปลงมันรวดเร็วมาก ๆ
ทั้ง แนวคิด เทคนิคและเครื่องมือ
แนวคิดของการออกแบบระบบ จำเป็นต้องเปลี่ยนเช่นกัน
จากการสร้างสิ่งที่ดีสุด ๆ หรือ perfect system/architecture
ไปเป็นการออกแบบและสร้างสิ่งที่ช่วยเหลือให้สร้างระบบได้ง่าย ตรงตามความต้องการ
ที่สำคัญพร้อมที่จะเปลี่ยนแปลง ตามความต้องการและเทคโนโลยีที่เปลี่ยนไป

ดังนั้นโครงสร้างที่ดีคือ โครงสร้างที่พร้อมหรือสามารถเปลี่ยนแปลงได้เสมอ
อีกสิ่งที่น่าสนใจคือ
คนที่ออกแบบระบบควรที่จะเขียน code ได้
เนื่องจากจะช่วยทำให้เข้าใจว่า
ผลกระทบที่จะเกิดขึ้นจากการตัดสินใจต่าง ๆ เป็นอย่างไรบ้าง
เพราะว่า คนคิดมักจะคิดแค่ว่าเปลี่ยนนิดเดียว
แต่ตอนลงมือทำมันเยอะมาก ๆ 
ดังนั้นจำเป็นต้องเขียน code ได้นะ
หรืออย่างน้อยก็ต้องเข้ามาร่วมทำงานกับทีมพัฒนาด้วย 
ไม่ใช่เพียงแค่นั่งดู นั่งสั่ง และนั่งบ่น

มีกรอบช่วยตัดสินใจ ประกอบไปด้วย Strategic goal, Principle และ Practice

  • Strategic goal คือเป้าหมายที่องค์กรจะไป และผลที่อยากเห็นเช่นทำให้ลูกค้ามีความสุข ซึ่งต้องมีเทคนิคและเทคโนโลยีสนับสนุนด้วย
  • Principle คือกฎระเบียบต่าง ๆ ที่จะทำให้เราไปถึงเป้าหมายที่ตั้งไว้ เช่นเป้าหมายเพื่อทำให้ส่งมอบ feature ใหม่ ๆ ให้เร็วขึ้น ดังนั้น priciple ที่ดีควรให้ delivery team ดูแลจัดการการส่งมอบแบบเบ็ดเสร็จ ทำให้ไม่ต้องไปเสียเวลากับการทำงานกับส่วนอื่น ๆ 
  • Practice คือวิธีการลงมือทำตามแนวคิดของ priciple เพื่อให้ถึงเป้าหมายที่ตั้งไว้ ยกตัวอย่าง coding guideline, รูปแบบการจัดเก็บ log ต่าง ๆ และ HTTP/REST สำหรับการ integrate ของระบบต่าง ๆ

เรื่องที่สำคัญมาก ๆ คือ การออกแบบ service

เริ่มด้วย service ที่ดีประกอไปด้วย

  • Loose coupling เมื่อแก้ไขที่ service หนึ่งแล้ว ต้องไม่ไปแก้ไขใน service อื่น ๆ
  • High cohesion ต้องให้การทำงานที่ทำงานร่วมกันเกี่ยวข้อกันให้อยู่ด้วยกัน ไม่จำเป็นต้องแยกออกจากกัน เพื่อหลีกเลี่ยงผลกระทบจากการแก้ไขรวมไปถึงเรื่องของการ deploy และ scaling

ปล.  เมื่อไปอ่านความหมายของคำว่า service แล้ว

คือ Standalone, loose-coupling และมีการทำงานที่มีประโยชน์ต่อผู้ใช้งาน


เรื่องหนึ่งที่พูดถึงกันอย่างมากคือ Boudary Context

ที่หยิบยืมมาจาก Domain-Driven Design (DDD)
เนื่องจากใน business domain หนึ่ง ๆ นั้น
ประกอบไปด้วย กลุ่มงานที่แตกต่างกันจำนวนมาก
ดังนั้นจำเป็นต้องแบ่งกลุ่มการทำงานให้ชัดเจน
ด้วยสิ่งที่เรียกว่า Boudary Context

เพื่อแยกหรือรวมกลุ่มการทำงานในส่วนต่าง ๆ ให้ชัดเจน
ว่าอะไรควรอยู่ด้วยกัน
ว่าอะไรควรแยกกัน
โดยในแต่ละกลุ่มหรือ context นั้นจะมี interface ไว้ติดต่อสื่อสารกัน
รวมไปถึง model บางอย่างจากที่เคย shared กัน
ก็ต้องแยกออกจากกันหรือไม่ ?
เพราะว่าในแต่ละ context จะเรียกต่างกัน และใช้งานต่างกัน

แสดงตัวอย่างดังรูป

ในการแยก service นั้น
ให้เริ่มจากหน้าที่รับผิดชอบของแต่ละ context ก่อน
เพื่อให้แยกตามหน้าที่การทำงานทาง busienss
จากนั้นจึงมาคิดถึงเรื่องของ data ว่าจะแยกหรือ share กันต่อไป

ในหนังสือยังมีคำเตือนด้วยว่า
การแยกระบบงานออกจากกันเป็น service ย่อย ๆ หรือ Microservices นั้น 
จะมีค่าใช้จ่ายตามมาเสมอ ดังนั้นแนะนำให้เริ่มจาก service เดียวดี ๆ
แบ่งกลุ่มให้ชัดเจน เมื่อถึงเวลาที่เหมาะสม ค่อยแยกออกมา

ต่อมาว่าด้วยเรื่องของการ Integration กับส่วนงานต่าง ๆ

ในหนังสือจะเน้นไปเรื่องของการทำงานกับ database/data store
ซึ่งมักจะเป็นการ shared database ในหลาย ๆ service
ส่งผลให้เกิดผลดังนี้

  • เมื่อทำการแก้ไข schema แล้วจะกระทบกับ service อื่น ๆ ที่ใช้งาน
  • ทุก ๆ service ที่ใช้งาน shared database เดียวกัน ทำให้เกิดการผูกมัดอย่างมาก เปลี่ยนได้ยาก

ทำให้เราต้องคิดมากขึ้นว่า จะแก้ไขปัญหานี้อย่างไร
ซึ่งแนะนำให้ทำการแยก database ออกไปตามส่วนการทำงานก่อน
จากนั้นทำการแยก service ออกมา

เมื่อแยกเป็น service ย่อย ๆ ออกมา ปัญหาการ integration จึงเกิดขึ้นมา
คำถามคือในแต่ละ service จะติดต่อสื่อสารกันอย่างไร
คำถามคือในแต่ละ service จะทำงานร่วมกันอย่างไร
การติดต่อสื่อสารอาจจะมีการทำงานแบบ synchonous หรือ asynchonous ขึ้นอยู่กับงาน

ยังไม่พอ ถ้าการทำงานมีความซับซ้อนขึ้น
นั่นคือต้องเรียกใช้งาน service จำนวนมาก
คำถามที่ตามมาคือ จะจัดการอย่างไร
ในหนังสือจะมี 2 แบบที่แนะนำคือ

  • Orchestration pattern
  • Choreography pattern

แบบแรกคือ Orchestration pattern

นั่นคือมีตัวกลางในการจัดการการทำงานทั้งหมด แสดงดังรูป

แบบที่สองคือ Choreography pattern

ตรงข้ามกับแบบแรกคือ
ไม่มีตัวควบคุม แต่ว่าเป็นการส่งต่อการทำงานไปเรื่อย ๆ
ซึ่งมักจะทำงานร่วมกับ Event-based architecture
นั่นคือเมื่อทำงานในขั้นตอนที่ 1 เสร็จแล้ว
จะทำการสร้าง event ขึ้นมา
ถ้า service ไหนที่สนใจ event นี้ก็จะทำการ subscribe ไว้
เพื่อนำ event ที่เกิดขึ้นไปทำงานต่อไป
ทำให้แต่ละ service ไม่ผูกมัดกัน แต่ความซับซ้อนจะสูงขึ้น แสดงดังรูป

อีกเรื่องที่น่าสนใจคือ การ integrate กับ User Interface

เนื่องจาก user interface นั่นคือ
ฝั่งที่ทำการรวบรวมหรือเรียกใช้งานหลาย service
ทำให้การทำงานจริง ๆ อาจจะเกิดปัญหาเรื่องการติดต่อสื่อสารไปยัง service ต่าง ๆ
ดังนั้นจึงแนะนำให้สร้าง composition service ขึ้นมา
เพื่อทำงานตามความต้องการของ user interface ไปเลย

ยกตัวอย่างเช่น user interface มีทั้ง Mobile, Web และ Admin
ก็ให้มี composition service ของแต่ละ user interface 
เรามักจะเรียก service เหล่านี้ว่า Backend for Frontend (BFF) แสดงดังรูป

รวมไปถึงการจัดการ version ของ service ก็สำคัญมาก ๆ
เพื่อสร้างความน่าเชื่อถือให้กับ service

เรื่องที่ผมชอบมาก ๆ คือ Split the monolith

หรือการแยก service จากระบบเดิม แน่นอนว่า ต้องมีเหตุผลในการแยกดังนี้

  • เหตุผลในการเปลี่ยนแปลง เมื่อแยก service ออกมาแล้วการเปลี่ยนแปลงต้องเป็นเฉพาะ service นั้น ๆ เท่านั้น ไม่ไปทำให้ service อื่นเปลี่ยนด้วย ถ้าแยกออกมาแล้ว ยังต้องเปลี่ยนเพราะว่า service อื่นเปลี่ยน แบบนี้เราจะแยกออกมาทำไมกัน
  • โครงสร้างของทีม การแยกทีมออกมาดูแต่ละ service ก็ทำให้จำนวน code น้อยลง การดูแลง่ายขึ้น ยิ่งถ้าทำงานต่างที่กัน น่าจะทำให้ตอบรับโจทย์หรือปัญหามากขึ้น
  • เทคโนโลยีที่เลือกใช้งานที่เหมาะสมกับงาน บางครั้งการแยก service ออกมา เพราะว่าเทคโนโลยีที่เหมาะสมกับงานทั้ง algorithm, เครื่องมือ, ภาษาโปรแกรม, database ทำให้ง่ายต่อการสร้างและ deploy

เมื่อทำการแยกออกมาเป็น service ย่อย ๆ แล้ว

Database ที่ใช้งานมักจะไม่ shared กัน
หรือเก็บข้อมูลแยกในแต่ละ service
ทำให้เกิดปัญหาที่ตามมา
ทั้งเรื่องการจัดการความถูกต้องของข้อมูล 
ซึ่งแต่ก่อนจะมีการจัดการด้วย transaction 
แต่พอมาเป็นหลาย ๆ service ไม่มี ทำให้ต้องรับมือกับปัญหานี้
ยังไม่พอนะ
ถ้ามีการใช้งานข้อมูลจากหลาย ๆ service จะจัดการอย่างไร
ยกตัวอย่างเช่นระบบ reporting

มาถึงเรื่องของการ deploy service ต่าง ๆ

เป็นอีกเรื่องที่น่าสนใจ ว่าจะใช้แนวทางใดบ้าง
ทั้งแบบเครื่องจริง ๆ VM หรือ container
เพื่อให้ตอบโจทย์ที่ต้องการ
ซึ่งตรงนี้ต้องมาวางแผนและศึกษากัน
เพื่อการส่งมอบงานที่รวดเร็ว และ น่าเชื่อถือ
แน่นอนว่า เรื่องของการทำงานแบบอัตโนมัติ เป็นเรื่องที่สำคัญขึ้นมาทันที

รูปแบบการ deploy service ต่าง ๆ ก็เช่นกัน
มีทั้ง Blue/green deployment และ Canary release เป็นต้น
ยิ่งกว่านั้น
ถ้ามีปัญหาเกิดขึ้นหลังจากการ deploy จะทำอย่างไร
ใช้เวลาในการแก้ไขนานหรือไม่ ?
ถ้าช้ากว่าเดิม หรือ ยากกว่าเดิม น่าจะเดินผิดทางอย่างแน่นอน

การทดสอบเป็นสิ่งที่ขาดไม่ได้เลย

เมื่อมีเพียง service เดียวยังทดสอบลำบาก
เมื่อแยกมาเป็น service ย่อย ๆ ยิ่งยากเข้าไปใหญ่
โดยในการพัฒนาตามแนวคิด Microservices นั้น
จะมีการทดสอบในหลาย ๆ ส่วน ประกอบไปด้วย

  • Unit test
  • Integration test
  • Component test
  • Consumer Contract test
  • End-to-End test

เรื่องของ integration test ใน level ต่าง ๆ เป็นความท้าทายสุด ๆ
ในโลกของ microservices
คำถามที่น่าสนใจมาก ๆ คือ
เมื่อมี service จำนวนมาก ๆ แล้ว การทดสอบจะทำกันอย่างไร
ได้วางแผนเพื่อรับมือกันหรือไม่ ?

เรื่องสุดท้ายคือ Monitoring หรือ Observability

ก่อนที่จะเริ่มแยก service นั้น
เราควรมีระบบ Monitoring ที่ดี
ทั้งเรื่องของ centralize logging, dashboard, alert, metric
และ tracing ของระบบ
มันคือ infrastructure พื้นฐานของระบบที่ต้องมีก่อน
มิเช่นนั้น ปัญหาที่ตามมาจะหายากและแก้ไขยากแน่นอน แสดงปัญหาดังรูป

เรื่องของการ monitoring ระบบนั้นมีหลายรูปแบบ
แต่ก่อนอื่นเราต้องตอบคำถามเหล่านี้ให้ได้

  • มีอะไรบ้างที่ต้องการรู้ทันทีเมื่อเกิดขึ้น
  • มีอะไรบ้างที่ต้องการรู้ในภายหลัง
  • มีข้อมูลอะไรบ้างที่เราต้องใช้งาน

เป็นหนังสืออีกเล่มที่น่าสนใจครับ