مقدمة في هندسة الخدمات الصغيرة
الجزء 1 من أصل 10
تعديل مقالات إيوان فالنتاين.
هذه سلسلة من عشرة أجزاء ، سأحاول أن أكتب عن بناء الخدمات الصغيرة على Golang مرة في الشهر. سأستخدم protobuf و gRPC كبروتوكول النقل الرئيسي.
المكدس الذي استخدمته: golang و mongodb و grpc و docker و Google Cloud و Kubernetes و NATS و CircleCI و Terraform و go-micro.
لماذا أحتاج هذا؟ حيث استغرق الأمر مني وقتًا طويلاً لفهمها وحل المشكلات المتراكمة. وأردت أيضًا أن أشارككم ما تعلمته عن إنشاء واختبار ونشر خدمات صغيرة على Go وتقنيات جديدة أخرى.
في هذا الجزء ، أريد أن أعرض المفاهيم والتقنيات الأساسية لبناء الخدمات الصغيرة. دعنا نكتب تنفيذ بسيط. سيحتوي المشروع على الكيانات التالية:
- البضائع
- جرد
- المحاكمة
- المستخدمين
- الأدوار
- المصادقة

للمضي قدمًا ، تحتاج إلى تثبيت Golang والمكتبات الضرورية ، بالإضافة إلى إنشاء مستودع git.
النظرية
ما هي هندسة الخدمات الصغيرة؟
تقوم الخدمات الصغيرة بعزل وظيفة منفصلة في خدمة ، مكتفية ذاتيا من حيث الوظيفة التي تؤديها هذه الخدمة. للتوافق مع الخدمات الأخرى ، لديه واجهة معروفة ومحددة مسبقًا.
تتواصل الخدمات الصغيرة مع بعضها البعض باستخدام الرسائل المرسلة من خلال وسيط رسائل وسيط.

بفضل بنية الخدمات الصغيرة ، لا يمكن تحجيم التطبيق بالكامل ، ولكن في أجزاء. على سبيل المثال ، إذا كانت خدمة التخويل "تشنجات" أكثر من غيرها ، فيمكننا زيادة عدد الحالات. يتماشى هذا المفهوم مع مفاهيم الحوسبة السحابية والحاويات بشكل عام.
لماذا جولانج
الخدمات الدقيقة مدعومة بجميع اللغات تقريبًا ، بعد كل شيء ، الخدمات الصغيرة هي مفهوم ، وليست بنية أو أداة محددة. ومع ذلك ، فإن بعض اللغات أكثر ملاءمة ، بالإضافة إلى ذلك ، لديها دعم أفضل للخدمات الدقيقة من غيرها. لغة واحدة مع دعم كبير هي Golang.
تلبية protobuf / gRPC
كما ذكرنا سابقًا ، تنقسم الخدمات الدقيقة إلى قواعد تعليمات برمجية منفصلة ، واحدة من المشكلات المهمة المرتبطة بالخدمات الدقيقة هي الاتصال. إذا كان لديك متراصة ، فيمكنك ببساطة الاتصال بالرمز مباشرة من مكان آخر في برنامجك.
لحل مشكلة الاتصال ، يمكننا استخدام نهج REST التقليدي ونقل البيانات بتنسيق JSON أو XML عبر HTTP. لكن هذا النهج له عيوبه ، على سبيل المثال ، أنه قبل إرسال رسالة ، عليك ترميز بياناتك ، وفك تشفيرها مرة أخرى على الجانب المتلقي. وهذا عام ويزيد من تعقيد الشفرة.
هناك حل! هذا هو بروتوكول gRPC - بروتوكول ثنائي الوزن وخفيف الوزن يلغي إرسال رؤوس HTTP ، وهذا سيوفر لنا بعض وحدات البايت. يتضمن بروتوكول HTTP2 المستقبلي أيضًا استخدام البيانات الثنائية ، التي تتحدث مرة أخرى لصالح gRPC. HTTP2 يسمح بالاتصال ثنائي الاتجاه ، وهو رائع!
يسمح لك GRPC أيضًا بتحديد الواجهة لخدمتك بتنسيق سهل - وهذا هو> protobuf .
تدرب
قم بإنشاء الملف /project/consigment.proto.
وثائق protobuf الرسمية
consigment.proto//consigment.proto syntax = "proto3"; package go.micro.srv.consignment; service ShippingService { rpc CreateConsignment(Consignment) returns (Response) {} } message Consignment { string id = 1; string description = 2; int32 weight = 3; repeated Container containers = 4; string vessel_id = 5; } message Container { string id = 1; string customer_id = 2; string origin = 3; string user_id = 4; } message Response { bool created = 1; Consignment consignment = 2; }
هذا مثال بسيط يحتوي على الخدمة التي تريد تقديمها لخدمات أخرى: خدمة ShippingService ، ثم سنحدد رسائلنا. Protobuf هو بروتوكول مكتوب بشكل ثابت ، ويمكننا إنشاء أنواع مخصصة (مماثلة للهياكل في golang). هنا تتداخل الحاوية في الدفعة.
قم بتثبيت المكتبات والمترجم وتجميع بروتوكولنا:
$ go get -u google.golang.org/grpc $ go get -u github.com/golang/protobuf/protoc-gen-go $ sudo apt install protobuf-compiler $ mkdir consignment && cd consignment $ protoc -I=. --go_out=plugins=grpc:. consignment.proto
يجب أن يكون الإخراج ملفًا:
شحنة. pb.go
إذا ، حدث خطأ ما. انتبه إلى الحجج - أنا هو المسار الذي يبحث فيه المترجم عن الملفات ، --go_out حيث سيتم إنشاء ملف جديد. هناك دائما مساعدة
$ protoc -h
هذا هو الرمز الذي يتم إنشاؤه تلقائيًا بواسطة مكتبات gRPC / protobuf بحيث يمكنك ربط تعريف protobuf الخاص بك مع التعليمات البرمجية الخاصة بك.
سنكتب main.go
main.go package seaport import ( "log" "net"
يرجى قراءة التعليقات المتبقية في التعليمات البرمجية بعناية. على ما يبدو ، نحن هنا ننشئ منطق التنفيذ الذي تتفاعل فيه أساليب gRPC الخاصة بنا باستخدام التنسيقات التي تم إنشاؤها ، وإنشاء خادم gRPC جديد على المنفذ 50051. الآن ستعيش خدمة gRPC هناك.
يمكنك تشغيل هذا باستخدام $ go run main.go ، لكنك لن ترى أي شيء ولن تتمكن من استخدامه ... لذا ، لننشئ عميلًا لرؤيته عمليًا .
لنقم بإنشاء واجهة سطر أوامر تأخذ ملف JSON وتتفاعل مع خدمة gRPC.
في الدليل الجذر ، قم بإنشاء دليل فرعي جديد لـ $ mkdir consignment-cli . في هذا الدليل ، قم بإنشاء ملف cli.go بالمحتويات التالية:
cli.go package main import ( "encoding/json" "io/ioutil" "log" "os" pbf "seaport/consignment" "golang.org/x/net/context" "google.golang.org/grpc" ) const ( address = "localhost:50051" defaultFilename = "consignment.json" )
الآن قم بإنشاء مجموعة (consignment-cli / consignment.json):
{ "description": " ", "weight": 100, "containers": [ { "customer_id": "_001", "user_id": "_001", "origin": " " } ], "vessel_id": "_001" }
الآن ، إذا قمت بتشغيل $ go ، قم بتشغيل main.go من حزمة الميناء ، ثم قمت بتشغيل $ go run cli.go في لوحة طرفية منفصلة. يجب أن تشاهد الرسالة "Created: true".
ولكن كيف يمكننا التحقق مما تم إنشاؤه بالضبط؟ دعنا نقوم بتحديث خدمتنا باستخدام طريقة GetConsignments حتى نتمكن من عرض جميع الدفعات التي تم إنشاؤها.
لذا ، قمنا هنا بإنشاء طريقة جديدة على خدمتنا تسمى GetConsignments ، وقمنا أيضًا بإنشاء GetRequest جديدة ، والتي لا تحتوي على أي شيء حتى الآن. أضفنا أيضًا حقل دفعات مرسلة إلى رسالة الرد الخاصة بنا. ستلاحظ أن النوع هنا يحتوي على الكلمة الرئيسية المتكررة حتى النوع. هذا ، كما قد تكون خمنت على الأرجح ، يعني ببساطة معالجة هذا المجال كمجموعة من هذه الأنواع.
لا تتسرع في تشغيل البرنامج ، حيث يعتمد تنفيذ أساليبنا gRPC على مطابقة الواجهة التي تم إنشاؤها بواسطة مكتبة protobuf ، نحتاج إلى التأكد من تطابق التنفيذ مع تعريفنا الأولي.
لقد قمنا هنا بتضمين طريقة GetConsignments الجديدة الخاصة بنا ، وتحديث المستودع والواجهة الخاصة بنا ، والتي تم إنشاؤها على التوالي في تعريف الملف. إذا قمت بتشغيل $ go run main.go مرة أخرى ، يجب أن يعمل البرنامج مرة أخرى.
دعنا نقوم بتحديث أداة cli الخاصة بنا لتشمل القدرة على استدعاء هذه الطريقة ومن الممكن سرد أطرافنا:
cli.go package main import ( "encoding/json" "io/ioutil" "log" "os" pbf "seaport/consignment" "golang.org/x/net/context" "google.golang.org/grpc" ) const ( address = "localhost:50051" defaultFilename = "consignment.json" )
أضف الكود أعلاه إلى cli.go وقم بتشغيل $ go run cli.go مرة أخرى . سيقوم العميل بتشغيل CreateConsignment ثم استدعاء GetConsignments. ويجب أن ترى أنه في قائمة الإجابات يحتوي على تركيبة الحزب.
وبالتالي ، لدينا أول خدمة صغيرة وعميل يتفاعل معها باستخدام protobuf و gRPC.
سيتضمن الجزء التالي من هذه السلسلة تكامل go-micro ، الذي يعد أساسًا قويًا لإنشاء الخدمات الدقيقة القائمة على gRPC. سننشئ أيضًا خدمتنا الثانية. ضع في اعتبارك عمل خدماتنا في حاويات Docker ، في الجزء التالي من سلسلة المقالات هذه.