सेवाओं के निर्माण के अपने वर्षों के दौरान, RESTful API मेरा प्राथमिक लक्ष्य रहा है। हालाँकि, भले ही REST के अपने गुण हों, लेकिन इसका मतलब यह नहीं है कि यह हर उपयोग के मामले के लिए सबसे अच्छा तरीका है। पिछले कुछ वर्षों में, मैंने सीखा है कि, कभी-कभी, कुछ परिदृश्यों के लिए बेहतर विकल्प हो सकते हैं। REST के साथ सिर्फ़ इसलिए जुड़े रहना क्योंकि मैं इसके बारे में भावुक हूँ - जब यह सही फिट नहीं है - केवल तकनीकी ऋण और उत्पाद स्वामी के साथ तनावपूर्ण संबंध का परिणाम है।
RESTful दृष्टिकोण के साथ सबसे बड़ी समस्या यह है कि किसी व्यावसायिक निर्णय के लिए सभी आवश्यक जानकारी प्राप्त करने के लिए कई अनुरोध करने की आवश्यकता होती है।
उदाहरण के लिए, मान लीजिए कि मुझे किसी ग्राहक का 360-दृश्य चाहिए। मुझे निम्नलिखित अनुरोध करने होंगे:
GET /customers/{some_token}
आधार ग्राहक जानकारी प्रदान करता हैGET /addresses/{some_token}
एक आवश्यक पता प्रदान करता हैGET /contacts/{some_token}
संपर्क जानकारी लौटाता हैGET /credit/{some_token}
मुख्य वित्तीय जानकारी लौटाता है
जबकि मैं समझता हूं कि REST का अंतर्निहित लक्ष्य प्रत्येक संसाधन के लिए प्रतिक्रियाओं को लेजर-केंद्रित रखना है, यह परिदृश्य उपभोक्ता पक्ष पर अधिक काम करता है। एक उपयोगकर्ता इंटरफ़ेस को पॉप्युलेट करने के लिए जो किसी संगठन को ग्राहक के साथ भविष्य के व्यवसाय से संबंधित निर्णय लेने में मदद करता है, उपभोक्ता को कई कॉल करने होंगे
इस लेख में, मैं दिखाऊंगा कि क्यों ग्राफक्यूएल एक RESTful API की तुलना में बेहतर तरीका है, तथा प्रदर्शित करूंगा कि ग्राफक्यूएल के साथ शीघ्रता से कार्य करने के लिए अपोलो सर्वर (और अपोलो एक्सप्लोरर) को कैसे तैनात किया जाए।
मैं Node.js के साथ अपना समाधान बनाने और Heroku पर अपना समाधान तैनात करने की योजना बना रहा हूं।
ऐसे कई सामान्य उपयोग मामले हैं जब GraphQL, REST से बेहतर दृष्टिकोण है:
चूंकि ग्राफक्यूएल के बारे में मेरी जानकारी पर्याप्त नहीं है, इसलिए मैंने इस लेख के लिए अपोलो सर्वर का उपयोग करने का निर्णय लिया।
अपोलो सर्वर एक ग्राफक्यूएल सर्वर है जो किसी भी ग्राफक्यूएल स्कीमा के साथ काम करता है। इसका लक्ष्य ग्राफक्यूएल एपीआई बनाने की प्रक्रिया को सरल बनाना है। अंतर्निहित डिज़ाइन एक्सप्रेस या कोआ जैसे फ्रेमवर्क के साथ अच्छी तरह से एकीकृत होता है। मैं अपने अगले लेख में वास्तविक समय के डेटा के लिए सदस्यता ( ग्राफक्यूएल-डब्ल्यूएस लाइब्रेरी के माध्यम से) का लाभ उठाने की क्षमता का पता लगाऊंगा।
अपोलो सर्वर वास्तव में अपोलो एक्सप्लोरर के रूप में चमकता है, जो एक अंतर्निहित वेब इंटरफ़ेस है जिसका उपयोग डेवलपर्स अपने ग्राफ़क्यूएल एपीआई का पता लगाने और परीक्षण करने के लिए कर सकते हैं। स्टूडियो मेरे लिए एकदम सही होगा, क्योंकि यह क्वेरी के आसान निर्माण और ग्राफ़िकल प्रारूप में एपीआई स्कीमा को देखने की क्षमता की अनुमति देता है।
इस उदाहरण के लिए, मान लें कि हमें ग्राहक का 360-दृश्य प्रदान करने के लिए निम्नलिखित स्कीमा की आवश्यकता है:
type Customer { token: String name: String sic_code: String } type Address { token: String customer_token: String address_line1: String address_line2: String city: String state: String postal_code: String } type Contact { token: String customer_token: String first_name: String last_name: String email: String phone: String } type Credit { token: String customer_token: String credit_limit: Float balance: Float credit_score: Int }
मैं निम्नलिखित ग्राफ़क्यूएल क्वेरीज़ पर ध्यान केंद्रित करने की योजना बना रहा हूँ:
type Query { addresses: [Address] address(customer_token: String): Address contacts: [Contact] contact(customer_token: String): Contact customers: [Customer] customer(token: String): Customer credits: [Credit] credit(customer_token: String): Credit }
उपभोक्ता उस ग्राहक के लिए टोकन प्रदान करेंगे जिसे वे देखना चाहते हैं। हम उचित पता, संपर्क और क्रेडिट ऑब्जेक्ट भी प्राप्त करने की उम्मीद करते हैं। लक्ष्य एक ही API कॉल के बजाय इस सारी जानकारी के लिए चार अलग-अलग API कॉल करने से बचना है।
मैंने अपने स्थानीय वर्कस्टेशन पर graphql-server-customer
नामक एक नया फ़ोल्डर बनाकर शुरुआत की। फिर, अपोलो सर्वर डॉक्यूमेंटेशन के आरंभ अनुभाग का उपयोग करते हुए, मैंने टाइपस्क्रिप्ट दृष्टिकोण का उपयोग करके चरण एक और दो का पालन किया।
इसके बाद, मैंने अपनी स्कीमा को परिभाषित किया और परीक्षण के लिए कुछ स्थिर डेटा भी शामिल किया। आम तौर पर, हम डेटाबेस से कनेक्ट होते हैं, लेकिन इस डेमो के लिए स्थिर डेटा ठीक काम करेगा।
नीचे मेरी अद्यतनित index.ts
फ़ाइल है:
import { ApolloServer } from '@apollo/server'; import { startStandaloneServer } from '@apollo/server/standalone'; const typeDefs = `#graphql type Customer { token: String name: String sic_code: String } type Address { token: String customer_token: String address_line1: String address_line2: String city: String state: String postal_code: String } type Contact { token: String customer_token: String first_name: String last_name: String email: String phone: String } type Credit { token: String customer_token: String credit_limit: Float balance: Float credit_score: Int } type Query { addresses: [Address] address(customer_token: String): Address contacts: [Contact] contact(customer_token: String): Contact customers: [Customer] customer(token: String): Customer credits: [Credit] credit(customer_token: String): Credit } `; const resolvers = { Query: { addresses: () => addresses, address: (parent, args, context) => { const customer_token = args.customer_token; return addresses.find(address => address.customer_token === customer_token); }, contacts: () => contacts, contact: (parent, args, context) => { const customer_token = args.customer_token; return contacts.find(contact => contact.customer_token === customer_token); }, customers: () => customers, customer: (parent, args, context) => { const token = args.token; return customers.find(customer => customer.token === token); }, credits: () => credits, credit: (parent, args, context) => { const customer_token = args.customer_token; return credits.find(credit => credit.customer_token === customer_token); } }, }; const server = new ApolloServer({ typeDefs, resolvers, }); const { url } = await startStandaloneServer(server, { listen: { port: 4000 }, }); console.log(`Apollo Server ready at: ${url}`); const customers = [ { token: 'customer-token-1', name: 'Acme Inc.', sic_code: '1234' }, { token: 'customer-token-2', name: 'Widget Co.', sic_code: '5678' } ]; const addresses = [ { token: 'address-token-1', customer_token: 'customer-token-1', address_line1: '123 Main St.', address_line2: '', city: 'Anytown', state: 'CA', postal_code: '12345' }, { token: 'address-token-22', customer_token: 'customer-token-2', address_line1: '456 Elm St.', address_line2: '', city: 'Othertown', state: 'NY', postal_code: '67890' } ]; const contacts = [ { token: 'contact-token-1', customer_token: 'customer-token-1', first_name: 'John', last_name: 'Doe', email: '[email protected]', phone: '123-456-7890' } ]; const credits = [ { token: 'credit-token-1', customer_token: 'customer-token-1', credit_limit: 10000.00, balance: 2500.00, credit_score: 750 } ];
सब कुछ अपेक्षानुसार कॉन्फ़िगर होने पर, हम सर्वर प्रारंभ करने के लिए निम्नलिखित कमांड चलाते हैं:
$ npm start
अपोलो सर्वर पोर्ट 4000 पर चल रहा था, मैंने अपोलो एक्सप्लोरर तक पहुँचने के लिए http://localhost:4000/ URL का उपयोग किया। फिर मैंने निम्नलिखित उदाहरण क्वेरी सेट की:
query ExampleQuery { addresses { token } contacts { token } customers { token } }
अपोलो एक्सप्लोरर में यह इस प्रकार दिखता है:
उदाहरण क्वेरी बटन दबाकर, मैंने पुष्टि की कि प्रतिक्रिया पेलोड index.ts
में मेरे द्वारा प्रदान किए गए स्थिर डेटा के साथ संरेखित है:
{ "data": { "addresses": [ { "token": "address-token-1" }, { "token": "address-token-22" } ], "contacts": [ { "token": "contact-token-1" } ], "customers": [ { "token": "customer-token-1" }, { "token": "customer-token-2" } ] } }
अपने ग्राहक 360 उपयोग मामले पर आगे बढ़ने से पहले, मैं इस सेवा को क्लाउड में चलाना चाहता था।
चूंकि यह लेख कुछ नया करने के बारे में है, इसलिए मैं यह देखना चाहता था कि मेरे अपोलो सर्वर को हेरोकू पर तैनात करना कितना कठिन होगा।
मुझे पता था कि मुझे स्थानीय रूप से चलाने और क्लाउड में कहीं चलाने के बीच पोर्ट नंबर के अंतर को संबोधित करना होगा। मैंने सर्वर शुरू करने के लिए अपने कोड को अपडेट किया जैसा कि नीचे दिखाया गया है:
const { url } = await startStandaloneServer(server, { listen: { port: Number.parseInt(process.env.PORT) || 4000 }, });
इस अद्यतन के साथ, हम पोर्ट 4000 का उपयोग करेंगे जब तक कि किसी पर्यावरण चर में PORT मान निर्दिष्ट न हो।
Gitlab का उपयोग करते हुए, मैंने इन फ़ाइलों के लिए एक नया प्रोजेक्ट बनाया और Heroku कमांड-लाइन इंटरफ़ेस (CLI) का उपयोग करके अपने Heroku खाते में लॉग इन किया:
$ heroku login
आप Heroku में उनके CLI या Heroku डैशबोर्ड वेब UI के साथ एक नया ऐप बना सकते हैं। इस लेख के लिए, हम CLI का उपयोग करेंगे:
$ heroku create jvc-graphql-server-customer
CLI कमांड ने निम्नलिखित प्रतिक्रिया लौटाई:
Creating ⬢ jvc-graphql-server-customer... done https://jvc-graphql-server-customer-b62b17a2c949.herokuapp.com/ | https://git.heroku.com/jvc-graphql-server-customer.git
कमांड ने हेरोकू द्वारा रिमोट के रूप में प्रयुक्त रिपोजिटरी को भी स्वचालित रूप से जोड़ दिया:
$ git remote heroku origin
डिफ़ॉल्ट रूप से, अपोलो सर्वर उत्पादन वातावरण में अपोलो एक्सप्लोरर को अक्षम कर देता है। अपने डेमो के लिए, मैं इसे Heroku पर चालू रखना चाहता हूँ। ऐसा करने के लिए, मुझे NODE_ENV
पर्यावरण चर को विकास पर सेट करना होगा। मैं इसे निम्नलिखित CLI कमांड के साथ सेट कर सकता हूँ:
$ heroku config:set NODE_ENV=development
CLI कमांड ने निम्नलिखित प्रतिक्रिया लौटाई:
Setting NODE_ENV and restarting ⬢ jvc-graphql-server-customer... done, v3 NODE_ENV: development
अब हम अपने कोड को Heroku पर तैनात करने की स्थिति में हैं:
$ git commit --allow-empty -m 'Deploy to Heroku' $ git push heroku
हेरोकू डैशबोर्ड का एक त्वरित दृश्य दिखाता है कि मेरा अपोलो सर्वर बिना किसी समस्या के चल रहा है:
यदि आप Heroku में नए हैं, तो यह मार्गदर्शिका आपको बताएगी कि नया खाता कैसे बनाएं और Heroku CLI कैसे स्थापित करें।
GraphQL के साथ, मैं निम्नलिखित क्वेरी के साथ अपने ग्राहक 360 उपयोग मामले के लिए स्वीकृति मानदंडों को पूरा कर सकता हूं:
query CustomerData($token: String) { customer(token: $token) { name sic_code token }, address(customer_token: $token) { token customer_token address_line1 address_line2 city state postal_code }, contact(customer_token: $token) { token, customer_token, first_name, last_name, email, phone }, credit(customer_token: $token) { token, customer_token, credit_limit, balance, credit_score } }
मुझे बस एक एकल ग्राहक token
चर को customer-token-1
मान के साथ पास करना है:
{ "token": "customer-token-1" }
हम एकल GraphQL API कॉल का उपयोग करके सभी डेटा पुनः प्राप्त कर सकते हैं:
{ "data": { "customer": { "name": "Acme Inc.", "sic_code": "1234", "token": "customer-token-1" }, "address": { "token": "address-token-1", "customer_token": "customer-token-1", "address_line1": "123 Main St.", "address_line2": "", "city": "Anytown", "state": "CA", "postal_code": "12345" }, "contact": { "token": "contact-token-1", "customer_token": "customer-token-1", "first_name": "John", "last_name": "Doe", "email": "[email protected]", "phone": "123-456-7890" }, "credit": { "token": "credit-token-1", "customer_token": "customer-token-1", "credit_limit": 10000, "balance": 2500, "credit_score": 750 } } }
नीचे मेरे Heroku ऐप से चल रहे अपोलो एक्सप्लोरर का स्क्रीनशॉट है:
मुझे अपने करियर के शुरूआती दिनों की याद आती है जब जावा और C# डेवलपर अपनाने के लिए एक दूसरे के खिलाफ प्रतिस्पर्धा कर रहे थे। बहस के प्रत्येक पक्ष के अधिवक्ता यह साबित करने के लिए तैयार थे कि उनकी चुनी हुई तकनीक सबसे अच्छी पसंद थी ... तब भी जब ऐसा नहीं था।
इस उदाहरण में, हम मेरे ग्राहक 360 उपयोग मामले को कई तरीकों से पूरा कर सकते थे। एक सिद्ध RESTful API का उपयोग करना कारगर होता, लेकिन सभी आवश्यक डेटा को पुनः प्राप्त करने के लिए कई API कॉल की आवश्यकता होती। अपोलो सर्वर और ग्राफ़क्यूएल का उपयोग करने से मुझे एक ही API कॉल के साथ अपने लक्ष्य पूरे करने में मदद मिली।
मुझे यह भी पसंद है कि टर्मिनल में कुछ ही कमांड के साथ अपने ग्राफक्यूएल सर्वर को हेरोकू में तैनात करना कितना आसान है। इससे मुझे कार्यान्वयन पर ध्यान केंद्रित करने में मदद मिलती है - बुनियादी ढांचे के बोझ को कम करना और अपने कोड को किसी विश्वसनीय तृतीय-पक्ष प्रदाता के पास चलाना। सबसे महत्वपूर्ण बात यह है कि यह मेरे व्यक्तिगत मिशन कथन के बिल्कुल अनुरूप है:
"अपना समय उन सुविधाओं/कार्यक्षमताओं को प्रदान करने पर केंद्रित करें जो आपकी बौद्धिक संपदा के मूल्य को बढ़ाती हैं। बाकी सभी चीज़ों के लिए फ्रेमवर्क, उत्पादों और सेवाओं का लाभ उठाएँ।"
– जे. वेस्टर
यदि आप इस लेख के स्रोत कोड में रुचि रखते हैं, तो यह GitLab पर उपलब्ध है।
लेकिन रुकिए... अभी और भी कुछ है!
मेरी अगली पोस्ट में, हम सब्सक्रिप्शन के साथ प्रमाणीकरण और वास्तविक समय डेटा पुनर्प्राप्ति को लागू करने के लिए अपने ग्राफक्यूएल सर्वर का और अधिक निर्माण करेंगे।
आपका दिन सचमुच बहुत अच्छा हो!