10 hidden monolith ที่ต่อให้คุณใช้ Microservices คุณก็ fail อยู่ดี

Chaowlert Chaisrichalermpol
5 min readJun 1, 2019

--

Photo by Nathan Dumlao on Unsplash

มี Video ตัวนึงที่ผมชอบมาก ดูซ้ำไปหลายรอบชื่อ 10 Tips for failing badly at Microservices โดย David Schmitz ถ้ามีเวลาแนะนำให้ดู เพราะนอกจากจะได้เนื้อหาแล้ว presentation ก็ทำได้เรียกว่าฮามาก เพื่อสรุปเนื้อหา วันนี้เรามาคุยหัวข้อใน presentation นี้กัน โดยจะเริ่มจากอันดับ 10

10. Polyglot แบบสุดซอย

ข้อดีของ Microservices มีเรื่องนึงคือแต่ละทีมมีอิสระสูง สูงมากจนทีมต่างๆ สามารถใช้ Tech Stack และภาษาต่างกันได้ (เรียกว่า polyglot) ทีมนึงสามารถใช้ php อีกทีมใช้ NodeJs อีกทีมใช้ Spring ก็ได้ แต่การทำแบบนี้ก็มีข้อเสียคือ Dev ค่อนข้าง rotate ลำบาก งานที่ apply กับทุก project ก็จะ apply ลำบากด้วย และเนื่องจากแต่ละ Tech Stack ใช้ library ต่างกัน ทำให้ปัญหาที่เจอบน production ต่างกัน ทำให้ maintain ลำบาก

นี่เป็นลำดับที่ 10 ดังนั้นปัญหานี้จริงๆ ก็มีทางแก้ไข มี pattern ในหนึ่งเรียกว่า Sidecar คือการมีอีก process นึงที่รวมเข้าไปใน container ด้วย เพื่อทำงานที่ apply กับทุก project เช่น traffic management, logging, monitoring

9. Data Monolith

หัวใจของ Microservice คือการเป็นอิสระต่อกัน แต่ถ้าแชร์ database กัน สุดท้ายก็เป็น monolith อยู่ดี สมมติวันนึง table ที่ใช้อยู่เกิดมีการแก้ไข ก็จะกระทบกับ service ตัวอื่นอีกหลายตัว และเนื่องจากการแตะ database ที่เป็น monolith มีผลกระทบเยอะ การแตะเลยมีความเสี่ยง เลยกลับกลายเป็นว่าการปรับ data model เป็นเรื่องใหญ่ ทำให้ไม่สามารถปรับเปลี่ยนได้ตามความต้องการ

ถ้าคุณออกแบบระบบใหม่ และคุณพบสถานการณ์ว่าจำเป็นต้องใช้ share database คุณอาจจะออกแบบ domain model ไม่ถูกต้อง หากคุณต้องการ consistency ลองดู Sega pattern โดยใช้ state เป็นตัวควบคุม หากคุณต้องการ performance ก็ทำ caching

8. Event Monolith

Technic นึงสำหรับการ decouple Microservices ออกจากกัน คือเอา CQRS และ Event Sourcing เข้ามาช่วย แต่เมื่อ services ใช้ event store ตัวเดียวกันก็จะคล้ายกับ Data Monolith ด้านบน แต่ความยากกว่า Data Monolith คือ เราอาจจะมี event 2 versions ในเวลาเดียวกันก็ได้ ดังนั้น โดยทั่วไป event ไม่ควรจะ conflict เวลามีการแก้ไข model แต่หากต้อง conflict นั่นหมายความว่าคุณต้องมี event handler ไว้ handle ทั้ง 2 versions และคุณต้อง handle event ตัวนี้ในทุกๆ services

Greg Young แนะนำว่า หากต้องเปลี่ยน event จนมันต้อง conflict ให้เราสร้าง event ใหม่เลยดีกว่า และมี converter แปลงจาก v1 เป็น v2 หรือถ้าคุณมี versions เยอะมากๆ อยากจะโละมันทิ้ง Greg Young แนะนำให้ transform event ย้อนหลังเป็นอันใหม่โดยไม่แตะต้องของเก่า และเมื่อย้ายทุกอย่างไป event ใหม่หมดแล้ว ก็ลบ event stream เก่าทิ้ง

7. Home Grown Monolith

ถ้าคุณสร้าง Framework ของตัวเองขึ้นมา แล้วให้ Microservices ทุกๆ ตัวใช้ Framework ตัวนั้น คุณอาจจะได้เรื่อง reusability แต่การมี Framework เท่ากับผูก Microservices เข้าด้วยกันให้เป็น Monolith รูปแบบหนึ่ง เช่น เวลาจะ deploy แทนที่แต่ละ service จะสามารถ deploy ได้อย่างอิสระ แต่กลับต้องมารอลงพร้อมกัน เพราะทุก service ต้องรอ framework ตัวเดียวกัน

นอกจากนี้ความแย่ของการมี Framework ทำเองคือ คนสร้าง Framework จะมีอำนาจต่อรองสูงมาก เนื่องจาก Framework นั้นจะทำมาเฉพาะทาง หาคนแทนไม่ได้เลย

6. ลงระบบด้วยมือ

งานๆ หนึ่งจะประกอบด้วย คนต้องการงาน (Want) คนที่มีความรู้ในการทำ (Know) คนที่มีสิทธิ์ (Privilege) และคนที่โดน assign ให้ลงมีทำ (Time) ถ้าเราสามารถรวมองค์ประกอบเหล่านี้มาอยู่คนๆ เดียว หรือทีมเดียวกันได้มากเท่าไหร่ งานก็จะมีประสิทธิภาพมากเท่านั้น

การลงระบบเป็นงานที่คน 4 กลุ่มด้านบนมักเป็นคนละคนกัน คือ Product Owner ที่ต้องการ release ใหม่ (Want) ทีม Dev ที่รู้ว่าองค์ประกอบของระบบมีอะไรบ้าง (Know) ทีม Ops ที่มีสิทธิ์ลงระบบ (Privilege & Time) ถ้าเราลงระบบแบบ manual นอกจากจะ burn เวลาของคนทุกคนแล้ว มันยังเกิดข้อผิดพลาดระหว่าง deploy ได้ง่ายมาก

การทำ CI/CD เป็นการรวมการลงระบบให้เลือกแค่ step เดียว และเป็นการโอนย้าย 4 องค์ประกอบ (Want, Know, Privilege & Time) ให้อยู่แค่คนๆ เดียว

5. Distributed Monolith

ในโลกของ Microservices เราจะไม่ focus ให้ระบบมันเสถียรที่สุด เพราะระบบที่ดีแค่ไหนก็มีสิทธิ์ down ได้ แต่เราจะ focus ที่เวลาในการ recover ที่สั้นที่สุด เมื่อเกิดปัญหาต้อง recover ได้รวดเร็ว ดังนั้น services ทุกตัวต้องทำงานอยู่บนสมมติฐานที่ว่า ระบบอื่นๆ ที่เราเรียกใช้ อาจจะกำลัง down อยู่ก็ได้ เพราะไม่เช่นนั้นแทนที่จะพังแค่ระบบเดียว ก็พังกันทั้งระบบอยู่ดี

Microservices มี pattern ที่เกี่ยวข้องกับเรื่องนี้มากมาย เช่น Bulkhead หรือการแบ่ง pool ถ้า pool นึงตาย ที่เหลือยังทำงานได้, Circuit Breaker เมื่อต่อระบบนึงไม่ได้ ก็มี action สำรองว่าจะทำงานยังไง, Compensating Transaction เมื่อเกิดปัญหาระหว่างทางจะ undo action ยังไง, Retry หรือการลองใหม่อีกครั้ง

4. SPA Monolith

Microservices กับ front-end นี่เป็นอะไรที่ย้อนแย้งกันมาก Microservices บอกให้แบ่ง service ตาม business capability แต่ front-end มันแบ่งอย่างนั้นไม่ได้ UX คือสิ่งสำคัญ service ต่างๆ ต้องทำงานร่วมกันเพื่อมอบประสบการณ์ที่ดีที่สุดให้ลูกค้า แต่เมื่อ front-end รวมเป็นอันเดียว front-end ก็เริ่มจะเป็นคอขวด และเนื่องจากมีหลาย features รวมๆ กัน การแก้ไขก็เป็นเรื่องยากขึ้นเรื่อยๆ

สิ่งที่ตลกร้ายกว่าก็คือ เราเริ่มรู้ตัวแล้วว่า front-end คือ monolith ต้องแตกมันออก ปัจจุบัน มีคำว่า “Micro front-ends” ซึ่งเป็น 1 ใน technology radar ที่ adopt แล้ว ของ ThoughtWorks แต่ปัจจุบันยังไม่มี practices หรือ standard มาตรฐานเพื่อทำ Micro front-ends ผมเคยเขียน blog แนะนำ Micro front-ends มาแล้ว มีวิธีแก้ปัญหา อาทิใช้ link, ใช้ iframe, ใช้ Micro front-end frameworks ต่างๆ, ใช้ Web Components, หรือจะใช้ library แค่ตัวเดียวแต่ develop แบบ component based ลองไปอ่านกันและปรับใช้ดูว่าอันไหนเหมาะกับเราที่สุด

3. Decision Monolith

อันดับ 3 แล้ว มันจะเริ่มไม่เกี่ยวกับ technical อีกต่อไป ใครๆ ก็อยากเป็นคนตัดสินใจ แต่คนตัดสินใจมักไม่ใช่คนปฏิบัติงาน ดังนั้นคนตัดสินใจมักจะตัดสินว่าอะไรเสี่ยงน้อยที่สุด ถ้ายังตัดสินใจไม่ได้ก็ไม่รีบเพราะปัญหาไม่ได้อยู่กับตัว แล้วให้คนปฏิบัติงานทนๆ กันไป แต่ต่อให้คนตัดสินใจเป็นคนกล้าเสี่ยง แต่อยู่บนหอคอยงาช้างคอยสั่งการอย่างเดียว ก็ไม่ได้รับ feedback loop จาก operation อยู่ดี

หากท่านเป็นคนที่ตัดสินใจ อย่าคิดว่าทุกคนไม่ฉลาด ธุรกิจทุกวันนี้ต้องการความคล่องตัว ทุกๆ 5–10 ปี ก็จะมีบริษัทที่ disrupt และถูก disrupted ขนาดบริษัทยักษ์ใหญ่อย่าง Amazon มีคนตั้ง 500,000 คน ยังกระจายการตัดสินใจลงไปถึงส่วนของ operation ที่อยู่ใกล้ชิดกับลูกค้ามากที่สุด (ลองอ่าน blog เก่า เกี่ยวกับ Amazon)

2. Business Monolith

ถ้าเราแบ่งทีม Business ออกจากทีม Technical สิ่งที่เกิดขึ้นตามธรรมชาติคือ Business กับ Technical คุยกันน้อยลง มีการกำหนดกฏเกณฑ์การส่งมอบงานมากขึ้น และเมื่อมีกฏเกณฑ์ก็ต้องมี Change management และการพัฒนาก็จะเป็นรูปแบบ waterfall ไม่ใช่ agile (ต่อให้บางที่ใช้ agile ก็เป็น slow agile)

อย่าคิดว่าเรื่อง Agile กับ DevOps เป็นเรื่องของ technical มีแนวคิดนึงเรียกว่า Lean Startup ที่ concept มันเข้ากับ Agile กับ DevOps ทีม Business และทีม Technical ต้องทำงานร่วมกัน สร้างสิ่งที่เล็กๆ ที่พอใช้งานได้เรียกว่า MVP (minimum viable product) แล้วก็ลองตลาด แล้วก็เอา feedback มาปรับแก้สินค้าใน version ถัดไป

  1. HR-driven Architecture

สมมติองค์กรเรามีทีมทำ UI ทีมทำ Services ทีมทำ Data แต่ละทีมมี Product Owner ด้วย อย่างนี้จะเรียกว่าเราทำ Microservices ได้หรือเปล่า? วิธีนี้อาจจะมีข้อดีคือทีมจะ specialize ในงานของตัวเอง แต่ปัญหาคือแต่ละทีมจะ focus แค่ปัญหาของทีมตัวเอง ส่วนการสื่อสารข้ามทีมจะทำผ่าน specification และสุดท้ายงานที่ออกมาก็ต้อง Deploy พร้อมๆ กัน และเมื่อมีระบบนึงพังก็จะพังทั้งระบบ

หลักการของ Microservices คือต้องแบ่งระบบตาม business capability แต่ละส่วนต้องมีอิสระต่อกัน และเน้นเรื่อง resilience ในทีมๆ หนึ่งของ Microservices จะประกอบด้วย cross functional teams ในทีมมีทุกคนที่เกี่ยวข้องตั้งแต่ Business ไปยัน Operation ทำให้ทีมเดียวกันนี้ เข้าถึง business intent และใกล้ชิดลูกค้ามากที่สุด สามารถตอบสนองต่อปัญหา หรือความต้องการของลูกค้าก็จะทำได้อย่างรวดเร็ว

จบแล้วครับ ถึงแม้คุณจะบอกว่าทีมคุณใช้ Microservices แต่ลองหา hidden monolith เหล่านี้ Microservices มันทำให้ระบบโดยรวมของเราซับซ้อน และเมื่อรวมกับ monolith แบบต่างๆ ด้านบน จะทำให้ระบบของคุณเปราะบาง กลายเป็นว่าระบบเราทั้งซับซ้อนและเปราะบาง หวังว่าบทความนี้จะทำให้คุณได้เห็น hidden monolith ที่ซ่อนอยู่ในระบบของคุณครับ

--

--