จากบทความเรื่อง How to ship production grade Go ?
แนะนำสิ่งที่ควรต้องทำก่อนที่จะทำการ deploy code ขึ้นไปยัง production server
ซึ่งมีหลายสิ่งอย่างที่ควรทำ
มิเช่นนั้นอาจจะเจอปัญหาต่าง ๆ มากมาย
ทั้งที่คาดหวังและไม่คาดหวังแน่นอน
ดังนั้นเรามาเตรียมความพร้อมกัน
จึงนำมาแปลและสรุปไว้นิดหน่อย
ในบทความนี้จะยกตัวอย่างระบบที่พัฒนาด้วยภาษา Go
มีเป้าหมายเพื่อส่งมอบ code
ที่มีความน่าเชื่อถือ
ที่สามารถระบุและบอกปัญหาได้
ซึ่งพร้อมสำหรับการ deploy
สิ่งที่นักพัฒนาระบบด้วยภาษา Go ต้องทำประกอบไปด้วย ( แบบ minimal สุด ๆ)
- การจัดการ Error ต่าง ๆ
- เมื่อเกิด Panic ขึ้นมา ควรทำการแจ้งให้รู้ทันที
- กำหนดมาตรฐานของ logging message ให้ชัดเจน
- ระบบงานต้องมีการเก็บ metric ต่าง ๆ เสมอ
- ทำการทดสอบในระดับต่าง ๆ ทั้ง unit, integration และ acceptance test พร้อมตรวจดูค่า coverage ด้วย
ระบบงานที่พัฒนาด้วยภาษา Go นั้น เรื่องของ Error และ Panic จำเป็นต้องจัดการให้ดี
มาดูที่ Error กันก่อน
ภาษา Go นั้นในแต่ละ method จะทำการ return ค่า Error กลับมาเสมอ เพื่อบอกสถานะของการทำงานว่าเป็นอย่างไร ถ้า Error เป็น nil แสดงว่ามีสถานะเป็นปกติ แต่ถ้าไม่ nil หมายถึงเกิดเหตุการณ์ที่ไม่ปกติขึ้นมาแล้ว ดังนั้น developer สามารถจัดการกับ Error ได้ง่ายมาก ๆ โดยที่ package สำหรับการจัดการ Error ที่ใช้บ่อย ๆ คือ Errors มันใช้ง่ายและมีประโยชน์อย่างมาก ที่สำคัญ ควรดัก error เดิมเพียงครั้งเดียวหรือที่เดียวนะ ไม่ใช่โยนและ print error message ไปเรื่อย ๆ รวมทั้งถ้าจะ print error message ต้องมีรูปแบบที่เป็นมาตรฐานทั้งระบบนะ มิฉะนั้นจะหา error ยากมาก ๆ [gist id="3ef77e23a1db736bb3781872a8529ea0" file="error.go"]ต่อมาเรื่องของ Panic ถ้าเกิดขึ้นมาต้องแจ้งหรือส่งข้อมูลออกมาทันที
ถ้าเกิด Panic ขึ้นมาในระบบงานแล้ว เราไม่สามารถจัดการได้เหมือน Error ดังนั้นถ้าจัดการหรือเรียกว่า recover ไม่ดีแล้ว ระบบงานก็จะหยุดทำงานได้เลย ซึ่งส่งผลเสียต่องานอย่างมาก สิ่งที่ควรทำคือ การ recover นั่นเอง ที่สำคัญคือ เมื่อเกิด Panic ขึ้นมาต้องแจ้งมายังทีมพัฒนาหรือผู้ดูแลด้วย เช่นผ่าน Email, Slack, Line หรืออะไรก็ตามที่ทำให้รู้ทันที เนื่องจาก Panic มันคือสิ่งที่สำคัญมาก ๆ อย่าปล่อยให้หลุดมือไปเด็ดขาด มาดูตัวอย่างกัน [gist id="3ef77e23a1db736bb3781872a8529ea0" file="panic.go"]เรื่องของ Logging ต้องกำหนดรูปแบบมาตรฐานขึ้นมา
ปัญหาของการจัดเก็บ log คือ รูปแบบที่ไร้ซึ่งมาตรฐาน ใครอยากเขียนแบบไหนก็ทำไป !! ซึ่งยากต่อการดูแล ซึ่งยากต่อการนำมาใช้งานโดยมี library ช่วยจัดการเยอะมาก ยกตัวอย่างเช่น Logrus, Zap และ Log15 เป็นต้นตัวอย่างที่ดี เช่น การจัดการในรูปแบบ key-value ด้วย Logrus [gist id="3ef77e23a1db736bb3781872a8529ea0" file="log.go"] เมื่อ log มีโครงสร้างที่ดีและมีมาตรฐานแล้ว ก็อย่าเขียนลงไฟล์อย่างเดียวนะ ให้ไปจัดเก็บในระบบอื่น ๆ บ้าง เพื่อช่วยให้วิเคราะห์ได้ง่ายขึ้น ยกตัวอย่างเช่น การใช้งาน ELK stack เป็นต้น
ต่อมาต้องจัดการเรื่องของ Metric ต่าง ๆ ด้วย
สิ่งที่มักจะมีเสมอคือ Monitoring สำหรับ Server เพื่อดูการใช้งานต่าง ๆ และ performance ของ server เช่น CPU, Memory, Disk และ Network เป็นต้น แต่สิ่งที่มักขาดหายไปเสมอคือ Metric ของระบบงานหรือ application นั่นเอง !! แต่คำถามที่เกิดขึ้นคือ จะเก็บ metric อะไรบ้างละ ? ตอบได้ยากมาก ๆ เพราะว่าแต่ละระบบมันแตกต่างกัน ความต้องการต่างกัน ยกตัวอย่างเช่น ระบบ REST APIs สิ่งที่อยากรู้น่าจะประกอบไปด้วย- จำนวน request และ response ในแต่ละช่วงเวลา เช่น นาที ชั่วโมง วัน เป็นต้น
- จำนวน success และ error ของ response
- Response time ของแต่ละ request รวมไปถึงค่าทางสถิติต่าง ๆ เช่น Max, Min, Average และ Percentile เป็นต้น
- แยกข้อมูลในแต่ละ endpoint
- เรื่องของ rate limit การใช้งานของผู้ใช้แต่ละคน
- StatD + Graphite
- Prometheus
- ELK
- มีเงินหน่อยก็ไปใช้พวก DataDog และ InfluxDB เป็นต้น
คำถามสุดท้ายคือ ระบบของคุณมีแล้วหรือยัง ?
เรื่องสุดท้ายคือ การทดสอบแบบอัตโนมัติ
ในฐานนะของ developer code ที่เขียนขึ้นมานั้น ถูกทดสอบหรือไม่ ? code ที่เขียนขึ้นมานั้น มีชุดการทดสอบแบบอัตโนมัติหรือไม่ ? การทดสอบมีทั้ง- End-to-End test
- Integration test
- Unit test
ถ้าคุณกำลังจะ deploy ระบบ ที่ไม่มีชุดการทดสอบขึ้น production แล้ว แนะนำว่าให้หยุด !! แล้วมาเขียนชุดการทดสอบก่อนเถอะนะ เพื่อทำให้มั่นใจก่อน deployที่สำคัญ Go มีตัวช่วยในการดูค่า test coverage อีกด้วยนะ โดยที่ไม่ต้องติดตั้งอะไรเพิ่มเลย ดังนั้นใช้มันซะ มันคือเพื่อที่ดีมาก ๆ ของคุณ
แนะนำให้ทำการทดสอบบ่อย ๆ และทำตั้งแต่เริ่มต้นนะครับ ชีวิตจะดีขึ้นกว่าเดิมแน่นอน แค่เขียน ชีวิตก็เปลี่ยนจากนั้นถ้ามีชุดการทดสอบแบบอัตโนมัติแล้ว ก็ให้ทำการ run ทุกครั้งแบบอัตโนมัติเมื่อ code เปลี่ยนแปลงกันไปเลย