كيفية إنشاء خدمة microservice بسيطة على Golang و gRPC وحاوياتها باستخدام Docker

مرحبا يا هبر! أقدم إليكم ترجمة المقال "Go، gRPC and Docker" من إعداد Mat Evans.

هناك العديد من المقالات حول مشاركة Go و Docker. من السهل جدًا إنشاء حاويات يمكنها التفاعل مع العملاء وفيما بينها. فيما يلي مثال صغير لكيفية القيام بذلك على المستوى الأساسي.

ماذا نخلق؟


سننشئ عميلًا وخادمًا بسيطًا للغاية ، ونتفاعل مع بعضنا البعض باستخدام gRPC . سيكون الخادم موجودًا داخل حاوية Docker حتى يمكن نشره بسهولة.

لنفترض أننا بحاجة إلى خدمة تتلقى سلسلة من عميل وترجع سلسلة بترتيب أحرف عكسي. على سبيل المثال ، أرسل "قطة" واحصل على "حالي" كرد.

.proto ملف


يصف ملف .proto ما هي العمليات التي ستنفذها خدمتنا والبيانات التي سيتم تبادلها. إنشاء مجلد proto في المشروع ، وملف revers.proto فيه

syntax = "proto3"; package reverse; service Reverse { rpc Do(Request) returns (Response) {} } message Request { string message = 1; } message Response { string message = 1; } 

يتم تمييز الوظيفة التي يتم استدعاءها عن بعد على الخادم وإرجاع البيانات إلى العميل كـ rpc . يتم وضع علامة على هياكل البيانات المستخدمة لتبادل المعلومات بين العقد المتفاعلة كرسالة . يجب تعيين رقم تسلسل لكل حقل رسالة. في هذه الحالة ، لدينا وظيفة يتلقى طلب الرسائل من العميل وإرجاع رسائل الاستجابة .
بمجرد إنشاء ملف .proto ، من الضروري الحصول على ملف .go الخاص بخدمتنا . للقيام بذلك ، قم بتشغيل أمر وحدة التحكم التالية في مجلد proto :

 $ protoc -I . reverse.proto --go_out=plugins=grpc:. 

بالطبع ، تحتاج أولاً إلى إنشاء gRPC .
سيؤدي تنفيذ الأمر أعلاه إلى إنشاء ملف .go جديد يحتوي على طرق لإنشاء العميل والخادم والرسائل التي يتبادلونها. إذا اتصلنا بـ godoc ، فسنرى ما يلي:

 $ godoc . PACKAGE DOCUMENTATION package reverse import "." Package reverse is a generated protocol buffer package. It is generated from these files: reverse.proto It has these top-level messages: Request Response .... 

زبون


سيكون من الرائع لو عمل العميل مثل هذا:

 reverse "this is a test" tset a si siht 

إليك الرمز الذي ينشئ عميل gRPC باستخدام هياكل البيانات التي تم إنشاؤها من ملف .proto :

 package main import ( "context" "fmt" "os" pb "github.com/matzhouse/go-grpc/proto" "google.golang.org/grpc" "google.golang.org/grpc/grpclog" ) func main() { opts := []grpc.DialOption{ grpc.WithInsecure(), } args := os.Args conn, err := grpc.Dial("127.0.0.1:5300", opts...) if err != nil { grpclog.Fatalf("fail to dial: %v", err) } defer conn.Close() client := pb.NewReverseClient(conn) request := &pb.Request{ Message: args[1], } response, err := client.Do(context.Background(), request) if err != nil { grpclog.Fatalf("fail to dial: %v", err) } fmt.Println(response.Message) } 


الخادم


سيستخدم الخادم نفس ملف .go الذي تم إنشاؤه. ومع ذلك ، فإنه يحدد واجهة الخادم فقط ، ولكن يتعين علينا تنفيذ المنطق بمفردنا:

 package main import ( "net" pb "github.com/matzhouse/go-grpc/proto" "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/grpclog" ) func main() { listener, err := net.Listen("tcp", ":5300") if err != nil { grpclog.Fatalf("failed to listen: %v", err) } opts := []grpc.ServerOption{} grpcServer := grpc.NewServer(opts...) pb.RegisterReverseServer(grpcServer, &server{}) grpcServer.Serve(listener) } type server struct{} func (s *server) Do(c context.Context, request *pb.Request) (response *pb.Response, err error) { n := 0 // reate an array of runes to safely reverse a string. rune := make([]rune, len(request.Message)) for _, r := range request.Message { rune[n] = r n++ } // Reverse using runes. rune = rune[0:n] for i := 0; i < n/2; i++ { rune[i], rune[n-1-i] = rune[n-1-i], rune[i] } output := string(rune) response = &pb.Response{ Message: output, } return response, nil } 


عامل ميناء


أفترض أنك تعرف ما هو عامل الميناء وما هو عليه. هنا لدينا Dockerfile :

 FROM golang:1.12 ADD . /go/src/github.com/matzhouse/go-grpc/server RUN go install github.com/matzhouse/go-grpc/server ENTRYPOINT ["/go/bin/server"] EXPOSE 5300 

تتم كتابة رمز التجميع لصورة Docker هنا. سنقوم بتحليلها سطرا سطرا.

 FROM golang:1.12 

يعني هذا الأمر أننا نريد إنشاء صورة لتطبيقنا على أساس صورة تم إنشاؤها مسبقًا ، وهي golang . هذه صورة Docker مع بيئة تم تكوينها بالفعل لإنشاء وتشغيل البرامج المكتوبة في Go .

 ADD . /go/src/github.com/matzhouse/go-grpc/server 

يقوم هذا الأمر بنسخ الكود المصدري لتطبيقنا في حاوية GOPATH / src .

 RUN go install github.com/matzhouse/go-grpc/server 

يجمع هذا الأمر طلبنا من المصادر المنسوخة إلى الحاوية ويثبته في مجلد حاوية GOPATH / bin .

 ENTRYPOINT ["/go/bin/server"] 

يقوم هذا الأمر بتكوين الحاوية لتعمل كبرنامج قابل للتنفيذ. في ذلك ، نشير إلى المسار إلى التطبيق القابل للتنفيذ ، وإذا لزم الأمر ، وسيطات سطر الأوامر.

 EXPOSE 5300 

باستخدام هذا الأمر ، نقوم بإخبار الحاوية بالمنافذ التي يجب الوصول إليها من الخارج.

بداية الخادم


نحن بحاجة إلى تشغيل الحاوية من خلال تطبيق الخادم الخاص بنا.
تحتاج أولاً إلى بناء الصورة بناءً على إرشادات Dockerfile :

 $ sudo docker build -t matzhouse/grpc-server . Sending build context to Docker daemon 31.76 MB Step 1/5 : FROM golang ---> a0c61f0b0796 Step 2/5 : ADD . /go/src/github.com/matzhouse/go-grpc ---> 9508be6501c1 Removing intermediate container 94dc6e3a9a20 Step 3/5 : RUN go install github.com/matzhouse/go-grpc/server ---> Running in f3e0b993a420 ---> f7a0370b7f7d Removing intermediate container f3e0b993a420 Step 4/5 : ENTRYPOINT /go/bin/server ---> Running in 9c9619e45df4 ---> fb34dfe1c0ea Removing intermediate container 9c9619e45df4 Step 5/5 : EXPOSE 5300 ---> Running in 0403390af135 ---> 008e09b9aebd Removing intermediate container 0403390af135 Successfully built 008e09b9aebd 

الآن يمكننا أن نرى هذه الصورة في القائمة:

 $ docker images REPOSITORY TAG IMAGE ID ... matzhouse/grpc-server latest 008e09b9aebd ... 

! ممتاز لدينا صورة لتطبيق الخادم الخاص بنا ، حيث يمكنك تشغيل الحاوية الخاصة به باستخدام الأمر التالي:

 $ docker run -it -p 5300:5300 matzhouse/grpc-server 

في هذه الحالة ، ما يسمى ميناء الشحن . لاحظ أننا نحتاج إلى كل من بيان EXPOSE ووسيطة -p .

إطلاق العميل


لن يوفر تطبيق الحاوية للعميل مزايا كبيرة ، لذلك دعونا نبدأها بالطريقة المعتادة:

 $ go build -o reverse $ ./reverse "this is a test" tset a si siht 

شكرا للقراءة!

Source: https://habr.com/ru/post/ar461279/


All Articles