इस ब्लॉग पोस्ट श्रृंखला में, मैं AWS में बहु-किरायेदार सेवाओं के निर्माण के लिए सर्वोत्तम प्रथाओं पर चर्चा करना चाहूंगा। बहु-किरायेदार सेवाओं का निर्माण कैसे करें, इस पर मौजूदा साहित्य आमतौर पर सैकड़ों ग्राहकों के साथ SaaS अनुप्रयोगों पर लक्षित होता है (उदाहरण के लिए AWS सर्वर रहित सेवाओं का उपयोग करके एक बहु-किरायेदार SaaS समाधान बनाना )।
इस श्रृंखला का मुख्य तर्क कम ग्राहकों वाले उपयोग के मामलों के लिए बहु-किरायेदार सेवाओं के निर्माण पर ध्यान केंद्रित करना है जो सभी एडब्ल्यूएस खातों में तैनात हैं। आमतौर पर, यह उन परिदृश्यों पर लागू होगा जब आप आंतरिक उपयोग के लिए बहु-किरायेदार सेवा बनाते हैं।
मैं प्रत्येक प्रकार की सेवा-से-सेवा एकीकरण के लिए ब्लॉग पोस्ट की श्रृंखला को तीन भागों में विभाजित करूंगा: सिंक्रोनस, एसिंक्रोनस और बैच एकीकरण।
भाग 1 दो AWS सेवाओं के लिए बहु-किरायेदार आर्किटेक्चर पर चर्चा करेगा: API गेटवे और AppSync। पूरे लेख में, मैं टाइपस्क्रिप्ट और एडब्ल्यूएस सीडीके में इस लेख के लिए बनाए गए नमूना एप्लिकेशन ऐप से कोड का संदर्भ देता हूं: https://github.com/filletofish/aws-cdk-multi-tenant-api-example/tree/main ।
आंतरिक सेवाओं के लिए बहु-किरायेदारी
1.1. किरायेदार अलगाव
1.2. बहु-किरायेदार निगरानी
1.3. स्केलिंग
आंतरिक सेवाओं के लिए बहु-किरायेदारी
2.1. किरायेदार-अलगाव - प्रवेश-नियंत्रण
2.2 किरायेदार-अलगाव - शोरगुल वाले पड़ोसी की समस्या
2.3 बहु-किरायेदार निगरानी
2.4 मेट्रिक्स, अलार्म, डैशबोर्ड
2.5 ऑनबोर्डिंग और ऑफबोर्डिंग एपीआई क्लाइंट
AWS AppSync के साथ बहु-किरायेदारी
निष्कर्ष
मल्टी-टेनेंसी सॉफ्टवेयर की एक ही इंस्टेंस के साथ कई ग्राहकों या किरायेदारों को सेवा प्रदान करने की क्षमता है।
एक बार जब आप एक से अधिक टीमों को अपनी सेवा एपीआई पर कॉल करने की अनुमति देते हैं, तो आपकी सेवा बहु-किरायेदार बन जाती है। मल्टी-टेनेंट आर्किटेक्चर आपकी सेवाओं में अतिरिक्त जटिलता लाता है, जैसे किरायेदार अलगाव, किरायेदार-स्तरीय निगरानी और स्केलिंग।
आम तौर पर, किरायेदार अलगाव यह सुनिश्चित करके सुरक्षा चिंताओं को संबोधित करता है कि किरायेदारों को दूसरे किरायेदार के संसाधनों तक पहुंचने से रोका जाता है। इसके अलावा, किरायेदार अलगाव को यह सुनिश्चित करने के लिए लागू किया गया है कि एक किरायेदार के कारण होने वाली कोई भी विफलता आपकी सेवा के अन्य किरायेदारों को प्रभावित नहीं करती है। इसे अक्सर शोरगुल वाले पड़ोसी की समस्या के रूप में भी जाना जाता है। किरायेदार अलगाव रणनीतियों पर AWS श्वेतपत्र में और देखें https://d1.awsstatic.com/whitepapers/saas-tenant-isolation-strategies.pdf ।
एक बार जब कई किरायेदार बुनियादी ढांचे के संसाधनों को साझा करना शुरू कर देते हैं, तो आपको यह निगरानी करने की आवश्यकता होगी कि आपका प्रत्येक किरायेदार आपके सिस्टम का उपयोग कैसे करता है। इसका आमतौर पर मतलब है कि किरायेदार का नाम या पहचानकर्ता आपके लॉग, मेट्रिक्स और डैशबोर्ड में मौजूद होना चाहिए। बहु-किरायेदार निगरानी कई कारणों से उपयोगी हो सकती है:
एकल-किरायेदार सेवाओं की तुलना में बहु-किरायेदार सेवाओं को स्केलिंग चुनौतियों का अधिक सामना करना पड़ता है। हालाँकि, स्केलेबिलिटी एक बहुत बड़ा विषय है और मैं इसे इस ब्लॉग पोस्ट में शामिल नहीं करूँगा।
यदि आप अपनी AWS वेब सेवा को AWS में REST , HTTP, या WebSocket API के साथ बना रहे हैं तो आप संभवतः API गेटवे का उपयोग कर रहे हैं।
AWS सेवा के संसाधनों और डेटा को अलग करने, आसान लागत-प्रबंधन और परीक्षण और उत्पादन वातावरण के बीच अलगाव के लिए प्रत्येक सेवा को अपने स्वयं के AWS खाते में तैनात करने की अनुशंसा करता है ( AWS श्वेतपत्र में एकाधिक खातों का उपयोग करके अपने AWS वातावरण को व्यवस्थित करने में विवरण देखें)।
यदि आपकी कंपनी की सेवाएँ AWS में तैनात हैं तो आपके API गेटवे तक पहुंच के प्रबंधन के लिए सबसे स्पष्ट समाधान AWS IAM है। एडब्ल्यूएस कॉग्निटो मल्टी-टेनेंट एपीआई तक पहुंच के प्रबंधन के लिए एक और विकल्प है ( एपीआई गेटवे का उपयोग करके बड़े पैमाने पर एक स्तरीय, मल्टी-टेनेंट आरईएसटी एपीआई को थ्रॉटलिंग करना , अमेज़ॅन कॉग्निटो के पक्ष और विपक्ष में मामला देखें)।
AWS IAM और AWS कॉग्निटो के बीच तुलना एक अलग गहन विश्लेषण की पात्र है। लेकिन इस लेख के लिए, मैं AWS IAM के साथ ही रहूंगा क्योंकि जब आपकी कंपनी की सेवाएं AWS में हों तो पहुंच प्रबंधित करने का यह सबसे आसान तरीका है।
एक बार जब आप एपीआई गेटवे विधि के लिए एडब्ल्यूएस आईएएम प्राधिकरण सक्षम कर लेते हैं ( सीएफएन देखें), तो इस विधि के लिए सभी एपीआई अनुरोधों पर आपके एपीआई गेटवे को कॉल करने की अनुमति वाली आईएएम पहचान के क्रेडेंशियल के साथ हस्ताक्षर किए जाने चाहिए।
डिफ़ॉल्ट रूप से, AWS खातों के बीच किसी पहुंच की अनुमति नहीं है। उदाहरण के लिए, किसी अन्य AWS खाते के क्रेडेंशियल्स के साथ आपके API गेटवे को लागू करना विफल हो जाएगा। अपने ग्राहकों को अपने एपीआई के साथ एकीकृत करने के लिए आपको क्रॉस-अकाउंट एक्सेस सेट करना होगा। अपने एपीआई गेटवे पर क्रॉस-अकाउंट एक्सेस देने के लिए आप दो तरीकों का उपयोग कर सकते हैं: संसाधन-आधारित प्राधिकरण (एपीआई गेटवे HTTP एपीआई के लिए उपलब्ध नहीं) और पहचान-आधारित प्राधिकरण ( https://repost.aws/knowledge-center/ पर अधिक देखें) एक्सेस-एपीआई-गेटवे-अकाउंट ):
संसाधन-आधारित प्राधिकरण के साथ एक ग्राहक को शामिल करना । संसाधन-आधारित पहुंच के लिए, आपको एपीआई गेटवे संसाधन नीति को अपडेट करना होगा और अपने क्लाइंट का AWS खाता जोड़ना होगा। इस पद्धति का मुख्य नुकसान यह है कि एक बार जब आप संसाधन नीति को अपडेट कर देते हैं, तो परिवर्तनों को प्रभावी करने के लिए एपीआई गेटवे चरण को फिर से तैनात करने की आवश्यकता होती है (एडब्ल्यूएस दस्तावेज़ [1] और [2] देखें)। हालाँकि, यदि आप सीडीके का उपयोग करते हैं तो आप नए चरणों की तैनाती को स्वचालित कर सकते हैं ( एपीआई गेटवे के लिए एडब्ल्यूएस सीडीके डॉक्स देखें)। एक अन्य नुकसान संसाधन नीति की अधिकतम लंबाई की सीमा है।
पहचान-आधारित प्राधिकरण के साथ एक ग्राहक को शामिल करना । पहचान-आधारित पहुंच नियंत्रण के लिए, आपको क्लाइंट के लिए एक IAM भूमिका बनानी होगी और भूमिका की संसाधन नीति (विश्वसनीय संबंध) को अपडेट करके क्लाइंट को इसे ग्रहण करने की अनुमति देनी होगी। आप IAM उपयोगकर्ताओं का उपयोग कर सकते हैं, लेकिन सुरक्षा की दृष्टि से IAM भूमिकाएँ बेहतर हैं। भूमिकाएँ अस्थायी क्रेडेंशियल्स के साथ प्रमाणीकरण की अनुमति देती हैं और IAM उपयोगकर्ता क्रेडेंशियल्स को संग्रहीत करने की आवश्यकता नहीं होती है। प्रति खाता 1,000 भूमिकाओं की सीमा है, लेकिन यह सीमा समायोज्य है। साथ ही, आपके एपीआई तक क्रॉस-अकाउंट एक्सेस प्राप्त करने के लिए भूमिका-आधारित पद्धति का एक और नुकसान यह है कि आपको प्रत्येक नए एपीआई क्लाइंट के लिए एक आईएएम भूमिका बनाने की आवश्यकता है। हालाँकि, भूमिका प्रबंधन को सीडीके के साथ स्वचालित किया जा सकता है ( प्रदान किए गए सीडीके ऐप से कोड नमूना देखें)।
AWS IAM प्राधिकरण आपको केवल API गेटवे तक पहुंच को नियंत्रित करने की अनुमति देता है (IAM नीति का उपयोग करके आप निर्दिष्ट कर सकते हैं कि AWS खाता किस API गेटवे एंडपॉइंट को कॉल कर सकता है)। आपकी सेवा के डेटा और अन्य अंतर्निहित संसाधनों तक नियंत्रण पहुंच लागू करना आपकी ज़िम्मेदारी है। अपनी सेवा के भीतर, आप कॉल करने वाले के एडब्ल्यूएस आईएएम एआरएन का उपयोग कर सकते हैं जो आगे पहुंच नियंत्रण के लिए एपीआई गेटवे अनुरोध के साथ पारित किया जाता है:
export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => { // IAM Principal ARN of the api caller const callerArn = event.requestContext.identity.userArn!; // .. business logic based on caller return { statusCode: 200, body: JSON.stringify({ message: `Received API Call from ${callerArn}`, }) }; };
डिफ़ॉल्ट एपीआई गेटवे सीमा 10,000 टीपीएस ( एपीआई गेटवे कोटा और सीमाएं ) है। हालाँकि, आपकी डाउनस्ट्रीम निर्भरता के कारण, आपकी सेवा को कम टीपीएस सीमा की आवश्यकता हो सकती है। एक ही किरायेदार से एपीआई अनुरोधों के अधिभार से बचने के लिए जो पूरे सिस्टम की उपलब्धता को प्रभावित करेगा, आपको प्रति किरायेदार एपीआई दर सीमित करना लागू करना चाहिए (जिसे "थ्रॉटलिंग" या "प्रवेश नियंत्रण" भी कहा जाता है)।
आप प्रत्येक क्लाइंट के लिए अलग-अलग सीमाएं कॉन्फ़िगर करने के लिए एपीआई गेटवे एपीआई उपयोग योजनाओं और कुंजियों का उपयोग कर सकते हैं (विवरण के लिए एडब्ल्यूएस दस्तावेज़ देखें [1], [2], और [3])
एपीआई गेटवे में दो प्रकार के लॉग होते हैं:
एपीआई गेटवे निष्पादन लॉग: इसमें अनुरोध या प्रतिक्रिया पैरामीटर मान, कौन सी एपीआई कुंजियाँ आवश्यक हैं, क्या उपयोग योजनाएं सक्षम हैं, आदि जैसे डेटा शामिल हैं। डिफ़ॉल्ट रूप से सक्षम नहीं है, लेकिन कॉन्फ़िगर किया जा सकता है।
एपीआई गेटवे एक्सेस लॉग सुविधा: आपको यह लॉग करने की अनुमति देता है कि आपके एपीआई को किसने एक्सेस किया है, इसे कैसे एक्सेस किया गया था, किस एंडपॉइंट तक एक्सेस किया गया था, और एपीआई कॉल का परिणाम। आप अपना लॉग प्रारूप प्रदान कर सकते हैं और चुन सकते हैं कि संदर्भ चर के साथ क्या लॉग करना है (सीडीके में दस्तावेज़ देखें)।
आपके एपीआई क्लाइंट के अनुरोधों की निगरानी के लिए, मैं एक्सेस लॉगिंग सक्षम करने की अनुशंसा करूंगा। आप कम से कम कॉलर के AWS IAM ARN ( $context.identity.userArn
), अनुरोध पथ ( $context.path
), आपकी सेवा प्रतिक्रिया स्थिति कोड $context.status
और API कॉल विलंबता ( $context.responseLatency
) को लॉग कर सकते हैं। .
व्यक्तिगत रूप से, एडब्ल्यूएस आईएएम ऑथ और लैम्ब्डा फ़ंक्शन के साथ एक सेवा के लिए गणना के लिए मुझे यह एपीआई गेटवे एक्सेस लॉगिंग कॉन्फ़िगरेशन उपयोगी लगा:
const formatObject = { requestId: '$context.requestId', extendedRequestId: '$context.extendedRequestId', apiId: '$context.apiId', resourceId: '$context.resourceId', domainName: '$context.domainName', stage: '$context.stage', path: '$context.path', resourcePath: '$context.resourcePath', httpMethod: '$context.httpMethod', protocol: '$context.protocol', accountId: '$context.identity.accountId', sourceIp: '$context.identity.sourceIp', user: '$context.identity.user', userAgent: '$context.identity.userAgent', userArn: '$context.identity.userArn', caller: '$context.identity.caller', cognitoIdentityId: '$context.identity.cognitoIdentityId', status: '$context.status', integration: { // The status code returned from an integration. For Lambda proxy integrations, this is the status code that your Lambda function code returns. status: '$context.integration.status', // For Lambda proxy integration, the status code returned from AWS Lambda, not from the backend Lambda function code. integrationStatus: '$context.integration.integrationStatus', // The error message returned from an integration // A string that contains an integration error message. error: '$context.integration.error', latency: '$context.integration.latency', }, error: { responseType: '$context.error.responseType', message: '$context.error.message', }, requestTime: '$context.requestTime', responseLength: '$context.responseLength', responseLatency: '$context.responseLatency', }; const accessLogFormatString = JSON.stringify(formatObject); const accessLogFormat = apigw.AccessLogFormat.custom(accessLogFormatString);
एक बार लॉगिंग सक्षम हो जाने पर, आप चुने गए एपीआई क्लाइंट से नवीनतम कॉल आसानी से प्राप्त करने के लिए क्लाउडवॉच इनसाइट्स का उपयोग कर सकते हैं:
fields @timestamp, path, status, responseLatency, userArn | sort @timestamp desc | filter userArn like 'payment-service' | limit 20
डिफ़ॉल्ट रूप से एपीआई गेटवे द्वारा समर्थित क्लाउडवॉच मेट्रिक्स सभी अनुरोधों के लिए एकत्रित किए जाते हैं। लेकिन आप अपने एपीआई के क्लाइंट (किरायेदार) उपयोग की निगरानी करने में सक्षम होने के लिए अपने क्लाइंट नाम के अतिरिक्त आयाम के साथ कस्टम क्लाउडवॉच मेट्रिक्स प्रकाशित करने के लिए एपीआई गेटवे एक्सेस लॉग को पार्स कर सकते हैं। बहुत कम से कम, मैं प्रति-क्लाइंट क्लाउडवॉच मेट्रिक्स गणना, 4xx, 5xx, Dimension=${Client}
द्वारा विभाजित विलंबता प्रकाशित करने की अनुशंसा करता हूं। आप स्टेटस कोड और एपीआई पथ जैसे आयाम भी जोड़ सकते हैं।
2.4.1. प्रति-क्लाइंट मेट्रिक्स प्रकाशित करने के लिए मेट्रिक लॉग फ़िल्टर का उपयोग करना
क्लाउडवॉच मेट्रिक लॉग फ़िल्टर (दस्तावेज़ देखें) आपको एक कस्टम फ़िल्टर प्रदान करने और एपीआई गेटवे एक्सेस लॉग से मीट्रिक मान निकालने की अनुमति देता है (नीचे उदाहरण देखें)। मीट्रिक लॉग फ़िल्टर लॉग से कस्टम मीट्रिक आयामों के लिए मान निकालने की भी अनुमति देते हैं। बहु-किरायेदारी निगरानी के लिए, आयाम क्लाइंट कॉल करने वाले का IAM ARN हो सकता है।
मीट्रिक लॉग फ़िल्टर के मुख्य लाभ हैं (1) प्रबंधन के लिए कोई गणना नहीं (2) यह सरल और सस्ता है। लेकिन आप कोई डेटा संशोधन नहीं कर सकते (उदाहरण के लिए IAM ARN के बजाय अधिक पठनीय क्लाइंट नाम सेट करें) और प्रति एकल लॉग समूह (दस्तावेज़) में 100 मीट्रिक फ़िल्टर की सीमा है।
आयाम Client
और Path
के साथ Count
प्रकाशित करने के लिए क्लाउडवॉच मीट्रिक लॉग फ़िल्टर का उदाहरण
new logs.MetricFilter(this, 'MultiTenantApiCountMetricFilter', { logGroup: accessLogsGroup, filterPattern: logs.FilterPattern.exists('$.userArn'), metricNamespace: metricNamespace, metricName: 'Count', metricValue: '1', unit: cloudwatch.Unit.COUNT, dimensions: { client: '$.userArn', method: '$.httpMethod', path: '$.path',},}); });
दिए गए नमूना सीडीके एप्लिकेशन पर 4xx, 5xx त्रुटि और विलंबता मेट्रिक्स के लिए सभी मीट्रिक फ़िल्टर देखें।
2.4.2. प्रति-क्लाइंट मेट्रिक्स प्रकाशित करने के लिए लैम्ब्डा फ़ंक्शन का उपयोग करना
वैकल्पिक विकल्प लॉग को पार्स करने, मेट्रिक्स निकालने और उन्हें प्रकाशित करने के लिए लैम्ब्डा फ़ंक्शन बनाना है। यह आपको अज्ञात क्लाइंट को फ़िल्टर करने या userArn से क्लाइंट का नाम निकालने जैसे अधिक कस्टम कार्य करने की अनुमति देता है।
एपीआई गेटवे एक्सेस लॉग में लैम्ब्डा फ़ंक्शन की सदस्यता लेने के लिए सीडीके कोड की बस कुछ पंक्तियों के साथ:
const logProcessingFunction = new lambda.NodejsFunction( this, 'log-processor-function', { functionName: 'multi-tenant-api-log-processor-function', } ); new logs.SubscriptionFilter(this, 'MultiTenantApiLogSubscriptionFilter', { logGroup: accessLogsGroup, destination: new logsd.LambdaDestination(logProcessingFunction), filterPattern: logs.FilterPattern.allEvents(), });
कोड के साथ-साथ लॉग प्रोसेसर लैम्ब्डा फ़ंक्शन के कार्यान्वयन का पूरा उदाहरण देखें।
एक बार जब आप क्लाइंट द्वारा विभाजित एपीआई गेटवे मेट्रिक्स प्रकाशित करना शुरू कर देते हैं, तो अब आप प्रत्येक क्लाइंट के लिए अलग से क्लाउडवॉच डैशबोर्ड और क्लाउडवॉच अलार्म बना सकते हैं।
आपका सीडीके ऐप क्लाइंट के नाम, उनके एडब्ल्यूएस खाते, अनुरोधित टीपीएस सीमा और अन्य मेटाडेटा के साथ कॉन्फ़िगरेशन संग्रहीत करने का एक आसान समाधान हो सकता है। एक नए एपीआई क्लाइंट को ऑनबोर्ड करने के लिए आपको इसे कोड में प्रबंधित कॉन्फ़िगरेशन में जोड़ना होगा:
interface ApiClientConfig { name: string; awsAccounts: string[]; rateLimit: number; burstLimit: number; } const apiClients: ApiClientConfig[] = [ { name: 'payment-service', awsAccounts: ['111122223333','444455556666'], rateLimit: 10, burstLimit: 2, }, { name: 'order-service', awsAccounts: ['777788889999'], rateLimit: 1, burstLimit: 1, }, ];
इस कॉन्फ़िगरेशन का उपयोग करके सीडीके ऐप एक आईएएम भूमिका, एपीआई गेटवे उपयोग कुंजी बना सकता है, और क्लाइंट का नाम लैम्ब्डा फ़ंक्शन को पास कर सकता है जो एक्सेस लॉग को पार्स करता है (इसे नमूना एप्लिकेशन कोड में देखें)।
यदि आपकी सेवा में GraphQL API है तो आप संभवतः AppSync का उपयोग करेंगे। एपीआई गेटवे के समान, आप AppSync अनुरोधों को अधिकृत करने के लिए IAM Auth का उपयोग कर सकते हैं। AppSync के पास कोई संसाधन नीति नहीं है ( GH समस्या देखें), इसलिए आप AppSync API पर पहुंच नियंत्रण स्थापित करने के लिए केवल भूमिका-आधारित प्राधिकरण का उपयोग कर सकते हैं। एपीआई गेटवे के समान, आप अपनी सेवा के प्रत्येक नए किरायेदार के लिए एक अलग IAM भूमिका बनाएंगे।
दुर्भाग्य से, AppSync के पास प्रति-ग्राहक थ्रॉटलिंग के लिए सीमित समर्थन है जिसकी हमें किरायेदार अलगाव और निगरानी के लिए आवश्यकता है। हालाँकि आप WAF के साथ AppSync के लिए TPS सीमाएँ सेट कर सकते हैं, लेकिन आप अपने सेवा किरायेदारों को अलग करने के लिए प्रति-ग्राहक अलग-अलग सीमाएँ नहीं बना सकते। इसी तरह, AppSync एपीआई गेटवे की तरह एक्सेस लॉग प्रदान नहीं करता है।
समाधान? आप एपीआई गेटवे को अपने ऐपसिंक में प्रॉक्सी के रूप में जोड़ सकते हैं और किरायेदार अलगाव और निगरानी जैसी बहु-किरायेदारी आवश्यकताओं को लागू करने के लिए ऊपर वर्णित सभी एपीआई गेटवे सुविधाओं का उपयोग कर सकते हैं। इसके शीर्ष पर, आप अन्य एपीआई गेटवे सुविधाओं जैसे लैम्ब्डा ऑथराइज़र, कस्टम डोमेन और एपीआई जीवनचक्र प्रबंधन का उपयोग कर सकते हैं जो अभी तक AppSync में मौजूद नहीं हैं। नुकसान आपके अनुरोधों के लिए थोड़ी अतिरिक्त विलंबता है।
इतना ही। यदि आपके कोई प्रश्न या विचार हैं, तो मुझे टिप्पणियों में बताएं या सीधे मुझसे संपर्क करें। इस श्रृंखला के अगले भाग में, मैं AWS इवेंट ब्रिज और AWS SQS/SNS के साथ अतुल्यकालिक आंतरिक एकीकरण के लिए सर्वोत्तम प्रथाओं की समीक्षा करूंगा।
यदि आप AWS के शीर्ष पर बहु-किरायेदार सेवाओं के निर्माण के विषय में गहराई से जाना चाहते हैं तो मुझे ये संसाधन उपयोगी लगे: