gRPC لجافا سكريبت (Node.js): المكتبات والأمثلة
\n\ngRPC هو إطار عالي الأداء لاستدعاء الإجراءات عن بُعد (RPC)، تم تطويره بواسطة Google. يستخدم Protocol Buffers (protobuf) لتسلسل البيانات و HTTP/2 للنقل. في نظام Node.js البيئي، يتيح gRPC إنشاء خدمات مصغرة موثوقة مع كتابة صارمة، ودعم التدفق (streaming) والاتصال ثنائي الاتجاه. في هذه المقالة، سنستعرض المكتبات الرئيسية للعمل مع gRPC في جافا سكريبت (Node.js) ونحلل مثالًا عمليًا للخادم والعميل.
\n\nالمكتبات الرئيسية لـ gRPC في Node.js
\n\nللعمل مع gRPC في Node.js، يتم استخدام حزمتين رئيسيتين:
\n\n- \n
- @grpc/grpc-js — تنفيذ خالص لجافا سكريبت لـ gRPC. لا يتطلب تبعيات أصلية، ويعمل على جميع المنصات، ويدعم جميع وظائف gRPC (الاستدعاءات الأحادية، التدفق من الخادم والعميل، التدفق ثنائي الاتجاه). \n
- @grpc/proto-loader — أداة لتحميل ملفات
.protoأثناء التشغيل. تسمح بإنشاء كائنات جافا سكريبت ديناميكيًا من تعريفات Protobuf. \n
لتجميع ملفات .proto إلى وحدات ثابتة، يمكن استخدام grpc-tools (جزء من grpc-tools)، ولكن في المشاريع الحديثة، يُستخدم التحميل الديناميكي عبر @grpc/proto-loader بشكل أكثر شيوعًا.
تثبيت التبعيات
\n\nnpm install @grpc/grpc-js @grpc/proto-loader\n\nمثال: تعريف ملف Proto
\n\nلنقم بإنشاء ملف helloworld.proto مع خدمة بسيطة:
syntax = "proto3";\n\npackage helloworld;\n\nservice Greeter {\n rpc SayHello (HelloRequest) returns (HelloReply) {}\n}\n\nmessage HelloRequest {\n string name = 1;\n}\n\nmessage HelloReply {\n string message = 1;\n}\n\nجزء الخادم (Node.js)
\n\nلنقم بإنشاء ملف server.js:
const grpc = require('@grpc/grpc-js');\nconst protoLoader = require('@grpc/proto-loader');\nconst path = require('path');\n\nconst PROTO_PATH = path.join(__dirname, 'helloworld.proto');\n\nconst packageDefinition = protoLoader.loadSync(PROTO_PATH, {\n keepCase: true,\n longs: String,\n enums: String,\n defaults: true,\n oneofs: true\n});\n\nconst helloProto = grpc.loadPackageDefinition(packageDefinition).helloworld;\n\nfunction sayHello(call, callback) {\n const name = call.request.name || 'ضيف';\n callback(null, { message: `مرحبًا، ${name}!` });\n}\n\nfunction main() {\n const server = new grpc.Server();\n server.addService(helloProto.Greeter.service, { sayHello: sayHello });\n server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => {\n console.log('خادم gRPC يعمل على المنفذ 50051');\n server.start();\n });\n}\n\nmain();\n\nجزء العميل (Node.js)
\n\nلنقم بإنشاء ملف client.js:
const grpc = require('@grpc/grpc-js');\nconst protoLoader = require('@grpc/proto-loader');\nconst path = require('path');\n\nconst PROTO_PATH = path.join(__dirname, 'helloworld.proto');\n\nconst packageDefinition = protoLoader.loadSync(PROTO_PATH, {\n keepCase: true,\n longs: String,\n enums: String,\n defaults: true,\n oneofs: true\n});\n\nconst helloProto = grpc.loadPackageDefinition(packageDefinition).helloworld;\n\nfunction main() {\n const client = new helloProto.Greeter('localhost:50051',\n grpc.credentials.createInsecure());\n\n const userName = process.argv[2] || 'العالم';\n\n client.sayHello({ name: userName }, (error, response) => {\n if (error) {\n console.error('خطأ:', error.message);\n return;\n }\n console.log('رد الخادم:', response.message);\n });\n}\n\nmain();\n\nالتشغيل والاختبار
\n\nقم بتشغيل الخادم في محطة طرفية واحدة:
\n\nnode server.js\n\nفي محطة طرفية أخرى، قم بتشغيل العميل:
\n\nnode client.js إيفان\n\nيجب