Microservice Pain Points (จุดเจ็บปวดของ Microservice)
Microservice สถาปัตยกรรมนำมาซึ่งประโยชน์มากมาย อย่างที่เราได้เห็นไปแล้ว แต่พวกมันก็นำความซับซ้อนมามากมายเช่นกัน หากคุณ กำลังพิจารณารับสถาปัตยกรรม microservice มาใช้ สิ่งสำคัญคือคุณต้องสามารถเปรียบเทียบข้อดีกับข้อเสียได้ ใน ความเป็นจริง ปัญหา microservice ส่วนใหญ่สามารถโยงไปถึงระบบแบบกระจายได้ และ ดังนั้นจะ ปรากฏชัดใน distributed monolith พอๆ กับใน สถาปัตยกรรม microservice
เราจะครอบคลุมประเด็นเหล่านี้จำนวนมากอย่างละเอียดตลอดส่วนที่เหลือของหนังสือ—อันที่จริง ผมขอเถียงว่าเนื้อหา ส่วนใหญ่ของหนังสือเล่มนี้พูดถึงการรับมือกับความเจ็บปวด ความทุกข์ทรมาน และความสยองขวัญของการเป็นเจ้าของ สถาปัตยกรรม microservice
Developer Experience (ประสบการณ์ของนักพัฒนา)
เมื่อคุณมี service มากขึ้นเรื่อยๆ ประสบการณ์ของนักพัฒนาอาจเริ่มแย่ลง runtime ที่ใช้ resource มากอย่าง JVM สามารถจำกัดจำนวน microservice ที่สามารถรันบนเครื่องนักพัฒนาเครื่องเดียวได้ ผมอาจรัน microservice ที่อิง JVM สี่หรือห้าตัวเป็น process แยกกันบน laptop ของผมได้ แต่ผมจะรันได้ 10 หรือ 20 ตัวไหม? แทบเป็นไปไม่ได้ แม้แต่กับ runtime ที่เบากว่า ก็ยังมีขีดจำกัดของจำนวนสิ่งที่คุณสามารถรันในเครื่องได้ ซึ่งหลีกเลี่ยงไม่ได้ ที่จะเริ่มบทสนทนาว่าจะทำอย่างไรเมื่อคุณไม่สามารถรันทั้งระบบบนเครื่องเดียวได้ สิ่งนี้อาจซับซ้อนยิ่งขึ้นไปอีก หากคุณใช้ cloud service ที่คุณไม่สามารถรันในเครื่องได้
solution สุดโต่งอาจเกี่ยวข้องกับ "การพัฒนาบน cloud" ซึ่งนักพัฒนาย้ายออกจากการพัฒนาในเครื่องได้อีกต่อไป ผมไม่ชอบแนวทางนี้ เพราะ feedback cycle อาจแย่ลงมาก แทนที่จะเป็นแบบนั้น ผมคิดว่าการจำกัดขอบเขตว่านักพัฒนา คนหนึ่งต้องทำงานกับส่วนไหนของระบบน่าจะเป็นแนวทางที่ตรงไปตรงมากว่ามาก อย่างไรก็ตาม สิ่งนี้อาจเป็นปัญหาได้ หากคุณต้องการโอบรับโมเดล "ความเป็นเจ้าของร่วม" มากขึ้น ซึ่งนักพัฒนาคนใดก็ตามคาดว่าจะทำงานกับส่วนใดของ ระบบก็ได้
Technology Overload (เทคโนโลยีล้นเกิน)
น้ำหนักมหาศาลของเทคโนโลยีใหม่ที่ผุดขึ้นมาเพื่อรองรับการรับสถาปัตยกรรม microservice มาใช้อาจทำให้รู้สึก ท่วมท้น ผมขอพูดตรงๆ ว่าเทคโนโลยีจำนวนมากนี้แค่ถูกรีแบรนด์เป็น "microservice friendly" แต่ความก้าวหน้าบาง อย่างก็ช่วยได้จริงในการรับมือกับความซับซ้อนของสถาปัตยกรรมประเภทนี้ อย่างไรก็ตาม มีอันตรายที่ของเล่นใหม่ มากมายเหล่านี้อาจนำไปสู่รูปแบบหนึ่งของการหลงใหลเทคโนโลยี ผมเคยเห็นบริษัทจำนวนมากที่รับสถาปัตยกรรม microservice มาใช้แล้วตัดสินใจว่านี่ก็เป็นเวลาที่ดีที่สุดที่จะนำเทคโนโลยีใหม่และแปลกประหลาดจำนวนมหาศาล เข้ามาด้วย
Microservices อาจให้ ตัวเลือก แก่คุณในการเขียนแต่ละ microservice ด้วยภาษาโปรแกรมที่แตกต่างกัน รันบน runtime ที่แตกต่างกัน หรือใช้ ฐานข้อมูลที่แตกต่างกัน—แต่นี่คือตัวเลือก ไม่ใช่ข้อบังคับ คุณต้องชั่งน้ำหนักอย่างระมัดระวังระหว่างความ กว้างและความซับซ้อนของเทคโนโลยีที่คุณใช้กับต้นทุนที่เทคโนโลยีที่หลากหลายอาจนำมาให้
เมื่อคุณเริ่มรับ microservices มาใช้ ความท้าทายพื้นฐานบางอย่างเป็นสิ่งที่หลีกเลี่ยงไม่ได้ คุณจะต้องใช้ เวลามากในการเข้าใจประเด็นเกี่ยวกับ data consistency, latency, การออกแบบโมเดล service และอื่นๆ หากคุณ พยายามเข้าใจว่าแนวคิดเหล่านี้เปลี่ยนวิธีที่คุณคิดเกี่ยวกับการพัฒนาซอฟต์แวร์ในเวลาเดียวกับที่คุณกำลังรับ เทคโนโลยีใหม่จำนวนมหาศาล คุณจะพบว่ามันยากลำบาก ยังควรชี้ให้เห็นด้วยว่า bandwidth ที่ถูกใช้ไปกับการพยายาม เข้าใจเทคโนโลยีใหม่ทั้งหมดนี้จะลดเวลาที่คุณมีสำหรับการส่งมอบฟีเจอร์จริงๆ ให้ผู้ใช้ของคุณ
เมื่อคุณ (ค่อยๆ) เพิ่มความซับซ้อนของสถาปัตยกรรม microservice มองหาการนำเทคโนโลยีใหม่มาใช้เมื่อคุณต้องการ มันจริงๆ คุณไม่จำเป็นต้องมี Kubernetes cluster เมื่อคุณมี service แค่สามตัว! นอกจากจะทำให้แน่ใจว่าคุณ ไม่ถูกครอบงำด้วยความซับซ้อนของเครื่องมือใหม่เหล่านี้แล้ว การเพิ่มขึ้นแบบค่อยเป็นค่อยไปนี้ยังมีประโยชน์เพิ่ม เติมคือช่วยให้คุณได้วิธีการทำงานที่ใหม่และดีกว่าซึ่งไม่ต้องสงสัยเลยว่าจะเกิดขึ้นเรื่อยๆ ตามกาลเวลา
Cost (ต้นทุน)
มีความเป็นไปได้สูงที่อย่างน้อยในระยะสั้นคุณจะเห็นต้นทุนเพิ่มขึ้นจากหลายปัจจัย ประการแรก คุณน่าจะต้องรัน สิ่งต่างๆ มากขึ้น—process มากขึ้น เครื่องมากขึ้น เครือข่ายมากขึ้น พื้นที่จัดเก็บมากขึ้น และซอฟต์แวร์รองรับ มากขึ้น (ซึ่งจะมีค่า license เพิ่มเติม)
ประการที่สอง การเปลี่ยนแปลงใดๆ ที่คุณนำเข้าไปในทีมหรือองค์กรจะทำให้คุณช้าลงในระยะสั้น มันใช้เวลาในการ เรียนรู้แนวคิดใหม่ และหาวิธีใช้มันอย่างมีประสิทธิภาพ ในขณะที่สิ่งนี้กำลังเกิดขึ้น กิจกรรมอื่นๆ จะได้รับ ผลกระทบ สิ่งนี้จะส่งผลให้เกิดการชะลอตัวโดยตรงในการส่งมอบฟังก์ชันการทำงานใหม่ หรือความจำเป็นในการเพิ่มคน เพื่อชดเชยต้นทุนนี้
จากประสบการณ์ของผม microservices เป็นตัวเลือกที่ไม่ดีสำหรับองค์กรที่ให้ความสำคัญหลักกับการลดต้นทุน เพราะแนวคิดแบบ cost-cutting—ที่ IT ถูกมองเป็น cost center แทนที่จะเป็น profit center—จะเป็นตัวถ่วงอยู่ เสมอในการดึงประโยชน์สูงสุดจากสถาปัตยกรรมนี้ ในทางกลับกัน microservices สามารถช่วยให้คุณทำเงินได้มากขึ้น หากคุณสามารถใช้สถาปัตยกรรมเหล่านี้เพื่อเข้าถึงลูกค้าได้มากขึ้นหรือพัฒนาฟังก์ชันการทำงานแบบขนานได้มากขึ้น ดังนั้น microservices เป็นวิธีขับเคลื่อนกำไรมากขึ้นหรือไม่? อาจจะใช่ microservices เป็นวิธีลดต้นทุนหรือไม่? ไม่ค่อยใช่
Reporting (การรายงาน)
ด้วยระบบ monolithic โดยทั่วไปคุณจะมีฐานข้อมูล monolithic นั่นหมายความว่าผู้มีส่วนได้ส่วนเสียที่ต้องการ วิเคราะห์ข้อมูลทั้งหมดร่วมกัน ซึ่งมักเกี่ยวข้องกับการ join ข้อมูลขนาดใหญ่ มี schema สำเร็จรูปให้รันรายงาน ของพวกเขาได้ พวกเขาสามารถรันรายงานเหล่านั้นได้โดยตรงกับฐานข้อมูล monolithic บางทีก็กับ read replica ดัง แสดงใน Figure 1-12
Figure 1-12. Reporting carried out directly on the database of a monolith (การรายงานที่ทำโดยตรงบนฐานข้อมูลของ monolith)
ด้วยสถาปัตยกรรม microservice เราได้แยก schema แบบ monolithic นี้ออกจากกัน นั่นไม่ได้หมายความว่าความ จำเป็นในการรายงานข้ามข้อมูลทั้งหมดของเราหายไป เราแค่ทำให้มันยากขึ้นมาก เพราะตอนนี้ข้อมูลของเรากระจัด กระจายอยู่ทั่ว schema ที่แยกตัวออกจากกันทางตรรกะหลายชุด
แนวทางการรายงานที่ทันสมัยกว่า เช่น การใช้ streaming เพื่อรองรับการรายงานแบบ real-time บนข้อมูลปริมาณมาก สามารถทำงานได้ดีกับสถาปัตยกรรม microservice แต่โดยทั่วไปต้องการการรับแนวคิดและเทคโนโลยีที่เกี่ยวข้องใหม่ๆ มาใช้ อีกทางหนึ่ง คุณอาจแค่ต้องเผยแพร่ข้อมูลจาก microservice ของคุณไปยังฐานข้อมูลรายงานส่วนกลาง (หรือ บางที data lake ที่มีโครงสร้างน้อยกว่า) เพื่อรองรับกรณีการใช้งานด้านรายงาน
Monitoring and Troubleshooting (การ Monitor และการแก้ปัญหา)
ด้วยแอปพลิเคชัน monolithic มาตรฐาน เราสามารถใช้แนวทาง monitoring ที่ค่อนข้างเรียบง่ายได้ เรามีเครื่อง จำนวนน้อยที่ต้องกังวล และรูปแบบความล้มเหลวของแอปพลิเคชันค่อนข้างเป็นแบบ binary—แอปพลิเคชันมักจะขึ้นทั้งหมด หรือล่มทั้งหมด ด้วยสถาปัตยกรรม microservice เราเข้าใจผลกระทบหรือไม่หาก instance เดียวของ service ล่มลง?
ด้วยระบบ monolithic หาก CPU ของเราติดอยู่ที่ 100% เป็นเวลานาน เรารู้ว่ามันเป็นปัญหาใหญ่ ด้วยสถาปัตยกรรม microservice ที่มี process นับสิบหรือนับร้อย เราพูดแบบเดียวกันได้ไหม? เราจำเป็นต้องปลุกใครสักคนตอนตีสาม เมื่อ process เดียวติดอยู่ที่ CPU 100% หรือไม่?
โชคดีที่มีแนวคิดมากมายในพื้นที่นี้ที่ช่วยได้ หากคุณต้องการสำรวจแนวคิดนี้อย่างละเอียดเพิ่มเติม ผมแนะนำ Distributed Systems Observability โดย Cindy Sridharan (O'Reilly) เป็นจุดเริ่มต้นที่ยอดเยี่ยม แม้ว่าเราจะพาไปดู monitoring และ observability ในแบบของเราเองใน Chapter 10 ด้วย
Security (ความปลอดภัย)
ด้วยระบบ single-process monolithic ข้อมูลส่วนใหญ่ของเราไหลอยู่ภายใน process นั้น ตอนนี้ ข้อมูลไหลผ่าน เครือข่ายระหว่าง service ของเรามากขึ้น สิ่งนี้อาจทำให้ข้อมูลของเราเสี่ยงต่อการถูกสังเกตระหว่างการส่งข้อมูล มากขึ้น และอาจถูกจัดการเป็นส่วนหนึ่งของการโจมตีแบบ man-in-the-middle ด้วย นั่นหมายความว่าคุณอาจต้องใส่ใจ มากขึ้นในการปกป้องข้อมูลระหว่างการส่ง และทำให้แน่ใจว่า endpoint ของ microservice ของคุณได้รับการปกป้อง เพื่อให้เฉพาะฝ่ายที่ได้รับอนุญาตเท่านั้นที่สามารถใช้งานได้ Chapter 11 อุทิศให้กับการมองความท้าทายในพื้นที่นี้โดยเฉพาะ
Testing (การทดสอบ)
ด้วย automated functional test ประเภทใดก็ตาม คุณมีการชั่งน้ำหนักที่ละเอียดอ่อน ยิ่งการทดสอบครอบคลุม ฟังก์ชันการทำงานมากเท่าไร—นั่นคือขอบเขตของการทดสอบกว้างขึ้นเท่าไร—คุณก็ยิ่งมั่นใจในแอปพลิเคชันของคุณ มากขึ้นเท่านั้น ในทางกลับกัน ยิ่งขอบเขตของการทดสอบใหญ่ขึ้น ก็ยิ่งยากขึ้นที่จะตั้งค่าข้อมูลทดสอบและ fixture ที่รองรับ การทดสอบยิ่งใช้เวลานานขึ้นในการรัน และยิ่งยากขึ้นที่จะหาว่าอะไรพังเมื่อมันล้มเหลว ใน Chapter 9 ผมจะแบ่งปันเทคนิคหลายอย่างสำหรับการทำให้การทดสอบทำงานได้ในสภาพแวดล้อมที่ท้าทายมากขึ้นนี้
End-to-end test สำหรับระบบประเภทใดก็ตามอยู่ที่ปลายสุดของสเกลในแง่ของฟังก์ชันการทำงานที่พวกมันครอบคลุม และเราคุ้นเคยกับการที่พวกมันมีปัญหามากกว่าในการเขียนและดูแลรักษาเมื่อเทียบกับ unit test ที่มีขอบเขตเล็กกว่า บ่อยครั้งมันก็คุ้มค่า เพราะเราต้องการความมั่นใจที่มาจากการมี end-to-end test ที่ใช้ระบบของเราในแบบเดียว กับที่ผู้ใช้อาจใช้
แต่ด้วยสถาปัตยกรรม microservice ขอบเขตของ end-to-end test ของเรากลาย ใหญ่ มาก ตอนนี้เราจะต้องรันการทดสอบข้ามหลาย process ซึ่งทั้งหมดต้องถูก deploy และกำหนดค่าอย่างเหมาะสมสำหรับ scenario การทดสอบ เรายังต้องเตรียมพร้อมสำหรับผลลบปลอมที่เกิดขึ้นเมื่อปัญหาด้านสภาพแวดล้อม เช่น service instance ล้มลงหรือ network time-out ของการ deploy ที่ล้มเหลว ทำให้การทดสอบของเราล้มเหลว
แรงเหล่านี้หมายความว่าเมื่อสถาปัตยกรรม microservice ของคุณเติบโตขึ้น คุณจะได้ผลตอบแทนที่ลดลงเมื่อพูดถึง end-to-end testing การทดสอบจะมีต้นทุนมากขึ้นแต่จะไม่สามารถให้ความมั่นใจในระดับเดียวกับที่เคยให้ในอดีตได้ สิ่งนี้จะผลักดันให้คุณไปสู่รูปแบบการทดสอบใหม่ เช่น contract-driven testing หรือการทดสอบใน production รวมถึงการสำรวจเทคนิค progressive delivery เช่น parallel run หรือ canary release ซึ่งเราจะดูใน Chapter 8
Latency (Latency)
ด้วยสถาปัตยกรรม microservice การประมวลผลที่ก่อนหน้านี้อาจทำในเครื่องเดียวบน processor เดียว ตอนนี้อาจ จบลงด้วยการถูกแบ่งข้ามหลาย microservice ที่แยกจากกัน ข้อมูลที่ก่อนหน้านี้ไหลอยู่ภายใน process เดียว ตอนนี้ ต้องถูก serialize, ส่งผ่าน และ deserialize ผ่านเครือข่ายที่คุณอาจใช้งานมากกว่าที่เคยมา ทั้งหมดนี้อาจส่งผล ให้ latency ของ ระบบ แย่ลง
แม้จะยากที่จะวัดผลกระทบที่แน่นอนต่อ latency ของ operation ในขั้นตอนการออกแบบหรือเขียนโค้ด นี่คืออีกเหตุผล หนึ่งที่สำคัญที่จะดำเนินการย้ายไป microservice แบบค่อยเป็นค่อยไป ทำการเปลี่ยนแปลงเล็กๆ แล้ววัดผลกระทบ นี่ สมมติว่าคุณมีวิธีวัด end-to-end latency สำหรับ operation ที่คุณสนใจ—เครื่องมือ distributed tracing อย่าง Jaeger สามารถ ช่วยได้ที่นี่ แต่คุณยังต้องเข้าใจว่า latency แค่ไหนที่ ยอมรับได้ สำหรับ operation เหล่านี้ บางครั้งการทำให้ operation ช้าลงก็ยอมรับได้อย่างสมบูรณ์ ตราบใดที่มันยังเร็ว เพียงพอ!
Data Consistency (ความสอดคล้องของข้อมูล)
การเปลี่ยนจากระบบ monolithic ที่ข้อมูลถูกจัดเก็บและจัดการในฐานข้อมูลเดียว ไปสู่ระบบที่กระจายมากขึ้นมาก ที่ หลาย process จัดการ state ในฐานข้อมูลที่แตกต่างกัน ก่อให้เกิดความท้าทายที่อาจเกิดขึ้นเกี่ยวกับความสอดคล้อง ของข้อมูล ในขณะที่ในอดีตคุณอาจพึ่งพา database transaction เพื่อจัดการการเปลี่ยนแปลง state คุณจะต้องเข้าใจ ว่าความปลอดภัยแบบเดียวกันนั้นไม่สามารถให้ได้ง่ายๆ ในระบบแบบกระจาย การใช้ distributed transaction ในกรณี ส่วนใหญ่พิสูจน์แล้วว่ามีปัญหาอย่างมากในการประสานการเปลี่ยนแปลง state
แทนที่จะเป็นแบบนั้น คุณอาจต้องเริ่มใช้แนวคิดอย่าง saga (สิ่งที่ผมจะอธิบายอย่างละเอียดใน Chapter 6 ) และ eventual consistency เพื่อจัดการและให้เหตุผลเกี่ยวกับ state ในระบบของคุณ แนวคิดเหล่านี้อาจต้องการ การเปลี่ยนแปลงพื้นฐานในวิธีที่คุณคิดเกี่ยวกับข้อมูลในระบบของคุณ ซึ่งอาจน่ากลัวมากเมื่อย้ายระบบที่มีอยู่แล้ว นี่คืออีกเหตุผลที่ดีที่จะระมัดระวังในความเร็วที่คุณแยกส่วนแอปพลิเคชันของคุณ การรับแนวทางแบบค่อยเป็นค่อยไป ในการแยกส่วน เพื่อให้คุณสามารถประเมินผลกระทบของการเปลี่ยนแปลงสถาปัตยกรรมของคุณใน production ได้ เป็นสิ่ง สำคัญมาก