Hato Hub’s Infra in 2022

Pongsakorn Teeraparpwong
Hato Hub
Published in
3 min readNov 24, 2022

จากบทความเดิมเรื่องการย้ายไปใช้ Golang และ Serverless ของ Indy Dish ตอนปี 2019 ปัจจุบันเราได้เปลี่ยน product ใหม่เป็น Hato Hub เรียบร้อยแล้ว โดยเรานำเทคโนโลยีตอนทำ Indy Dish มาต่อยอดใหม่ โดยมี goal เพื่อช่วยให้ร้านอาหารสามารถมี delivery channel ของตัวเองได้ผ่าน LINE OA และยังมีบริการอื่นๆ เช่น Loyalty/CRM และ Digital Dine-in เพื่อสร้าง Digital Omnichannel ให้กับร้านอาหารอย่างครบวงจร

ในบทความนี้อยากจะมา update ว่าตอนนี้เราใช้ AWS Services อะไรเป็น Infra บ้าง เนื่องจาก tech team เราค่อนข้าง lean เราจึงพยายามทำ architecture ให้ simple ที่สุด และเลือกใช้ serverless และ fully managed service ทั้งหมดเพื่อลดงาน operation และ maintenance ทำให้ dev สามารถ focus ในการพัฒนา product ได้เต็มที่

Frontend

ReactJS on S3 and CloudFront

React hosted on S3 served through CloudFront

ในส่วนของ Frontend เราใช้ React เป็นหลัก ทั้งส่วน customer-facing ที่เป็น LIFF App ใน LINE OA และส่วนหลังบ้านที่เป็น merchant app / website โดยตัว mobile app เราใช้ Ionic มา wrap ReactJS เป็น Android App อีกที

ReactJS ตอนนี้เป็น static website ทั้งหมดเลยสามารถ host ไว้บน S3 และ serve ผ่าน CloudFront ได้ ข้อดีคือไม่ต้องมีการ manage server และสามารถ scale ได้ด้วยตัวเอง โดยในอนาคตหากเราต้องการเพิ่มความ Dynamic สามารถใช้ Lambda@Edge ของ CloudFront ได้ด้วย

API

Golang, Lambda, API Gateway, PostgresQL RDS

API architecture with API Gateway, Lambda and RDS

ต่อยอดจาก Indy Dish เดิม ในส่วนของ API เรายังใช้ Golang และ AWS Lambda ซึ่งเป็น serverless อยู่ ใช้งานได้ดีประทับใจ ทั้งเรื่องราคาที่ถูกสุดๆ สามารถ scale ได้อัตโนมัติ ไม่ต้องกลัว server ล่ม (ถ้า database ไม่ล่มไปก่อน 555) รวมถึง Golang นั้นมี cold start ที่สั้นมาก จึงเหมาะกับ Lambda จริงๆ โดยตาม architecture ของ Lambda ถ้าต้องการรับ HTTP traffic จากข้างนอกก็ต้องผ่าน API Gateway ก่อน

ถึง Lambda จะเหมาะกับการทำ microservice แต่เราไม่ได้แบ่ง service ย่อยๆ ขนาดนั้นเพราะยิ่งแยก Lambda function เยอะ ยิ่งทำให้ maintain ยาก เราเลยแยก Lambda ตาม client ของ API เป็นหลัก เช่น API สำหรับ Customer-facing LIFF App และ API สำหรับ Merchant App เป็นต้น โดยทั้งหมดอยู่ใน codebase เดียวกัน แต่ใช้วิธี compile แยก main กันเพื่อเอาไป deploy บน Lambda คนละตัวกัน

ทุกๆ API จะใช้ Database ตัวเดียวกันซึ่งคือ RDS PostgresQL โดยมี Read replica 2–3 ตัวเพื่อรับโหลด read ในบางส่วนรวมถึง Analytics ด้วย นอกจากนี้ยังมีใช้ DynamoDB เป็น cache ในบางส่วน ถึงแม้ว่าอาจจะไม่ได้เร็วเท่า Redis/Memcached แต่ก็ง่ายที่ไม่ต้องมา maintain server อีกตัว

Async job

StepFunctions, Golang and Lambda

Example Step Functions Workflow for checking payment status with Lambda

Hato Hub มี asynchronous job อยู่มากพอสมควร ส่วนนึงคือพวก cron ที่ run ตาม schedule และอีกส่วนคือถูก trigger โดย event บางอย่าง เช่นหลังลูกค้าสั่งอาหารก็จะต้องคอย check และเปลี่ยนสถานะของ order นั้นตามเวลาและเงื่อนไขที่กำหนด เป็นต้น

AWS Service ที่เราใช้ในการ orchestrate workflow พวกนี้คือ StepFunctions ที่ทำงานร่วมกับ Lambda ได้อย่างดีและง่ายมากๆ โดยเราจะ define workflow ใน YML config file ออกมา State machine โดยแต่ละ state สามารถไปผูกไว้กับ Lambda ได้ เราสามารถ trigger execution ของ workflow ได้หลายวิธีทั้งจาก cron schedule (CloudWatch event) หรือจาก API

CICD

CloudFormation, CodePipeline, CodeBuild, CodeDeploy

CodePipeline stages of our API

สำหรับ API และ Async Job ที่เป็น Golang และ Lambda นั้นเราใช้ CloudFormation (Infrastructure as Code) ในการ provision และ manage resource ทั้งหมด โดยใช้ framework ของ AWS เองที่ชื่อ Serverless Application Model โดย framework ตัวนี้ทำให้ define พวก Lambda และ API ค่อนข้างง่ายกว่าเขียน CloudFormation ปกติ

ข้อดีของการใช้ Infrastructure as Code นั้นมีเยอะมาก อย่างแรกคือสามารถลดข้อผิดพลาดในการ manage resource จำนวนมากๆเช่น Lambda ได้ (ไปกดใน AWS console เองไม่ work แน่ๆ) สามารถเห็น overview ของ resource ทั้งหมดใน config file เดียวและสามารถทำ code review และมี revision ได้เหมือน code ทั่วไปผ่าน git

ตัว CloudFormation นี้เอาใส่เป็น step ในการ deploy ของ CodePipeline ซึ่งเป็น CICD service ของ AWS ได้ การทำ CICD นั้นสำคัญมากๆเพราะช่วย automate process ของการ test และ deploy ทำให้ release feature ไปหาลูกค้าได้ง่ายและเร็วขึ้น ลด operation ของ dev เลยเป็นสิ่งที่ต้องทำอย่างแรกๆเลย โดย service อย่าง CodeBuild สามารถเอาไปผูกกับ GitHub Pull Request เพื่อ run test อัตโนมัติก่อน merge ได้ด้วย

Analytics/Data Warehouse

Redshift, PowerBI

ส่วนสุดท้ายที่สำคัญมากๆคือการทำ Analytics และ Data Warehouse ก่อนหน้านี้เราทำ dashboard ให้ลูกค้าผ่าน Data Studio ซึ่งต่อกับ Read Replica ของ RDS ตรงๆ แต่ทั้ง Data Studio และ Read Replica มีข้อจำกัดค่อนข้างมาก โดยเฉพาะถ้าเราต้องการ pre-process data ก่อนนำไปแสดงผล ตอนนี้เลยเริ่มย้ายมาใช้ Redshift และ PowerBI แทน ซึ่งดีมากๆ ในอนาคตสามารถเอา data ไปทำ build ML model แบบอัตโนมัติได้ง่ายๆด้วย

ไว้คราวหน้าจะเขียนถึง architecture ส่วนนี้ รวมถึงการทำ ETL แบบง่ายๆ ด้วย Redshift

--

--

Pongsakorn Teeraparpwong
Hato Hub

CTO & Co-founder @ Indie Dish • AWS Certified • TEDx Volunteer || Ex-SDE @ Amazon.com • Chula Intania 87 • BCC 150