บาปแห่ง Microservice

Teerayut Hiruntaraporn
2 min readMay 8, 2022

--

อันนี้เป็นความเห็นส่วนตัว จากที่ดูๆ ทำๆ มา

CR: https://www.linkedin.com/pulse/api-microservices-hell-has-obvious-boundary-nor-gates-trojan/?trk=related_artice_The%20(API%20and%20microservices)%20hell%20has%20no%20(obvious)%20boundary%20nor%20gates%20to%20defend_article-card_title

1. แยก Microservice เพราะไม่อยากเขียนโค้ดกับเพื่อน

เหตุผลที่มักจะอ้างอิงเรื่องนี้คือ การเอา Single Responsibility Principle มาอ้างอิง ในทางที่ไม่ใช่ส่ิงที่ควรจะเป็นนัก

เพราะการแยกความรับผิดในมุมของ SRP เป็นเรื่องของ ความรับผิดชอบของ Module ต่อ System เพื่อความง่ายในการควบคุม เปลี่ยนแปลง และบ่งชี้ถ้าเกิดปัญหาขึ้น

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

  1. Single Point of Failure — ซึ่งคำว่า Point ในที่นี้คือคนด้วย
  2. New Legacy — สุดท้ายระบบที่จัดการโดยคนเดียวโดยไม่มีใครมาเอี่ยวเลย จะกลายเป็น Legacy ที่คนอื่นไม่กล้าแตะต้อง ทำให้เสียเวลาและโอกาสในการจัดการอีกหลายอย่าง

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

กิจกรรมอื่นๆ เช่น Code Review , Pair ถ้าจัดการดีๆ ก็จะมีส่วนช่วยได้

2. ใช้ Microservice แต่ทำงานแบบตัวใครตัวมัน

กรณีนี้คือ คิดจะทำ Microservice แต่ไม่เคย Sync กันในภาพใหญ่ว่าระบบวิ่งกันยังไง ระบบเราทำงานและต้องคุยกับใครบ้าง หรือมีใครต้อง Depend กับเราบ้าง

สิ่งที่เกิดขึ้นคือ การที่คนทำ Service จะทำอะไรตามใจฉัน โดยไม่สนใจคนที่จะใช้งาน เช่น

  • อยากเปลี่ยน api ก็เปลี่ยน ไม่แจ้ง เวลาคนอื่นเจอปัญหา ก็บอกว่า update ใน document แล้ว ซึ่งมันไม่เพียงพอในการสื่อสาร
  • เวลาเกิดปัญหา มักจะบอกว่า service ที่ใช้อยู่ทำงานถูกต้องแล้ว แต่ไม่สามารถไล่ Flow ได้ว่าของวิ่งมาถึง service และออกจาก service เป็นยังไง

ถ้าจะทำ Microservice การสื่อสารสำคัญมาก เพราะวัตถุประสงค์ของ Microservice มันต้องการให้เกิด Decouple และ Independent Service แต่ การจะทำให้ เกิด Independent ได้จริงๆ ต้องมี Direction หรือพิมพ์เขียวที่แข็งแรงเพียวพอ ไม่เช่นนั้น จะวิ่งไปคนละทิศละทาง ถ้าเป็นทีมบอลก็เรียกว่าบอลไม่มีทรงได้

ย้อนกลับมาดูเรื่องของแผนภาพต่างๆ use case ต่างๆ ว่ามีสำหรับอ้างอิงหรือไม่ วิธีการในการ update api เราทำอย่างไร วิธีการ inform user ที่จะใช้ api ของเราคือท่าไหน ทั้งหมดนี้เป็นสิ่งที่ควรจะต้องมาดูกัน

3. ไม่รักษาคุณภาพและความน่าเชื่อถือของ Service ที่เขียน

แม้ว่าระบบจะถูกทำให้แยกกันไปแล้ว แต่ Dependency มันก็ยังมีอยู่ ซึ่งบางครั้งอาจจะวุ่นวายกว่า การทำ Monolith ก็เป็นได้ เพราะ Monolith เดิม ถ้าจะตาย ก็มักตายทั้งก้อน นั่นหมายถึง state เดียว

แต่ในกรณีของ Microservice เวลาที่ตัวใดตัวหนึ่งตาย มันส่งผลต่อ ตัวที่วิ่งๆ กันอยู่ ที่จะต้องจัดการ State กันมากมาย ซึ่งอาจจะมีหลายจุด

ตรงนี้ถ้า ระบบตรงไหนไม่ให้ความน่าเชื่อถือที่เพียงพอ จะทำให้เกิดปัญหาได้

และเมื่อใดที่เพื่อนร่วมทีมต้องมาเขียน Test เพื่อ Proof ว่า Service เราทำงานถูกไหม มันเป็น red flags

ตรงนี้กลับมายังเรื่องที่เป็นพื้นฐานสำคัญคือ การออกแบบ และการทดสอบระบบ Developer ในปัจจุบันถูกคาดหวังว่า ควรจะมี Behavioral Test ที่ Contract เพื่อตรวจว่า งานที่ทำ มีพฤติกรรมในรูปของ Blackbox เป็นไปตามที่คาดหวัง ในมุมมองของผู้ใช้ หรือไม่

Standard ต่างๆ เช่น Code Quality, Security ที่ถูกจัดการ ผ่าน CI ควรจะต้องนำมาใช้งานกัน และ Developer ในปัจจุบันก็ถูกคาดหวังว่าจะทำการ integrate development cycle เข้าไปใน workflow การทำงานของตัวเองได้

Microservice อาศัย TeamWork และหลายครั้งต้องมีการฝึกซ้อมกันด้วย ไม่ได้ต่างจากทีมฟุตบอล เมื่อให้มีมาตรฐานที่สามารถวิ่งไปพร้อมกันทั้งทีมได้

แม้ว่าจะมีหลายคุณสมบัติ ที่ดูน่าดึงดูดทางทฤษฏี เช่น จะใช้ภาษาอะไรเขียนระหว่าง Service ก็ได้ ทำงานไม่ได้ขึ้นกัน

แต่ในความเป็นจริง ไม่มีองค์กรไหนจะปล่อย ให้ tech stack มันฟุ้ง ขนาดมี ภาษา 20 ภาษาในระบบ หรือไม่มีมาตรฐานจนเป็น Anarchy แล้วปล่อยทีมด้นสดกันไปตามยถากรรมได้

อยากมองให้เป็นการแก้ปัญหา แบบ Divide and Conquer คือสับเป็นเรื่องย่อยๆ แล้วรวมกันแก้ปัญหาใหญ่ ซึ่งจุดสุดท้าย มันต้องรวมกันเป็นหนึ่งเหมือนเดิมได้

มันไม่มีประโยชน์ที่จะแยกกันแล้ว แต่ไม่แก้ปัญหาที่ควรจะแก้ ถ้าอย่างนั้นกลับไปอยู่ Monolith ยังดีเสียกว่า

--

--

Teerayut Hiruntaraporn
Teerayut Hiruntaraporn

No responses yet