MongoDB
 sql >> डेटाबेस >  >> NoSQL >> MongoDB

एडब्ल्यूएस लैम्ब्डा पर MongoDB कनेक्शन पूलिंग का उपयोग कैसे करें?

इस पोस्ट में, हम आपको दिखाएंगे कि Node.js और Java ड्राइवरों दोनों का उपयोग करके AWS लैम्ब्डा पर MongoDB कनेक्शन पूलिंग का उपयोग कैसे करें।

AWS लैम्ब्डा क्या है?

एडब्ल्यूएस लैम्ब्डा अमेज़ॅन वेब सेवाओं . द्वारा प्रदान की गई एक घटना-संचालित, सर्वर रहित कंप्यूटिंग सेवा है . यह उपयोगकर्ता को EC2 इंस्टेंस के विपरीत, बिना किसी व्यवस्थापकीय कार्य के कोड चलाने की अनुमति देता है जहां एक उपयोगकर्ता सर्वर, स्केलिंग, उच्च उपलब्धता आदि के प्रावधान के लिए जिम्मेदार है। इसके बजाय, आपको केवल कोड अपलोड करना होगा और ईवेंट ट्रिगर सेट करना होगा, और AWS लैम्ब्डा स्वचालित रूप से बाकी सब कुछ संभाल लेता है।

AWS लैम्ब्डा Node.js . सहित विभिन्न रनटाइम का समर्थन करता है , पायथन , जावा , और जाएं . इसे सीधे S3 . जैसी AWS सेवाओं द्वारा ट्रिगर किया जा सकता है , डायनेमोडीबी , किनेसिस , एसएनएस , आदि। हमारे उदाहरण में, हम लैम्ब्डा कार्यों को ट्रिगर करने के लिए एडब्ल्यूएस एपीआई गेटवे का उपयोग करते हैं।

कनेक्शन पूल क्या है?

डेटाबेस कनेक्शन को खोलना और बंद करना एक महंगा ऑपरेशन है क्योंकि इसमें CPU समय और मेमोरी दोनों शामिल होते हैं। यदि किसी एप्लिकेशन को प्रत्येक ऑपरेशन के लिए डेटाबेस कनेक्शन खोलने की आवश्यकता है, तो इसका गंभीर प्रदर्शन प्रभाव पड़ेगा।

क्या होगा यदि हमारे पास डेटाबेस कनेक्शन का एक गुच्छा है जो कैश में जीवित रखा जाता है? जब भी किसी एप्लिकेशन को डेटाबेस ऑपरेशन करने की आवश्यकता होती है, तो वह कैश से कनेक्शन उधार ले सकता है, आवश्यक ऑपरेशन कर सकता है, और उसे वापस दे सकता है। इस दृष्टिकोण का उपयोग करके, हम हर बार एक नया कनेक्शन स्थापित करने के लिए आवश्यक समय बचा सकते हैं और कनेक्शन का पुन:उपयोग कर सकते हैं। इस संचय को कनेक्शन पूल . के रूप में जाना जाता है ।

अधिकांश मोंगोडीबी ड्राइवरों में कनेक्शन पूल का आकार कॉन्फ़िगर करने योग्य है, और डिफ़ॉल्ट पूल आकार ड्राइवर से ड्राइवर में भिन्न होता है। उदाहरण के लिए, यह Node.js ड्राइवर में 5 है, जबकि जावा ड्राइवर में यह 100 है। कनेक्शन पूल आकार समानांतर अनुरोधों की अधिकतम संख्या निर्धारित करता है जिसे आपका ड्राइवर एक निश्चित समय में संभाल सकता है। यदि कनेक्शन पूल की सीमा समाप्त हो जाती है, तो मौजूदा अनुरोधों के पूरा होने तक प्रतीक्षा करने के लिए कोई भी नया अनुरोध किया जाएगा। इसलिए, पूल के आकार को ध्यान से चुना जाना चाहिए, एप्लिकेशन लोड और समवर्ती प्राप्त करने पर विचार करना।

AWS लैम्ब्डा में MongoDB कनेक्शन पूल

इस पोस्ट में, हम आपको MongoDB के लिए Node.js और Java ड्राइवर दोनों से जुड़े उदाहरण दिखाएंगे। इस ट्यूटोरियल के लिए, हम AWS EC2 इंस्टेंस का उपयोग करके स्केलग्रिड पर होस्ट किए गए MongoDB का उपयोग करते हैं। इसे सेट होने में 5 मिनट से भी कम समय लगता है, और आप 30-दिन का निःशुल्क परीक्षण बना सकते हैं आरंभ करने के लिए यहां।
Node.js और लैम्ब्डा ड्राइवर्स का उपयोग करके AWS लैम्ब्डा पर #MongoDB कनेक्शन पूलिंग का उपयोग कैसे करें ट्वीट करने के लिए क्लिक करें

Java ड्राइवर MongoDB कनेक्शन पूल

एडब्ल्यूएस लैम्ब्डा हैंडलर फ़ंक्शन में जावा ड्राइवर का उपयोग करके मोंगोडीबी कनेक्शन पूल को सक्षम करने के लिए कोड यहां दिया गया है:


public class LambdaFunctionHandler
		implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

	private MongoClient sgMongoClient;
	private String sgMongoClusterURI;
	private String sgMongoDbName;

	@Override
	public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
		APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
		response.setStatusCode(200);

		try {
			context.getLogger().log("Input: " + new Gson().toJson(input));
			init(context);
			String body = getLastAlert(input, context);
			context.getLogger().log("Result body: " + body);
			response.setBody(body);
		} catch (Exception e) {
			response.setBody(e.getLocalizedMessage());
			response.setStatusCode(500);
		}

		return response;
	}

	private MongoDatabase getDbConnection(String dbName, Context context) {
		if (sgMongoClient == null) {
			context.getLogger().log("Initializing new connection");
			MongoClientOptions.Builder destDboptions = MongoClientOptions.builder();
			destDboptions.socketKeepAlive(true);
			sgMongoClient = new MongoClient(new MongoClientURI(sgMongoClusterURI, destDboptions));
			return sgMongoClient.getDatabase(dbName);
		}
		context.getLogger().log("Reusing existing connection");
		return sgMongoClient.getDatabase(dbName);
	}

	private String getLastAlert(APIGatewayProxyRequestEvent input, Context context) {
		String userId = input.getPathParameters().get("userId");
		MongoDatabase db = getDbConnection(sgMongoDbName, context);
		MongoCollection coll = db.getCollection("useralerts");
		Bson query = new Document("userId", Integer.parseInt(userId));
		Object result = coll.find(query).sort(Sorts.descending("$natural")).limit(1).first();
		context.getLogger().log("Result: " + result);
		return new Gson().toJson(result);
	}

	private void init(Context context) {
		sgMongoClusterURI = System.getenv("SCALEGRID_MONGO_CLUSTER_URI");
		sgMongoDbName = System.getenv("SCALEGRID_MONGO_DB_NAME");
	}

}

एक sgMongoClient . घोषित करके यहां कनेक्शन पूलिंग हासिल की गई है हैंडलर फ़ंक्शन के बाहर चर। जब तक एक ही कंटेनर का पुन:उपयोग किया जाता है, तब तक हैंडलर विधि के बाहर घोषित वेरिएबल कॉल के दौरान आरंभीकृत रहते हैं। यह AWS लैम्ब्डा द्वारा समर्थित किसी भी अन्य प्रोग्रामिंग भाषा के लिए सही है।

Node.js ड्राइवर MongoDB कनेक्शन पूल

Node.js ड्राइवर के लिए, कनेक्शन वैरिएबल को ग्लोबल स्कोप में घोषित करना भी ट्रिक काम करेगा। हालांकि, एक विशेष सेटिंग है जिसके बिना कनेक्शन पूलिंग संभव नहीं है। वह पैरामीटर है callbackWaitsForEmptyEventLoop जो लैम्ब्डा के संदर्भ वस्तु से संबंधित है। इस गुण को गलत पर सेट करने से AWS लैम्ब्डा प्रक्रिया और किसी भी राज्य डेटा को फ्रीज कर देगा। यह कॉलबैक कॉल करने के तुरंत बाद किया जाता है, भले ही ईवेंट लूप में ईवेंट हों।

AWS लैम्ब्डा हैंडलर फ़ंक्शन में Node.js ड्राइवर का उपयोग करके MongoDB कनेक्शन पूल को सक्षम करने के लिए कोड यहां दिया गया है:


'use strict'

var MongoClient = require('mongodb').MongoClient;

let mongoDbConnectionPool = null;
let scalegridMongoURI = null;
let scalegridMongoDbName = null;

exports.handler = (event, context, callback) => {

    console.log('Received event:', JSON.stringify(event));
    console.log('remaining time =', context.getRemainingTimeInMillis());
    console.log('functionName =', context.functionName);
    console.log('AWSrequestID =', context.awsRequestId);
    console.log('logGroupName =', context.logGroupName);
    console.log('logStreamName =', context.logStreamName);
    console.log('clientContext =', context.clientContext);
   
    // This freezes node event loop when callback is invoked
    context.callbackWaitsForEmptyEventLoop = false;

    var mongoURIFromEnv = process.env['SCALEGRID_MONGO_CLUSTER_URI'];
    var mongoDbNameFromEnv = process.env['SCALEGRID_MONGO_DB_NAME'];
    if(!scalegridMongoURI) {
	if(mongoURIFromEnv){
		scalegridMongoURI = mongoURIFromEnv;
	} else {
		var errMsg = 'Scalegrid MongoDB cluster URI is not specified.';
		console.log(errMsg);
		var errResponse = prepareResponse(null, errMsg);
		return callback(errResponse);
	}			
    }

    if(!scalegridMongoDbName) {
	if(mongoDbNameFromEnv) {
                scalegridMongoDbName = mongoDbNameFromEnv;
	} else {
		var errMsg = 'Scalegrid MongoDB name not specified.';
		console.log(errMsg);
		var errResponse = prepareResponse(null, errMsg);
		return callback(errResponse);
	}
    }

    handleEvent(event, context, callback);
};


function getMongoDbConnection(uri) {

    if (mongoDbConnectionPool && mongoDbConnectionPool.isConnected(scalegridMongoDbName)) {
        console.log('Reusing the connection from pool');
        return Promise.resolve(mongoDbConnectionPool.db(scalegridMongoDbName));
    }

    console.log('Init the new connection pool');
    return MongoClient.connect(uri, { poolSize: 10 })
        .then(dbConnPool => { 
                            mongoDbConnectionPool = dbConnPool; 
                            return mongoDbConnectionPool.db(scalegridMongoDbName); 
                          });
}

function handleEvent(event, context, callback) {
    getMongoDbConnection(scalegridMongoURI)
        .then(dbConn => {
			console.log('retrieving userId from event.pathParameters');
			var userId = event.pathParameters.userId;
			getAlertForUser(dbConn, userId, context);
		})
        .then(response => {
            console.log('getAlertForUser response: ', response);
            callback(null, response);
        })
        .catch(err => {
            console.log('=> an error occurred: ', err);
            callback(prepareResponse(null, err));
        });
}

function getAlertForUser(dbConn, userId, context) {

    return dbConn.collection('useralerts').find({'userId': userId}).sort({$natural:1}).limit(1)
        .toArray()
        .then(docs => { return prepareResponse(docs, null);})
        .catch(err => { return prepareResponse(null, err); });
}

function prepareResponse(result, err) {
	if(err) {
		return { statusCode:500, body: err };
	} else {
		return { statusCode:200, body: result };
	}
}

AWS लैम्ब्डा कनेक्शन पूल विश्लेषण और अवलोकन

कनेक्शन पूल का उपयोग करने के प्रदर्शन और अनुकूलन को सत्यापित करने के लिए, हमने जावा और Node.js लैम्ब्डा दोनों कार्यों के लिए कुछ परीक्षण चलाए। एडब्ल्यूएस एपीआई गेटवे को एक ट्रिगर के रूप में उपयोग करते हुए, हमने प्रति पुनरावृत्ति 50 अनुरोधों के फटने में कार्यों को लागू किया और प्रत्येक पुनरावृत्ति में अनुरोध के लिए औसत प्रतिक्रिया समय निर्धारित किया। यह परीक्षण लैम्ब्डा फ़ंक्शन के लिए शुरू में कनेक्शन पूल का उपयोग किए बिना और बाद में कनेक्शन पूल के साथ दोहराया गया था।

ऊपर दिए गए ग्राफ़ प्रत्येक पुनरावृत्ति में अनुरोध के औसत प्रतिक्रिया समय का प्रतिनिधित्व करते हैं। आप यहां प्रतिक्रिया समय में अंतर देख सकते हैं जब डेटाबेस संचालन करने के लिए कनेक्शन पूल का उपयोग किया जाता है। कनेक्शन पूल का उपयोग करने का प्रतिक्रिया समय इस तथ्य के कारण काफी कम है कि कनेक्शन पूल एक बार प्रारंभ होता है और प्रत्येक डेटाबेस ऑपरेशन के लिए कनेक्शन खोलने और बंद करने के बजाय कनेक्शन का पुन:उपयोग करता है।

Java और Node.js लैम्ब्डा फ़ंक्शंस के बीच एकमात्र उल्लेखनीय अंतर कोल्ड स्टार्ट टाइम है।

कोल्ड स्टार्ट टाइम क्या है?

कोल्ड स्टार्ट टाइम एडब्ल्यूएस लैम्ब्डा फंक्शन द्वारा इनिशियलाइज़ेशन के लिए लिए गए समय को संदर्भित करता है। जब लैम्ब्डा फ़ंक्शन को अपना पहला अनुरोध प्राप्त होता है, तो यह कंटेनर और आवश्यक प्रक्रिया वातावरण को इनिशियलाइज़ करेगा। उपरोक्त ग्राफ़ में, अनुरोध 1 के प्रतिक्रिया समय में कोल्ड स्टार्ट टाइम शामिल है, जो AWS लैम्ब्डा फ़ंक्शन के लिए उपयोग की जाने वाली प्रोग्रामिंग भाषा के आधार पर काफी भिन्न है।

क्या मुझे ठंड शुरू होने के समय के बारे में चिंता करने की ज़रूरत है?

यदि आप लैम्ब्डा फ़ंक्शन के लिए एडब्ल्यूएस एपीआई गेटवे को ट्रिगर के रूप में उपयोग कर रहे हैं, तो आपको कोल्ड स्टार्ट टाइम को ध्यान में रखना चाहिए। यदि एडब्ल्यूएस लैम्ब्डा एकीकरण फ़ंक्शन दी गई समय सीमा में प्रारंभ नहीं किया गया है, तो एपीआई गेटवे प्रतिक्रिया त्रुटिपूर्ण होगी। एपीआई गेटवे इंटीग्रेशन टाइमआउट 50 मिलीसेकंड से लेकर 29 सेकंड तक होता है।

Java AWS लैम्ब्डा फ़ंक्शन के ग्राफ़ में, आप देख सकते हैं कि पहले अनुरोध में 29 सेकंड से अधिक समय लगा, इसलिए, API गेटवे प्रतिक्रिया त्रुटिपूर्ण हो गई। जावा का उपयोग करके लिखे गए AWS लैम्ब्डा फ़ंक्शन के लिए कोल्ड स्टार्ट टाइम अन्य समर्थित प्रोग्रामिंग भाषाओं की तुलना में अधिक है। इन ठंडे प्रारंभ समय के मुद्दों को हल करने के लिए, आप वास्तविक आमंत्रण से पहले प्रारंभिक अनुरोध को सक्रिय कर सकते हैं। दूसरा विकल्प क्लाइंट साइड पर पुनः प्रयास करना है। इस तरह, यदि अनुरोध ठंडे प्रारंभ समय के कारण विफल हो जाता है, तो पुन:प्रयास सफल होगा।

निष्क्रियता के दौरान AWS लैम्ब्डा फ़ंक्शन का क्या होता है?

हमारे परीक्षण में, हमने यह भी देखा कि AWS लैम्ब्डा होस्टिंग कंटेनरों को कुछ समय के लिए निष्क्रिय होने पर रोक दिया गया था। यह अंतराल 7 से 20 मिनट के बीच होता है। इसलिए, यदि आपके लैम्ब्डा फ़ंक्शन का अक्सर उपयोग नहीं किया जाता है, तो आपको या तो दिल की धड़कन के अनुरोधों को सक्रिय करके या क्लाइंट साइड पर पुनः प्रयास जोड़कर उन्हें जीवित रखने पर विचार करने की आवश्यकता है।

क्या होता है जब मैं लैम्ब्डा फ़ंक्शंस को समवर्ती रूप से आमंत्रित करता हूं?

यदि लैम्ब्डा फ़ंक्शन समवर्ती रूप से लागू होते हैं, तो लैम्ब्डा अनुरोध को पूरा करने के लिए कई कंटेनरों का उपयोग करेगा। डिफ़ॉल्ट रूप से, AWS लैम्ब्डा 1000 अनुरोधों की अनारक्षित समरूपता प्रदान करता है और किसी दिए गए लैम्ब्डा फ़ंक्शन के लिए कॉन्फ़िगर करने योग्य है।

यह वह जगह है जहाँ आपको कनेक्शन पूल आकार के बारे में सावधान रहने की आवश्यकता है क्योंकि समवर्ती अनुरोध बहुत अधिक कनेक्शन खोल सकते हैं। इसलिए, आपको अपने फ़ंक्शन के लिए कनेक्शन पूल आकार को इष्टतम रखना चाहिए। हालांकि, एक बार कंटेनर बंद हो जाने के बाद, MongoDB सर्वर से टाइमआउट के आधार पर कनेक्शन जारी किए जाएंगे।

AWS लैम्ब्डा कनेक्शन पूलिंग निष्कर्ष

लैम्ब्डा फ़ंक्शन स्टेटलेस और एसिंक्रोनस हैं, और डेटाबेस कनेक्शन पूल का उपयोग करके, आप इसमें एक स्थिति जोड़ पाएंगे। हालांकि, यह केवल तभी मदद करेगा जब कंटेनरों का पुन:उपयोग किया जाएगा, जिससे आप बहुत समय बचा पाएंगे। AWS EC2 का उपयोग करके कनेक्शन पूलिंग को प्रबंधित करना आसान है क्योंकि एक एकल इंस्टेंस बिना किसी समस्या के अपने कनेक्शन पूल की स्थिति को ट्रैक कर सकता है। इस प्रकार, AWS EC2 का उपयोग करने से डेटाबेस कनेक्शन समाप्त होने का जोखिम काफी कम हो जाता है। एडब्ल्यूएस लैम्ब्डा को बेहतर काम करने के लिए डिज़ाइन किया गया है जब यह सिर्फ एक एपीआई को हिट कर सकता है और उसे डेटाबेस इंजन से कनेक्ट नहीं करना पड़ता है।


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDB दस्तावेज़ों और संग्रहों को दृष्टिगत रूप से प्रबंधित करना

  2. नेस्टेड फ़ील्ड में MongoDB अद्यतन डेटा

  3. नेवला खोज (), परिणाम दस्तावेज़ों तक कैसे पहुँचें?

  4. मोंगो एकत्रीकरण कई मानों से मेल खाता है

  5. दस्तावेज़ों के नेस्टेड सरणी में एम्बेडेड दस्तावेज़ निकालें