เริ่มต้นจากสถาปัตยกรรมของระบบงาน (Application Architecture)
สถาปัตยกรรมของ software นั้นมีหลากหลายรูปแบบ
แต่แนวโน้มของสถาปัตยกรรมต่าง ๆ ล้วนพยายามแยกส่วนการทำงานออกเป็นชิ้นเล็ก (Decomposition)
โดยแต่ละชิ้นต้องทำงานได้ด้วยตัวเอง (Service)
ระบบงานใหญ่ ๆ เรามักจะเรียกว่า Monolithic
ส่วนระบบงานที่เราทำการแบ่งเป็น Service เล็ก ๆ จะเรียกว่า Microservice
แสดงดังรูป
คำถามที่น่าสนใจคือ Monolithic มันไม่ดีหรือ ?
ตอบได้เลยว่า ดีสิ
ด้วยเหตุผลดังนี้
- ง่ายต่อการพัฒนา
- ง่ายต่อการเปลี่ยนแปลง
- ง่ายต่อการทดสอบ
- ง่ายต่อการ deploy
- ง่ายต่อการ scale
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 แบบคือ- Synchronous หรือ Request-Response Model คือต้องทำการรอผลลัพธ์จาก request ที่ส่งไปยังผู้ให้บริการ
- Asynchronous จะตรงข้ามกับ Synchronous นั่นคือไม่ต้องรอนั่นเอง ทำให้สามารถติดต่อในรูปแบบ one-to-one และแบบ one-to-many ได้
- Domain specific แบ่งตามการใช้งานเช่น HTTP สำหรับระบบ web application หรือ SMTP สำหรับการส่ง email เป้นต้น
- Messaging สำหรับการส่งข้อมูลในรูปแบบ messaing เช่น queue และ topic เป็นต้น โดยนิยมใช้งาน RabitMQ และ Apache Kafka
- Remote Procedure Invocation (RPI) หรือการเขียนจากระยะไกล เป็นรูปบบที่เก่ามาก ๆ แต่กลับมาได้รับความนิยมอย่างมากในปัจจุบัน ยกตัวอย่างเช่น REST, gRPC และ Apache Thrift เป็นต้น
- API gateway เนื่องจากจำนวน service มีจำนวนมาก ถ้าเรียกใช้งาน service-to-service จำนวนมาก ๆ แล้ว น่าจะทำให้เกิดความยุ่งเหยิงได้ ดังนั้นเราจึงนำ API gateway มาเป็นคนกลางของการติดต่อสื่อสาร แต่ต้องระวังอย่างให้กลายเป็นคอขวดหรือ Single Point of Failure ด้วยละ
ต่อมาคือ เราจะทดสอบกันอย่างไร ? การทดสอบระบบงานเป็นเรื่องที่มีความสำคัญอย่างมาก
เพื่อทำให้เรามั่นใจว่า ระบบงานยังคงทำงานได้ตามที่คาดหวัง ประเด็นที่สำคัญคือ แนวทางในการทดสอบระบบงานของเราเป็นอย่างไร ? ทดสอบแบบ manual หรือว่าแบบอัตโนมัติ ? แน่นอนว่า ในปัจจุบันนั้นการทดสอบแบบอัตโนมัติ น่าจะเริ่มเข้ามาเป็นส่วนหลักไปแล้ว (มั้ง !!) ซึ่งการทดสอบจะเป็นไปตาม Pyramid Testing ดังรูป แต่เมื่อระบบอยู่ในรูปแบบ Microservice แล้ว นั่นคือจำนวน service มากกว่า 1 service คำถามที่น่าสนใจคือ เราจะทำการทดสอบกันอย่างไร ?- Unit testing ทดสอบ code ของแต่ละ service
- Integration testing ทดสอบการทำการกับส่วนอื่น ๆ ที่ใช้งานจาก service เช่น database และ การติดต่อไปยัง service อื่น
- Component testing ทดสอบการทำงานภายในทั้งหมดของ service โดยตัดหรือจำลองการทำงานภายนอก
- Contract testing ทดสอบการทำงานของ service ในมุมมองของผู้ใช้งานเป็นหลัก
- 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
คำถามก่อนที่จะเริ่มนำ 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