เริ่มต้นจากสถาปัตยกรรมของระบบงาน (Application Architecture)

สถาปัตยกรรมของ software นั้นมีหลากหลายรูปแบบ
แต่แนวโน้มของสถาปัตยกรรมต่าง ๆ ล้วนพยายามแยกส่วนการทำงานออกเป็นชิ้นเล็ก (Decomposition)
โดยแต่ละชิ้นต้องทำงานได้ด้วยตัวเอง (Service)
ระบบงานใหญ่ ๆ เรามักจะเรียกว่า Monolithic
ส่วนระบบงานที่เราทำการแบ่งเป็น Service เล็ก ๆ จะเรียกว่า Microservice

แสดงดังรูป

คำถามที่น่าสนใจคือ Monolithic มันไม่ดีหรือ ?
ตอบได้เลยว่า ดีสิ
ด้วยเหตุผลดังนี้

  • ง่ายต่อการพัฒนา
  • ง่ายต่อการเปลี่ยนแปลง
  • ง่ายต่อการทดสอบ
  • ง่ายต่อการ deploy
  • ง่ายต่อการ scale

เพราะว่าทุกอย่างมันอยู่ที่เดียวกัน

แต่เมื่อระบบที่เรียกว่า Monolithic มันมีขนาดใหญ่ขึ้น !!!
ทั้งจำนวนทีมพัฒนา
ทั้งจำนวนบรรทัดของ code
ทั้งการพูดคุยที่เยอะและล่าช้า
สิ่งที่เคยง่ายกลับกลายยากขึ้น
ทั้งการพัฒนา เปลี่ยนแปลง ทดสอบ deploy และ scale

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

ด้วยเหตุผลเหล่านี้ นักพัฒนาระบบงาน
จึงพยายามหาแนวทางในการแก้ไข
หนึ่งในการแก้ไขปัญหาคือ การแยกส่วนทำงานต่าง ๆ ออกจากกัน (Decomposition)
หรืออีกชื่อที่เราชอบเรียกกันคือ Separation of Concern (SoC)
ในปัจจุบันสิ่งที่กำลังได้รับความนิยมและพูดถึงกันอย่างมากคือ Microservice
ดังนั้นเรามาทำความรู้จักกันหน่อย

Microservice คืออะไร ?

เป็นเทคนิคหนึ่งในการพัฒนาระบบงาน
เพื่อแยกส่วนการทำงานออกเป็น service ย่อย ๆ ที่มีขนาดเล็ก (คำถามคือ อะไรคือคำว่าเล็ก ?)
แต่ละ service มีการทำงานเพียงอย่างเดียว (Single Responsibility)
แต่ละ service ต้องให้ทำงานจบในตัวเอง (Self service) นั่นคือมี data store หรือที่จัดเก็บข้อมูลของแต่ละ service

แต่ถ้าต้องเรียกหรือทำงานร่วมกับ service อื่น ๆ ต้องไม่ลึกเกิน 3 ชั้น (อ้างอิงจาก Service Principle)
เนื่องจากจะทำให้ service มีความซับซ้อนเกินไป
ที่สำคัญการทำงานร่วมกับ service อื่น ๆ ทำให้เกิดปัญหาตามมามากมาย
ที่สำคัญขัดแย้งกับแนวคิดข้างต้น

ผลที่ได้คือ
Service ง่ายต่อการทำความเข้าใจ
Service ง่ายต่อการพัฒนา
Service ง่ายต่อการทดสอบ
Service ง่ายต่อการ deploy
Service ง่ายต่อการ scale

ที่สำคัญของการแยกเป็น service เล็ก ๆ คือ
ทำให้แต่ละทีมสามารถพัฒนา Service ไปพร้อม ๆ กันได้
รวมทั้งแต่ละทีมพัฒนา service สามารถทำได้ตั้งแต่ พัฒนา ทดสอบและ deploy เองได้ (Autonomous Team)
นั่นคือแต่ละทีมสามารถปิดงานได้อย่างอิสระ
แน่นอนว่า มันส่งผลต่อโครงสร้างและขั้นตอนการทำงานของทีมและบริษัทอย่างแน่นอน

ลองคิดดูสิว่า
ถ้าขั้นตอนการทำงานยังซับซ้อน มากมาย ล่าช้าแล้ว
แต่นำ Microservice มาใช้งาน มันจะรอดไหม ?

แต่ว่าเราจะแยก service ในแนวทางของ Microservice ทำได้อย่างไรบ้าง ?

วิธีง่าย ๆ แบ่งออกเป็นสองมุมมองคือ
1. มุมมองทาง business (Business capability)
2. มุมมองทางด้วย technical (Technical capability)

ในระบบส่วนใหญ่นั้น เรามักจะแบ่งส่วนการทำงานต่าง ๆ เป็นส่วนเล็ก ๆ อยู่แล้ว
แต่แบ่งเป็น layer ตามหน้าที่การทำงาน
ยกตัวอย่างเช่น User Interface, Business layer และ Database layer เป็นต้น
ส่งผลให้จำนวนทีมก็แบ่งตาม layer เหล่านี้นั่นเอง
ผลที่ตามมาจากการแยกทีมทำงานตามแต่ละ layer คือ
การทำงานร่วมกันยากขึ้น
ทั้งการพูดคุยกัน ทั้งการวางแผน เพื่อให้ไปในทิศทางเดียวกัน
รวมทั้งการประเมินค่าใช้จ่ายที่มักจะสูงอีกด้วย

ยิ่งหน่วยงานใหญ่มากขึ้นเท่าไร
จำนวน layer และจำนวนทีมก็สูงขึ้น
ดังนั้น overhead ของการทำงานยิ่งสูงขึ้น

ดังนั้นระบบงานของเราเป็นอย่างไร มันบ่งบอกว่าโครงสร้างขององค์ของเราเป็นเช่นนั้น
ตามกฏของ Conway แสดงดังรูป

ดังนั้นด้วยแนวคิด Microservice จึงไม่ทำตามวิธีการข้างต้น
เพราะว่า สิ่งที่ผิดพลาดไปแล้ว ไม่น่าจะทำตามใช่ไหม ?
นั่นคือ ทีมทำงานจะมีคนที่มีความสามารถครบตามที่ระบบงานต้องการ
ยกตัวอย่างเช่น ต้องมี UI, Middleware และ Database Administrator specialist
กลายว่าทีมจะมีรูปแบบที่เรียกว่า Cross-functional team
แสดงดังรูป

 

คำถามต่อมาคือ ขนาดของ service จะมีขนาดเล็ก มันต้องเล็กเพียงใด ?

จากข้างต้นบอกว่า แต่ละ service ต้องมีทีมที่ดูแล เรียกว่า Cross-functional team
ดังนั้นขนาดของ service จะใหญ่เพียงใดนั้น
ตอบได้ง่าย ๆ คือ ทีมนั้น ๆ สามารถดูแล service ได้หรือไม่ ? (You build it, You run it)
ระบบงานที่เราสร้างมานั้น ไม่ได้เน้นไปที่จำนวน feature ให้ใช้งาน
แต่เน้นไปที่คุณค่าของระบบงานที่ให้ทางผู้ใช้งานและ business
รวมทั้งขนาดของ service ที่เล็ก จะยิ่งช่วยทำให้
ทีมพัฒนาและผู้ใช้งาน รวมทั้ง business ใกล้ชิดกันมากขึ้น
ซึ่งมันส่งผลดีต่อทุกฝ่าย

ส่วนเรื่องของจำนวนบรรทัดของ code ไม่ได้เกี่ยวกับ Microservice เลย !!

เนื่องจากแต่ละ service นั้นต้องมี data store หรือที่จะเก็บข้อมูลเป็นของตัวเอง

มันทำให้เกิดคำถามหนึ่งขึ้นมาคือ
เราจัดการความถูกต้องของข้อมูลกันอย่างไร
ถ้าข้อมูลหล่านั้นถูกใช้งานข้าม service ?

ปล. ปัญหานี้จะไม่เกิดในระบบ Monolithic อย่างแน่นอน

แสดงดังรูป

วิธีการจัดการปัญหาเรื่อง ความถูกต้องของข้อมูล (Data consistency) มีดังนี้

  • การ aggregate ข้อมูลจาก data store จาก service ต่าง ๆมารวมกัน
  • Domain event คือเมื่อมีการเปลี่ยนแปลงใด ๆ แล้วจะทำการส่งการเปลี่ยนแปลงนั้นไปยังส่วนกลางที่จัดการระบบทั้งหมด
  • Event sourcing
  • Saga

ถ้าแต่ละ service ต้องดึงข้อมูลข้าม service จะต้องทำอย่างไร ?

วิธีการจัดการมีดังนี้

  • API composition
  • CQRS (Command Query Responsibility Segregation)

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

จะพบว่าจำนวน Service เยอะมาก ๆ แล้วแต่ละ service จะติดต่อสื่อสารกันอย่างไร ?

การสื่อสารนั้นมีรูปแบบหลัก ๆ 2 แบบคือ

  1. Synchronous หรือ Request-Response Model คือต้องทำการรอผลลัพธ์จาก request ที่ส่งไปยังผู้ให้บริการ
  2. Asynchronous จะตรงข้ามกับ Synchronous นั่นคือไม่ต้องรอนั่นเอง ทำให้สามารถติดต่อในรูปแบบ one-to-one และแบบ one-to-many ได้

การติดต่อสื่อสารของ service ต่าง ๆ ใน Microservice ก็มีรูปแบบตามนี้เช่นกัน
แต่สามารถแบ่งกลุ่มได้ตามรูปแบบที่ต่างกันดังนี้

  1. Domain specific แบ่งตามการใช้งานเช่น HTTP สำหรับระบบ web application หรือ SMTP สำหรับการส่ง email เป้นต้น
  2. Messaging สำหรับการส่งข้อมูลในรูปแบบ messaing เช่น queue และ topic เป็นต้น โดยนิยมใช้งาน RabitMQ และ Apache Kafka
  3. Remote Procedure Invocation (RPI) หรือการเขียนจากระยะไกล เป็นรูปบบที่เก่ามาก ๆ แต่กลับมาได้รับความนิยมอย่างมากในปัจจุบัน ยกตัวอย่างเช่น REST, gRPC และ Apache Thrift เป็นต้น
  4. API gateway เนื่องจากจำนวน service มีจำนวนมาก ถ้าเรียกใช้งาน service-to-service จำนวนมาก ๆ แล้ว น่าจะทำให้เกิดความยุ่งเหยิงได้ ดังนั้นเราจึงนำ API gateway มาเป็นคนกลางของการติดต่อสื่อสาร แต่ต้องระวังอย่างให้กลายเป็นคอขวดหรือ Single Point of Failure ด้วยละ

แสดงดังรูป

ไม่ใช้งาน API gateway

ใช้งาน API gateway มาใช้งาน เพื่อแก้ไขปัญหา แต่ก็มีปัญหาอย่างอื่นให้แก้ไขและรับมือนะ

ต่อมาคือ เราจะทดสอบกันอย่างไร ? การทดสอบระบบงานเป็นเรื่องที่มีความสำคัญอย่างมาก

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

แน่นอนว่า ในปัจจุบันนั้นการทดสอบแบบอัตโนมัติ น่าจะเริ่มเข้ามาเป็นส่วนหลักไปแล้ว (มั้ง !!)
ซึ่งการทดสอบจะเป็นไปตาม Pyramid Testing ดังรูป

แต่เมื่อระบบอยู่ในรูปแบบ Microservice แล้ว
นั่นคือจำนวน service มากกว่า 1 service
คำถามที่น่าสนใจคือ เราจะทำการทดสอบกันอย่างไร ?

  1. Unit testing ทดสอบ code ของแต่ละ service
  2. Integration testing ทดสอบการทำการกับส่วนอื่น ๆ ที่ใช้งานจาก service เช่น database และ การติดต่อไปยัง service อื่น
  3. Component testing ทดสอบการทำงานภายในทั้งหมดของ service โดยตัดหรือจำลองการทำงานภายนอก
  4. Contract testing ทดสอบการทำงานของ service ในมุมมองของผู้ใช้งานเป็นหลัก
  5. End-to-End testing ทดสอบการทำงานโดยรวมของระบบว่า แต่ละ service ทำงานร่วมกันได้หรือไม่

แสดงดังรูป

วันนี้เรายังทดสอบระบบงานแบบ manual กันอยู่หรือไม่ ?
ถ้ายังใช่แล้ว คุณคิดว่าคุณพร้อมกับ Microservice หรือไม่ ?
แต่ผมมั่นใจว่า ไม่รอดแน่ ๆ

 

 

โดยรวมแล้วการพัฒนาแต่ละ service ตามแนวคิดของ Microservice จะประกอบไปด้วยสิ่งต่าง ๆ ดังรูป

ยังไม่พอนะ เราจะทำการ deploy service จำนวนมากกันอย่างไร ?

ก่อนอื่นนั้นต้องดูที่ process การทำงานในปัจจุบันว่าเป็นอย่างไร ?
ทั้งการ deploy มีความยุ่งยากและช้าหรือไม่ ?
ทั้งการ provisioning พวก infrastructure ทั้งเครื่อง server ทั้งระบบ network รวมถึงระบบรอบข้าง
ว่ามีความยุ่งยากและช้าหรือไม่ ?
ทั้งการทดสอบว่าเป็นอย่างไร ?
แสดงดังรูป

ถ้ายังช้าและยุ่งยากแล้ว แนะนำให้แก้ไขก่อนเลย
มิเช่นนั้น Microservice จะเข้ามาสร้างปัญหามากกว่าเดิมอย่างแน่นอน
เพราะว่า แทนที่จะ deploy เพียง service เดียว ต้องไปดูแล service มากกว่า 1 ตัว !!!

ที่สำคัญคือ รูปแบบการ deploy ก็จะเปลี่ยนไปอีกด้วย
เช่นอาจจะต้องมีการทำ VM และ container มาช่วยจัดการ
รวมไปถึงเครื่องมือใหม่ ๆ ที่ต้องใช้งาน ดังนั้นจำเป็นต้องศึกษาให้มากขึ้น
ยกตัวอย่างเช่น Docker, Kubernetes และ Istio เป็นต้น
รวมไปถึงเครื่องมือพวก Ansible และ Chef เป็นต้น
แสดงดังรูป

เราสามารถสรุปรูปแบบของการ deploy Microservice ได้ดังนี้

  • Multiple services per host
  • Single service per host
  • Service per VM
  • Service per container

จะเลือกวิธีการใด จำเป็นต้องดูหลาย ๆ อย่าง
ทั้งเรื่องของ skill ของคน
ทั้งเรื่องของ process ของการทำงาน
ทั้งเรื่องของเครื่องมือที่ใช้งาน

ส่วนการจะ release ระบบงานไปยังผู้ใช้งาน ก็มีหลายแนวทางให้ใช้
ยกตัวอย่างเช่น

Blue-Green Deployment
แสดงดังรูป

หรือจะเป็น Canary Deployment
แสดงดังรูป

 

คำถามก่อนที่จะเริ่มนำ Microservice มาใช้งานคือ เราพร้อมที่จะเริ่มต้นทำความรู้จักกับ Microservice แล้วหรือยัง ?

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

อีกอย่างที่เราต้องเข้าใจก่อนคือ
เราพร้อมหรือไม่ ?
ทั้ง skill ของทีมพัฒนา และคนในองค์กร
ทั้ง process ของการพัฒนา
ทั้งระบบ Continuous Integration และ Continuous Delivery รวมถึง DevOps
ก่อนที่จะไปถึง Microservice
แสดงดังรูป

สุดท้ายแล้วนั้น ปัญหาของคุณคืออะไร ถึงจะนำแนวคิด Microservice มาใช้งาน ?

Reference Websites
https://martinfowler.com/articles/microservices.html
https://www.nginx.com/blog/building-microservices-using-an-api-gateway/
https://martinfowler.com/articles/microservice-testing/
https://www.xenonstack.com/blog/devops/microservices-testing-strategy-automation-architecture/
https://www.gocd.org/2018/05/08/continuous-delivery-microservices-test-strategy.html