มาทำ HTTP/Rest Endpoint ไปยัง gRPC service ด้วย Go กัน
มาทำความเข้าใจในส่วน gRPC กันก่อน
เนื่องจาก gRPC service นั้นจะทำการสื่อสารบน HTTP 2 แต่ ทาง API Client นั้นจะเป็น HTTP 1 เท่านั้น ส่ิงที่จะทำให้ฝั่ง API Client กับ gRPC Service สื่อสารกันได้ ก็คือตัวกลาง หรือในบทความนี้จะใช้ grpc-gateway ในการทำ proxy ให้ฝั่ง API Client สามารถสื่อสารมายัง gRPC service ได้
- โครงสร้างการทำงานเป็นดังนี้
สามารถอ่าน documentation ได้ที่ grpc-gateway
สามารถดูโค้ดตัวอย่างก่อนเร่ิมต้นได้ที่นี้
ก่อนที่เราจะเริ่มต้น เราจำเป็นต้องสร้างโครงสร้างโครงการ Go
โดยเราจะใช้ template for Go project:
มาลุยกันเลย
ขั้นแรกให้สร้างโปรเจคเราไว้ที่ root project
mkdir patstore-service
cd patstore-service
go mod init github.com/<you>/patstore-service
สร้างโฟลเดอร์ไว้เก็บ API definition:
mkdir -p api/proto/v1
โดยที่ v1 คือเวอร์ชัน API
API versioning: เป็นวิธีปฏิบัติที่ดีในการค้นหา API เวอร์ชันหลักในโฟลเดอร์ต่างๆ
ต่อไปสร้าง petstore-service.proto ไว้ใน api\proto\v1 :
สามารถไปศึกษาสเปคของภาษา proto เพิ่มเติมได้ที่ :
การที่เราจะ Compile Proto เราจำเป็นต้องติดตั้งเครื่องมือที่จำเป็นและเพิ่มแพ็คเกจ
- สามารถไปดาวน์โหลดไลบรารี่ของตัวคอมไพเลอร์ได้ที่ :
- ติดตั้งไว้ที่ “bin” ของ env ของเครื่อง
- สร้างโฟลเดอร์ที่ชื่อว่า trird_party
- เลือกมาจาก “bin” ที่เราติดตั้งก่อนหน้านี้แล้ว copy เฉพาะตัวที่ต้องการใช้งาน
- เราจำเป็นต้องติดตั้ง Plugin ของภาษา Go เพื่อใช้งาน protoc compiler:
go get -u github.com/golang/protobuf/protoc-gen-go
- สร้าง protoc-gen.cmd (protoc-gen.sh for MacOS/Linux) ไว้ในโฟลเดอร์ “third_party” :
- สร้าง forder เพื่อรองรับการ gen-protoc
mkdir -p api/swagger
mkdir -p pkg/api/v1
- แล้วลอง run proto compiler ด้วยคำสั่งนี้:
./third_party/protoc-gen.sh
ต่อไปจะเป็นการพัฒนาแพคแกจของเรากัน
- เริ่มจากการสร้างโฟลเดอร์ pkg/service เพื่อสร้าง
mkdir -p pkg/service && cd pkg/service
- แล้วก็ลงมือเขียนโค้ดตามนี้ครับ:
- โดยในแพคแกจนี้จะใช้ database ของ firestore ลองไปศึกษาเพิ่มเติมได้ที่:
- ต่อไปนี้เราจะมาสร้างโปรโตคอลเพื่อให้ฝั่ง client และ server สื่อสารกันได้ สร้างไว้อยู่ภายใต้ pkg
- ก่อนอื่นสร้างโฟลเดอร์ config ไว้สำหรับใส่ค่า config ทั้งหมดของ pkg ไว้ที่ภายใต้ petstore-service
mkdir config
cd config
- ทำการสร้างไฟล์ config.go
- และทำการสร้าง local-config.yaml เพื่อจะใส่ key กับ value ที่เราต้องการเปลี่ยนค่าคอนฟิกได้ ในส่วนนี้จะเขียนให้ดูแค่ local-config.ymal แต่ถ้ามี env อื่นก็สร้างสามารถสร้างไฟล์เพิ่มได้ตาม env ที่ต้องการ
- เรามาเริ่มทำฝั่ง gRPC กันก่อน
mkdir -p protocol/grpc && cd protocol/grpc
ทำการสร้างไฟล์ server.go
- ต่อไปก็มาทำฝั่ง REST ต่อ
cd ..
mkdir rest && cd rest
แล้วก็สร้างไฟล์ที่ชื่อว่า server.go เหมือนฝั่ง gRPC เลยแต่โค้ดจะต่างกันเพราะไฟล์นี้เราจะใช้ให้ HTTP คุยกับทาง gRPC ได้
เพียงเท่านี้เราก็จะได้ Protocol ไว้ให้ฝั่ง HTTP คุยกับ gRPC ได้แล้ว
- ต่อมาเราก็มาสร้างโฟลเดอร์ cmd จะอยู่ภายใต้ pkg
mkdir cmd && cd cmd
- แล้วเราก็สร้างไฟล์ที่ชื่อว่า server.go เพื่อทำการ run โปรโตคอลทั้งสองฝั่งของ server ที่เราสร้างไว้ก่อนก่อนโดยเขียนดังนี้
- สุดท้ายเรามาสร้างไฟล์สำหรับการ run ทั้งหมดของ pkg ไว้ที่ภายใต้ petstore-service
mkdir -p cmd/server && cd cmd/server
ลองไปทดสอบกันเลย 🤹♂️
go run cmd/server/main.go -env=local
ทดสอบด้วยการยิง API ด้วย Postman
สรุป
ทำไมเราถึงมาใช้ gRPC มาดูข้อดีกันครับ
- gRPC ใช้ “Protobuf”, “HTTP/2” และ “Google” พัฒนา
- รองรับทั้งการเขียนแบบ synchronous และ asynchronous
- ทำงานได้หลาย languages และ platforms
- Bi-directional streaming และ integrated auth
- สามารถติดต่อกับ Services ต่าง ๆ ได้อย่างมีประสิทธิภาพ ไม่ว่าจะติดต่อกับ devices, mobile applications รวมถึง browsers ไปสู่ backend service
- รองรับการ Scale, load balancing, tracing, health check หรือ จะเป็นการ authentication ก็ได้
จะดีแค่ไหนถ้า Service ของเราสามารถรับการสื่อสารได้ทั้งฝั่ง API Client และ
gRPC Service ทำให้งานเรามีประสิทธิภาพมากขึ้นในสื่อสารโดยไม่ต้องเลือกให้ Protocol สื่อสารทางใดทางหนึ่ง