จาก Monolith สู่ Microservices

🤔 เวลาเขาถอดชิ้นส่วน Monolith ให้กลายเป็น Microservices เขาทำกันยังไงนะ ?

จากบทความ Microservices Tips เราจะพอเข้าใจแล้วว่าการที่จะทำ Microservices Architecture นั้น เราไม่ควรออกแบบให้มันเป็น microservices ตั้งแต่แรกเพราะมันมีปัญหาเยอะมาก แต่เราควรที่จะทำเป็น monolith ไปก่อน จนกว่ามันจะสุกงอมแล้วเราถึงจะค่อยๆถอดแต่ละชิ้นส่วนของมันให้ออกมาเป็น microservice เรื่อยๆนั่นเอง

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

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

🤔 ถอดชิ้นส่วนเป็น service เขาทำยังไงกันนะ ?

🔥 มองหาชิ้นส่วนที่จะถอด

หลังจากที่โปรแกรมแบบ Monolith เขาเราเริ่มมีขนาดใหญ่และเราเข้าใจในตัวขอบเขตของงานในแต่ละเรื่องแล้ว เราก็จะเริ่มมองหาว่าจะเอางานในส่วนไหนเปลี่ยนไปเป็น microservice ดี ซึ่งถ้าเจอแล้วเราจะต้องเอาชิ้นงานส่วนนั้นไปให้หมดแบบถอนรากถอนโคนมันเลย หรือที่เราเรียกว่า เอาไปให้หมดทั้ง Vertical ของมันนั่นเอง สาเหตุที่ต้องเอามันไปแบบถอนรากนั้นเพราะว่า microservice 1 ตัวมันควรจะต้องดูแลงานในเรื่องของมันทั้งหมดตั้งแต่หัวจรดเท้า ดังนั้นเวลาที่จะยกงานเรื่องนั้นๆออกไป มันเลยจะต้องยกออกไปทั้งหมดยังไงล่ะ ไม่อย่างนั้นมันจะทำให้มีงานเรื่องเดียวกันแต่อยู่ต่าง service เกิดขึ้น ซึ่งมันจะทำให้เวลาที่ต้องแก้งานเรื่องนั้นๆ มันจะต้องแก้ ต้องเทส ต้องเอางานขึ้นเซิฟเวอร์ใหม่ ทั้ง 2 services เลยทำให้มันเสียความคล่องตัวไปนั่นเอง

พูดให้เห็นภาพง่ายๆ ตอนแรกเรากับแฟนก็ใช้ชีวิตร่วมกันสุขสบายดี แต่วันนึงก็เลิกกันขึ้นมา ทำให้เราต้องย้ายออกจากบ้านของเขาไป คำถามคือเราจะทิ้งของๆเราไว้ในบ้านนั้นด้วยไหม? เมื่อต้องการจะใช้เราต้องเดินกลับไปบ้านนั้นทุกครั้งเหรอ? แล้วไหนจะต้องไปขออนุญาตให้แฟนเปิดประตูให้เราเข้าไปใช้เจ้าของสิ่งนั้นอีกเนี่ยนะ .... บร๊าไปแบ้ว

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

ข้อควรระวัง ก่อนที่จะเริ่มต้นทำ microservice architecture อย่าลืมว่าทุกคนในทีมจะต้องเข้าใจหลักในการทำ architecture นี้ด้วยนะ ไม่อย่างนั้นเราจะได้ service ที่เป็น monolith กระจายเต็มไปหมด ซึ่งแย่กว่าเดิมอีก

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

🔥 เตรียมสภาพแวดล้อมที่เหมาะสม

หลังจากที่เลือกได้แล้วว่าเราจะถอดชิ้นส่วนไหนให้กลายเป็น Microservice ถัดไปเราจะต้องเตรียมสภาพแวดล้อมให้กับ service ตัวนั้นๆด้วย เพราะเจ้า microservice มันต้องการความคล่องตัวสูง ดังนั้นเราจะต้องทำให้มันสามารถ

  • ถูกนำเอา Build เมื่อไหร่ก็ได้ อยาก Test มันเมื่อไหร่ก็ได้ และต้องเป็น Automation ด้วยนะ

  • สามารถเอา service ไปขึ้นเซิฟเวอร์ในแต่ละ environment ได้ ซึ่งกระบวนการนี้เราเรียกว่าการทำ Continuous Integration (CI) กับ Continuous Delivery (CD)

  • มีโครงสร้างที่สามารถทำ Reliable & Secure network ภายใน

  • มีระบบในการจัดการ Containers ต่างๆในการเอางานขึ้นลง ตรวจสอบ service ต่างๆว่ายังทำงานอยู่ดีมีสุขหรือเปล่า เช่น Container Orchestration

  • มีระบบจัดการ API เพื่อจัดการคนที่สามารถเข้ามาทำงานกับ service หรือแม้กระทั่งจัดการ API versioning ต่างๆ ซึ่งเราเรียกตัวนี้ว่า API management system

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

🔥 ค่อยๆปรับแก้ไป

หลังจากที่เลือกชิ้นส่วนได้แล้ว + ทีมมีความรู้ในการจัดการ environment ของ microservice แล้ว ถัดไปเราก็จะค่อยๆย้ายการทำงานใน monolith ตัวเดิมมาเป็น microservice นั่นเอง โดยเราจะไม่ copy งานเดิมมาวางไว้แล้วถือว่าจบนะ แต่เราจะต้องค่อยๆปรับให้มันทำงานกับโครงสร้างใหม่นี้ด้วย เพราะถ้ามันมีการเรียกใช้งานของที่อยู่นอกขอบเขตของมัน (Bounded context) นั่นหมายความว่า มันจะต้องเรียกใช้งานผ่าน API นั่นเอง และในทางกลับกัน โค้ดเก่าที่อยู่ใน monolith ถ้าจะมาเรียกใช้งานตัว service ที่เราย้ายออกมาแล้ว เราก็จะต้องมี API ให้เขาเรียกด้วยเช่นกัน ดังนั้นในจุดนี้จะต้องค่อยๆปรับไปเรื่อยๆจนกว่าจะเสร็จ และอย่าลืมทดสอบด้วยนะว่าตอนเรียกใช้ Pipeline ที่เตรียมไว้มันทำงานได้จริงๆ ซึ่งถ้าได้ครบหมดทุกอย่าง ก็เริ่มกลับไปหาชิ้นถัดไปมาถอดชิ้นส่วนได้เลยจร้า

🤔 ขอตัวอย่างหน่อยได้ป่ะ ?

ตัวอย่างนี้ขอเอามาจากบทความ How to break Monolith into Microservices นะครับ ซึ่งในบทความเขากำลังทำระบบขายของออนไลน์ โดยในบทความเขาเลือกถอดชิ้นส่วนไล่จากแบบง่ายไปถึงแบบยากตามด้านล่างนี้เลย

🔥 แยกชิ้นส่วนที่ไม่เกี่ยวข้องกับใคร

ชิ้นส่วนแรกที่ทีมเขาเลือกถอดออกมาคือ ระบบยืนยันตัวตน (Authentication) ส่วนสาเหตุที่เลือกทำตัวนี้เป็นตัวแรกก็เพราะว่า มันเล็กและทำให้ทีมของเขาได้ลองสร้างของที่มันง่ายๆก่อน และอยากให้ทีมคุ้นเคยกับการทำ Microservices Architecture นั่นเอง ตามรูปด้านล่างเลย

อธิบายรูปด้านบน เราก็จะเริ่มไปสร้าง service ตัวใหม่ที่ทำงานเรื่อง authentication โดยเฉพาะออกมา แล้วให้ระบบ monolith เติมได้ลองเปลี่ยนมาใช้เจ้า service ที่แยกออกมา โดยเรียกทำงานผ่าน API contracts นั่นเอง

หลักในการแยก เวลาถอดของมาทำเป็น microservice เราควรจะเลือกถอดตัวที่ เมื่อถอดแล้วมันไม่ยุ่งเกี่ยวกับ monolith ได้จะดีมาก เพราะไม่อย่างนั้นตัว service ของเราก็จะยังผูกติดกับ monolith อยู่ดีนั่นเอง ดังนั้นเวลาเลือกให้ดูด้วยว่า monolith ต่างหากที่มาผูกติดกับ microservice

🔥 แยกชิ้นส่วนของที่ผูกกัน

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

คำตอบก็คือเลือกทำระบบโปรโมชั่นก่อน เพราะถ้าเลือกระบบซื้อสินค้าก่อนมันจะทำให้ service ของเรายังต้องผูกติดกับ monolith เพราะจะซื้อสินค้ามันจะต้องดูโปรโมชั่นก่อน ซึ่งเจ้าโปรโมชั่นมันยังอยู่ใน monolith นั่นเอง

ข้อแนะนำ ถ้าเกิดเหตุการณ์ที่เลี่ยงไม่ได้ เลยทำให้ microservice ต้องไปผูกติดกับ monolith จริงๆแล้วละก็ ให้เราสร้าง API ชุดใหม่ใน monolith ออกมาให้ microservice ใช้งานเลยจะดีกว่า เพราะอย่างน้อยเรามันใจได้ว่าจะไม่มีหน้าที่การรับผิดชอบจาก monolith ไหลเข้ามาปนใน service แน่ๆ

🔥 แยกของที่ผูกกันแบบเหนียวแน่น

ในบางกรณีเราก็ไม่สามารถบอกได้ว่าเจ้าสิ่งนั้นกับสิ่งนี้มันจะแยกเรื่องกันได้ยังไง ซึ่งโดยปรกติสาเหตุนั้นจะเกิดจากการที่เรายังไม่เคลียในเรื่องของ Domain concept นั่นเอง ดังนั้นวิธีการแก้ไขคือ เราจะต้องมานั่งทำความเข้าใจว่าจริงๆแล้วมันมี domain เรื่องอะไรบ้าง แล้วค่อยๆแก้ปมแต่ละเรื่องออก แล้วค่อยเอาไปทำเป็น microservice ต่อนั่นเอง

ในตัวอย่างการผูกกันแบบเหนียวแน่นของเขาเกิดจากการใช้ web session เลยทำให้การแยกของต่างๆทำได้ยากขึ้น เช่น ตอนซื้อของเราจะต้องเก็บว่าผู้ใช้คนนนี้ชอบอะไร มีรายการที่อยากได้อะไรบ้าง ข้อมูลการจ่ายเงินเป็นยังไงบ้าง ดังนั้นเขาเลยต้องเอามานั่ง define domain concept เสียใหม่ว่าจริงๆแล้วมันคือเรื่องอะไรบ้าง แล้วค่อยสร้าง service เพื่อแก้ไขมันทีละตัวนั่นเอง ตามรูปด้านล่าง

😵 พอก่อนเยอะละ

ในบทความที่ถอดรหัสมาเขามีเขียนไว้อีกเยอะเลย เดี๋ยววันหน้าเอามาลงต่อให้ละกันนะ