Node.js बैकएंड विकास बूटकैंप · पाठ

Protobuf IDL से सेवाएँ और संदेश परिभाषित करना

.proto अनुबंध लिखिए और उनसे टाइप-सुरक्षित क्लाइंट व सर्वर स्टब बनाइए।

पाठ 1, कुल 4 में से13 चरण

Protobuf IDL से सेवाएँ और संदेश परिभाषित करना, CoddyKit पर Node.js बैकएंड विकास बूटकैंप का एक निःशुल्क पाठ है। यह 4 में से 1वाँ पाठ है। आप नीचे पूरा पाठ निःशुल्क पढ़ सकते हैं—फिर अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर के साथ ब्राउज़र में इसका व्यावहारिक अभ्यास कर सकते हैं। यह Node.js बैकएंड विकास बूटकैंप सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। Node.js बैकएंड विकास बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

IDL क्यों?

gRPC माइक्रोसर्विस में कॉन्ट्रैक्ट कोड से पहले आता है। आप अपने डेटा और RPC मेथड को भाषा-निरपेक्ष इंटरफ़ेस परिभाषा भाषा (IDL) में लिखते हैं, जिसे .proto कहा जाता है, और फिर उसी एक फ़ाइल से Node.js, Go, Java आदि के लिए टाइप-सुरक्षित स्टब जनरेट करते हैं।

  • एक .proto फ़ाइल क्लाइंट और सर्वर द्वारा साझा किया गया सत्य का एकमात्र स्रोत होती है।
  • Protocol Buffers (protobuf) IDL और बाइनरी वायर फ़ॉर्मैट, दोनों है।
  • आपको सीरियलाइज़ेशन कोड हाथ से लिखने की आवश्यकता नहीं होती — कंपाइलर यह काम करता है।

इस पाठ में बताया गया है कि .proto कॉन्ट्रैक्ट कैसे लिखें और उन्हें JavaScript क्लाइंट व सर्वर स्टब में कैसे बदलें।

.proto फ़ाइल की संरचना

हर आधुनिक .proto फ़ाइल की शुरुआत सिंटैक्स संस्करण और पैकेज घोषित करने से होती है। package आपके प्रतीकों के लिए नेमस्पेस बनाता है, ताकि दो सेवाएँ बिना टकराव के User परिभाषित कर सकें।

  • syntax = "proto3"; — नई सेवाओं के लिए हमेशा proto3 का उपयोग करें।
  • package — तार्किक नेमस्पेस, जो जनरेशन के बाद JS ऑब्जेक्ट पथ में बदल जाता है।
  • फ़ाइल में message (डेटा संरचनाएँ) और service (RPC मेथड) को समूहित किया जाता है।
// user.proto
syntax = "proto3";

package users.v1;

// A data shape sent over the wire
message User {
  string id = 1;
  string email = 2;
  bool active = 3;
}

मैसेज और फ़ील्ड नंबर

message टाइप वाले फ़ील्ड का रिकॉर्ड होता है। = के बाद की संख्या फ़ील्ड टैग होती है, डिफ़ॉल्ट मान नहीं। बाइनरी वायर पर protobuf हर फ़ील्ड की पहचान टैग से करता है — एक मैसेज के भीतर ये अद्वितीय होने चाहिए और डिप्लॉय होने के बाद इन्हें कभी नहीं बदलना चाहिए।

  • फ़ील्ड के नाम स्वतंत्र रूप से बदले जा सकते हैं; बैकवर्ड संगतता के लिए टैग स्थिर रहने चाहिए।
  • 1-15 टैग एक बाइट का उपयोग करते हैं, इसलिए इन्हें सबसे अधिक उपयोग होने वाले फ़ील्ड के लिए सुरक्षित रखें।
  • स्केलर प्रकार: string, bool, int32, int64, double, bytes।
message Product {
  string id = 1;          // tag 1 (1 byte on the wire)
  string name = 2;
  int32 stock = 3;
  double price = 4;
  bool discontinued = 5;
}

proto3 से JavaScript प्रकारों का मैपिंग

जब आप @grpc/proto-loader से .proto लोड करते हैं, तो हर protobuf प्रकार एक JavaScript मान में मैप हो जाता है। इस मैपिंग को जानने से रनटाइम पर होने वाले आश्चर्यों से बचा जा सकता है।

  • string, bool, int32, float, double, JS के string, boolean, number में मैप होते हैं।
  • int64 / uint64 JS में डिफ़ॉल्ट रूप से string में मैप होते हैं (संख्याएँ Number.MAX_SAFE_INTEGER से बड़ी हो सकती हैं)।
  • bytes एक Buffer बन जाता है।
  • अनसेट proto3 स्केलर अपने शून्य मान ("", 0, false) के रूप में वापस आते हैं — वायर पर वे कभी undefined नहीं होते।
// What a decoded User object looks like in Node.js
const user = {
  id: 'u_123',      // string -> string
  email: '',         // unset string -> '' (zero value)
  active: false,     // unset bool -> false
  loginCount: '0'    // int64 -> string, not number!
};

console.log(typeof user.loginCount); // 'string'

सेवा परिभाषित करना

service ब्लॉक उन RPC मेथड की सूची देता है जिन्हें क्लाइंट कॉल कर सकते हैं। हर rpc ठीक एक अनुरोध मैसेज लेता है और ठीक एक प्रतिक्रिया मैसेज लौटाता है। अनुरोध और प्रतिक्रिया को समर्पित मैसेज में लपेटने से (सीधे स्केलर भेजने के बजाय) कॉन्ट्रैक्ट तोड़े बिना बाद में फ़ील्ड जोड़ना संभव होता है।

  • परंपरा के अनुसार मेथड के नाम PascalCase में होते हैं।
  • हर मेथड के लिए हमेशा एक अनुरोध और एक प्रतिक्रिया मैसेज परिभाषित करें, भले ही उनमें से कोई एक खाली हो।
message GetUserRequest { string id = 1; }
message GetUserResponse { User user = 1; }

service UserService {
  // unary: one request -> one response
  rpc GetUser(GetUserRequest) returns (GetUserResponse);
  rpc CreateUser(CreateUserRequest) returns (User);
}

RPC के चार प्रकार

rpc घोषणा के किसी भी ओर मौजूद stream कीवर्ड स्ट्रीमिंग मॉडल को नियंत्रित करता है। यही IDL कीवर्ड तय करता है कि आपके जनरेट किए गए हैंडलर को एक मान मिलेगा या स्ट्रीम।

  • यूनरी: rpc Get(Req) returns (Res) — एक इनपुट, एक आउटपुट।
  • सर्वर स्ट्रीमिंग: returns (stream Res) — सर्वर कई मान भेजता है।
  • क्लाइंट स्ट्रीमिंग: (stream Req) — क्लाइंट कई मान अपलोड करता है।
  • द्विदिशात्मक: (stream Req) returns (stream Res)।
service OrderService {
  rpc GetOrder(GetOrderRequest) returns (Order);
  rpc ListOrders(ListOrdersRequest) returns (stream Order);
  rpc ImportOrders(stream Order) returns (ImportSummary);
  rpc LiveOrders(stream OrderEvent) returns (stream OrderEvent);
}

एनम, repeated और नेस्टेड मैसेज

स्केलर के अलावा protobuf वास्तविक दुनिया के डेटा के लिए मिश्रित संरचनाएँ भी देता है।

  • enum — मानों का सीमित सेट; पहला सदस्य अनिवार्य रूप से 0 होना चाहिए और वही डिफ़ॉल्ट होता है।
  • repeated — क्रमबद्ध सूची; यह JS Array में डिकोड होती है।
  • नेस्टेड मैसेज संरचित उप-रिकॉर्ड का मॉडल बनाते हैं।

नामों के टकराव से बचने के लिए एनम सदस्यों के आगे उपसर्ग लगाएँ, क्योंकि एनम मान बाहरी स्कोप साझा करते हैं।

enum OrderStatus {
  ORDER_STATUS_UNSPECIFIED = 0; // required zero default
  ORDER_STATUS_PENDING = 1;
  ORDER_STATUS_SHIPPED = 2;
}

message Order {
  string id = 1;
  OrderStatus status = 2;
  repeated LineItem items = 3; // -> JS Array
}

message LineItem {
  string sku = 1;
  int32 qty = 2;
}

Node.js में कॉन्ट्रैक्ट लोड करना

Node में आप @grpc/proto-loader और @grpc/grpc-js की सहायता से रनटाइम पर स्टब जनरेट करते हैं। लोडर .proto को पार्स करता है और loadPackageDefinition उसे आपके पैकेज पथ के आधार पर नेविगेट किए जा सकने वाले JS ऑब्जेक्ट में बदल देता है।

  • keepCase: true फ़ील्ड के नामों को proto में लिखे गए रूप में ही रखता है।
  • longs: String 64-बिट इंटिजर को स्ट्रिंग के रूप में सुरक्षित रखता है।
  • पैकेज पथ users.v1, proto.users.v1 बन जाता है।
const protoLoader = require('@grpc/proto-loader');
const grpc = require('@grpc/grpc-js');

const pkgDef = protoLoader.loadSync('user.proto', {
  keepCase: true,
  longs: String,
  enums: String,
  defaults: true,
  oneofs: true,
});

const proto = grpc.loadPackageDefinition(pkgDef);
const UserService = proto.users.v1.UserService;

सर्वर स्टब लागू करना

जनरेट किया गया UserService आपको एक सेवा परिभाषा देता है, जिसके साथ आप हैंडलर पंजीकृत करते हैं। हर यूनरी हैंडलर को (call, callback) मिलता है; call.request आपका डिकोड किया हुआ अनुरोध मैसेज होता है और आप Node-शैली के callback(err, response) से उत्तर देते हैं।

  • grpc.status से प्राप्त code वाली त्रुटि पास करके gRPC स्थिति लौटाएँ।
  • प्रतिक्रिया ऑब्जेक्ट के फ़ील्ड प्रतिक्रिया मैसेज के फ़ील्ड से मेल खाने चाहिए।
const server = new grpc.Server();

server.addService(UserService.service, {
  GetUser(call, callback) {
    const { id } = call.request;
    const user = db.find(id);
    if (!user) {
      return callback({
        code: grpc.status.NOT_FOUND,
        message: `User ${id} not found`,
      });
    }
    callback(null, { user });
  },
});

क्लाइंट स्टब से कॉल करना

वही जनरेट किया गया UserService क्लाइंट कंस्ट्रक्टर भी होता है। आप इसे लक्ष्य पते और क्रेडेंशियल के साथ इंस्टैंशिएट करते हैं, फिर मेथड को सीधे कॉल करते हैं। हर यूनरी कॉल में अनुरोध ऑब्जेक्ट और Node-शैली का कॉलबैक लिया जाता है।

  • स्थानीय/डेवलपमेंट के लिए credentials.createInsecure() का उपयोग करें; प्रोडक्शन में TLS इस्तेमाल करें।
  • अनुरोध और प्रतिक्रिया proto मैसेज से मेल खाने वाले साधारण JS ऑब्जेक्ट होते हैं।
const client = new UserService(
  'localhost:50051',
  grpc.credentials.createInsecure()
);

client.GetUser({ id: 'u_123' }, (err, res) => {
  if (err) {
    console.error(err.code, err.message);
    return;
  }
  console.log(res.user.email);
});

कॉन्ट्रैक्ट को सुरक्षित रूप से विकसित करना

कॉन्ट्रैक्ट तभी उपयोगी है जब डिप्लॉय किए गए क्लाइंट को तोड़े बिना उसमें बदलाव किया जा सके। कुछ नियमों का पालन करने पर proto3 में जोड़-आधारित विकास सुरक्षित रहता है।

  • जोड़ें नए फ़ील्ड, जिनके लिए पहले कभी उपयोग न किए गए नए टैग नंबर हों — पुराने क्लाइंट उन्हें अनदेखा कर देते हैं।
  • टैग को कभी दोबारा उपयोग या पुनः क्रमांकित न करें; हटाए गए टैग को reserved से चिह्नित करें।
  • फ़ील्ड का नाम बदलना वायर-संगत होता है (महत्वपूर्ण टैग होता है), लेकिन JSON/टेक्स्ट उपयोग को तोड़ देता है।
  • टैग नंबर और नाम, दोनों के लिए reserved का उपयोग करें, ताकि उनका आकस्मिक पुनः उपयोग न हो।
message User {
  reserved 4, 5;              // retired tags, never reuse
  reserved "phone";          // retired field name
  string id = 1;
  string email = 2;
  bool active = 3;
  string display_name = 6;   // safe additive change
}

त्वरित जाँच

आपको डिप्लॉय किए गए User मैसेज से अप्रचलित phone फ़ील्ड (टैग 4) हटाना है। इसे बैकवर्ड-संगत तरीके से हटाने का सही तरीका क्या है?

पुनरावलोकन

आपने Protobuf IDL के साथ gRPC कॉन्ट्रैक्ट डिज़ाइन करना और उनका उपयोग करना सीखा:

  • syntax = "proto3" और package वाली .proto फ़ाइल क्लाइंट और सर्वर के लिए सत्य का एकमात्र स्रोत होती है।
  • message टाइप वाले रिकॉर्ड परिभाषित करता है; हर फ़ील्ड के बाद की संख्या उसका स्थिर वायर टैग होती है, डिफ़ॉल्ट मान नहीं।
  • service + rpc मेथड घोषित करते हैं; stream कीवर्ड यूनरी, सर्वर, क्लाइंट या द्विदिशात्मक स्ट्रीमिंग चुनता है।
  • enum, repeated और नेस्टेड मैसेज अधिक समृद्ध डेटा का मॉडल बनाते हैं; int64 एक JS स्ट्रिंग में डिकोड होता है।
  • Node में @grpc/proto-loader + grpc.loadPackageDefinition सर्वर सेवा और क्लाइंट कंस्ट्रक्टर, दोनों जनरेट करते हैं।
  • कॉन्ट्रैक्ट को जोड़-आधारित तरीके से विकसित करें और हटाए गए टैग/नाम को reserved से सुरक्षित रखें।
शुरुआत निःशुल्क

एआई शिक्षक के साथ JavaScript सीखें — निःशुल्क

अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।

पाठ्यक्रम
22
पाठ
92

अक्सर पूछे जाने वाले प्रश्न

क्या “Protobuf IDL से सेवाएँ और संदेश परिभाषित करना” पाठ निःशुल्क है?

हाँ—“Protobuf IDL से सेवाएँ और संदेश परिभाषित करना” का पूरा पाठ यहाँ वेब पर निःशुल्क पढ़ा जा सकता है। इंटरैक्टिव अभ्यास (अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर) करने और Node.js बैकएंड विकास बूटकैंप पाठ्यक्रम का बाकी हिस्सा अनलॉक करने के लिए CoddyKit PRO लें। Node.js बैकएंड विकास बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

“Protobuf IDL से सेवाएँ और संदेश परिभाषित करना” में मैं क्या सीखूँगा?

.proto अनुबंध लिखिए और उनसे टाइप-सुरक्षित क्लाइंट व सर्वर स्टब बनाइए। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ Node.js बैकएंड विकास बूटकैंप का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।

क्या Node.js बैकएंड विकास बूटकैंप शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?

पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर Node.js बैकएंड विकास बूटकैंप शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 1वाँ पाठ है।

“Protobuf IDL से सेवाएँ और संदेश परिभाषित करना” पाठ पूरा करने में कितना समय लगता है?

CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।

क्या मैं इस Node.js बैकएंड विकास बूटकैंप पाठ में कोड लिख और चला सकता हूँ?

हाँ। हर Node.js बैकएंड विकास बूटकैंप पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।

इस पाठ्यक्रम के सभी पाठ

  1. Protobuf IDL से सेवाएँ और संदेश परिभाषित करना
  2. Unary, Server, Client और द्विदिश स्ट्रीमिंग RPC
  3. इंटरसेप्टर, समय-सीमाएँ और मेटाडेटा
  4. Proto का विकास और पिछली संगतता
← Node.js बैकएंड विकास बूटकैंप पर वापस जाएँ