जावास्क्रिप्ट में माइक्रोसर्विसेज़: मोनोलिथ से वितरित प्रणाली तक
\n\nमोनोलिथिक एप्लिकेशन से माइक्रोसर्विस आर्किटेक्चर में संक्रमण केवल एक तकनीकी रिफैक्टरिंग नहीं है, बल्कि विकास के दर्शन में बदलाव है। Node.js के साथ उन्नत स्तर पर काम करते हुए, हमें केवल कोड को मॉड्यूल में विभाजित करने की नहीं, बल्कि एक स्थिर, स्केलेबल और दोष-सहिष्णु वितरित प्रणाली बनाने की आवश्यकता का सामना करना पड़ता है। इस लेख में, हम प्रमुख आर्किटेक्चरल निर्णयों और व्यावहारिक पैटर्न का विश्लेषण करेंगे जो आपको JavaScript में production-ready माइक्रोसर्विसेज़ बनाने में मदद करेंगे।
\n\nडेवलपर के सामने मुख्य चुनौतियाँ: सेवाओं के बीच डेटा सिंक्रनाइज़ेशन, लेन-देन की अखंडता बनाए रखना, सेवा खोज और कुशल संचार। डिज़ाइन चरण में एक गलती प्रोडक्शन में अराजकता पैदा कर सकती है। आइए देखें कि इससे कैसे बचा जाए।
\n\n1. सेवाओं के बीच संचार: RabbitMQ और gRPC
\n\nमाइक्रोसर्विसेज़ की दुनिया में, संचार प्रोटोकॉल का चुनाव महत्वपूर्ण है। Node.js के लिए दो सबसे लोकप्रिय दृष्टिकोण हैं: एसिंक्रोनस मैसेज क्यू (RabbitMQ) और सिंक्रोनस हाई-परफॉर्मेंस RPC (gRPC)।
\n\nएसिंक्रोनस क्यू (RabbitMQ)
\nइवेंट-ड्रिवन आर्किटेक्चर के लिए उपयोग किया जाता है। उत्पादक सेवा उत्तर की प्रतीक्षा नहीं करती, बल्कि एक इवेंट प्रकाशित करती है। इससे युग्मन कम होता है। आइए डिलीवरी सेवा में ऑर्डर भेजने का एक उदाहरण देखें।
\n\n// सर्विस "ऑर्डर" — प्रोड्यूसर\nconst amqp = require('amqplib');\n\nasync function publishOrderCreated(order) {\n const connection = await amqp.connect('amqp://rabbitmq:5672');\n const channel = await connection.createChannel();\n const exchange = 'order.events';\n await channel.assertExchange(exchange, 'topic', { durable: true });\n\n channel.publish(exchange, 'order.created', Buffer.from(JSON.stringify(order)), {\n persistent: true\n });\n\n console.log(`[x] Sent order: ${order.id}`);\n await channel.close();\n await connection.close();\n}\n\n// ऑर्डर बनाते समय कॉल करें\npublishOrderCreated({ id: '123', userId: '456', amount: 1500 });\n\n\nउपभोक्ता सेवा (डिलीवरी) क्यू की सदस्यता लेती है:
\n\n// सर्विस "डिलीवरी" — कंज्यूमर\nconst amqp = require('amqplib');\n\nasync function consumeOrders() {\n const connection = await amqp.connect('amqp://rabbitmq:5672');\n const channel = await connection.createChannel();\n const exchange = 'order.events';\n await channel.assertExchange(exchange, 'topic', { durable: true });\n\n const q = await channel.assertQueue('', { exclusive: true });\n await channel.bindQueue(q.queue, exchange, 'order.created');\n\n channel.consume(q.queue, (msg) => {\n if (msg.content) {\n const order = JSON.parse(msg.content.toString());\n console.log(`[x] Received order: ${order.id}`);\n // डिलीवरी बनाने का तर्क\n channel.ack(msg);\n }\n });\n}\n\nconsumeOrders();\n\n\nसिंक्रोनस gRPC
\nउन परिदृश्यों के लिए जहां तत्काल प्रतिक्रिया की आवश्यकता होती है (जैसे, उपयोगकर्ता की शेष राशि की जाँच), gRPC HTTP/2 के माध्यम से सख्त टाइपिंग और उच्च गति प्रदान करता है। हम प्रोटो-फ़ाइल को परिभाषित करते हैं:
\n\n// user.proto\nservice UserService {\n rpc GetUserBalance (UserRequest) returns (UserResponse);\n}\n\nmessage UserRequest {\n string user_id = 1;\n}\n\nmessage UserResponse {\n double balance = 1;\n}\n\n\nNode.js पर सर्वर का कार्यान्वयन:
\n\nconst grpc = require('@grpc/grpc-js');\nconst protoLoader = require('@grpc/proto-loader');\nconst PROTO_PATH = './user.proto';\n\nconst packageDefinition = protoLoader.loadSync(PROTO_PATH, {\n keepCase: true,\n longs: String,\n enums: String,\n defaults: true,\n oneofs: true\n});\nconst userProto = grpc.loadPackageDefinition(packageDefinition).userservice;\n\nfunction getBalance(call, callback) {\n const userId = call.request.user_id;\n // डेटाबेस क्वेरी का अनुकरण\n const balance = userId === '456' ? 5000 : 0;\n callback(null, { balance });\n}\n\nconst server = new grpc.Server();\nserver.addSe