gRPC مع Go (Golang): مكتبات وأمثلة عملية
ما هو gRPC ولماذا تحتاجه في Go؟
gRPC هو إطار عمل عالي الأداء للاستدعاء عن بُعد (RPC) طورته Google. يستخدم Protocol Buffers (protobuf) لتسلسل البيانات و HTTP/2 للنقل. في نظام Go البيئي، أصبح gRPC المعيار لبناء بنية الميكروسيرفيسات بفضل:
- الأداء العالي (بروتوكول ثنائي، تعدد الإرسال عبر HTTP/2)
- الكتابة الصارمة للأنواع (كود Go مولّد)
- دعم البث (من العميل، من الخادم، وثنائي الاتجاه)
- المصادقة المدمجة وتوزيع الأحمال
في هذا المقال، سنستعرض المكتبات الأساسية والأدوات، ونكتب مثالًا كاملًا لخادم وعميل بلغة Golang.
المكتبات والأدوات المطلوبة
للعمل مع gRPC في Go، ستحتاج إلى:
google.golang.org/grpc— المكتبة الأساسية لـ gRPC في Gogoogle.golang.org/protobuf— للتعامل مع Protocol Buffersprotoc— مترجم ملفات .protoprotoc-gen-go— إضافة لتوليد كود Go من .protoprotoc-gen-go-grpc— إضافة لتوليد كود الخادم/العميل لـ gRPC
تثبيت الأدوات
# تثبيت protoc (Linux/macOS)
sudo apt install protobuf-compiler # أو brew install protobuf
# تثبيت إضافات Go
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
# التحقق من التثبيت
protoc --version
protoc-gen-go --version
إنشاء ملف .proto
لنبدأ بتعريف الخدمة والرسائل في ملف hello.proto:
syntax = "proto3";
package hello;
option go_package = "github.com/youruser/grpc-example/hello";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
rpc SayHelloStream (HelloRequest) returns (stream HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
توليد كود Go
protoc --go_out=. --go-grpc_out=. hello.proto
بعد التنفيذ، سيظهر ملفان:
hello.pb.go— هياكل الرسائلhello_grpc.pb.go— واجهات الخادم والعميل
تنفيذ خادم gRPC في Go
لننشئ ملف server.go:
package main
import (
"context"
"log"
"net"
"google.golang.org/grpc"
pb "github.com/youruser/grpc-example/hello"
)
type server struct {
pb.UnimplementedGreeterServer
}
func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("تم الاستلام: %v", req.GetName())
return &pb.HelloReply{Message: "مرحبًا، " + req.GetName()}, nil
}
func (s *server) SayHelloStream(req *pb.HelloRequest, stream pb.Greeter_SayHelloStreamServer) error {
for i := 0; i < 5; i++ {
if err := stream.Send(&pb.HelloReply{
Message: "مرحبًا " + req.GetName() + " - " + fmt.Sprint(i),
}); err != nil {
return err
}
}
return nil
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("فشل الاستماع: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
log.Println("الخادم يستمع على المنفذ :50051")
if err := s.Serve(lis); err != nil {
log.Fatalf("فشل تشغيل الخادم: %v", err)
}
}
تنفيذ عميل gRPC في Go
لننشئ ملف client.go:
package main
import (
"context"
"log"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
pb "github.com/youruser/grpc-example/hello"
)
func main() {
conn, err := grpc.Dial("localhost:50051",
grpc.WithTransportCredential