node.js - გააზიარებს თუ არა AWS lambda (nodejs) მეხსიერებას სხვადასხვა გაშვებებს შორის?


მე მაქვს ეს ლამბდა ფუნქცია, რომელიც პასუხობს Http მოვლენას (get), მოთხოვნის გაგზავნისას მე ვიღებ წყვილ(headers) headerA და headerB.

ლამბდა დაწერილია nodejs/typescript-ში

განხორციელებისას მე მაქვს გლობალური ცვლადი, რომელიც განისაზღვრება, როგორც ობიექტების კოლექცია:

let storage:{[myIndex :typeofHeaderA]? : storageDrivers } = {}

როცა მე მივიღებ მოთხოვნას, მე ვდებ ჩემს კლასის ახალ ინსტანსს ზემოთ აღწერილ გლობალურ ვერში, „გეგმილ“ ინდექსზე, თუ ჯერ არ არის არსებული:

if(!storage[headerA]){
   storage[headerA] = new MyStorageDriver(headerB)
}

რაც მე განმიცდია არის ის, რომ, თუ გავითვალისწინებთ ორ განსხვავებულ მოთხოვნას, რომლებიც ერთმანეთს ახლოს არიან:

1-ე მოთხოვნა headerA1 headerB1

მეორე მოთხოვნა headerA1 headerB2

მეორე მოთხოვნის შემდეგ storage[headerA1] შეიცავს MyStorageDriver(headerB1)-ის ინტანსიას და არა MyStorageDriver(headerB2)-ის

მაგალითად, განსხვავებული მოთხოვნის Lambda შესრულების შემთხვევაში, გლობალური გრაფის მეხსიერება გაზიარებულია ან reused მოთხოვნებს შორის.

ეს არის მოსალოდნელი რამ AWS Lambda-სთან, თუ ეს სხვა რამაა, რაც დამიყვანა ამ მოულოდნელ ქცევამდე?

ჩემი არსებული გადაწყვეტილება (და იმისთვის, რომ ორმაგად დავიდასტურო ეს ქცევა, არის გლობალური ვარის შეცვლა შემდეგნაირად:

      let storage:{[myIndex :typeofHeaderB]? :{
                      [myIndex :typeofHeaderA]? : storageDrivers }
                  } = {}

და შემდეგ დაადგინი ასე მოთხოვნებზე:

     if(!storage[headerB]){storage[headerB]={}
     if(!storage[headerB][headerA]){
         storage[headerB][headerA] = new MyStorageDriver(headerB)
     }

პასუხი #1

კი, ეს ხდება და არა, არ უნდა დაყრდნოთ მასზე.

რაც ხდება, არის ის, რომ ყოველ ჯერზე, როდესაც ლამბდას მოქმედების მოთხოვნაა, AWS backend ეძებს რა არის ხელმისაწვდომი. თუ ამ ლამბდასთვის მიმდინარე გაშვებული კონტეინერი არ არსებობს, ის დაატრიალებს ერთს და შექმნის კონტეინერს, ლამბდას და შემდეგ გამოიყენებს მას. ლამბდას გამოძახებას ეწოდება "გამოწვევა". კონტეინერის გაშვებისა და ლამბდას ინიციალიზაციის პროცესს ეწოდება ცივი დაწყება და ცოტა პრობლემას წარმოადგენს - მას შეიძლება დასჭირდეს 15-30 წამზე მეტი, რაც დამოკიდებულია თქვენი ლამბდას და ფენების სირთულეზე.

შემდეგ ჯერზე, როცა AWS იწვევს იმ ლამბდას, თუ უკვე არსებული კონტეინერი ჯერ კიდევ მუშაობს, ის დაიცდება იმ კონტეინერის გადამუშავებას. ეს ცნობილია როგორც „ლამბდას თბილად შენახვა“, რათა ის იყოს შესაძლებელი გამოძახებისთვის ცივი სტარტის გარეშე, რამაც მნიშვნელოვნად სწრაფი რეაგირების დრო გამოიწვევს.

თუ საჭიროა რამდენიმე მოთხოვნის პასუხის გაცემა (მაგალითად: მასშტაბირება), ის დაამატებს დამატებით კონტეინერებს. ამას ეწოდება თანმიმდევრული შესრულებები - თუ დაათვალიერებთ თქვენი ლამბდას მეტრიკებს, შესაძლოა ნახოთ ათასობით გამოტანა (Invokes), მაგრამ მხოლოდ 3 ან 4 თანმიმდევრული შესრულება (Concurrent).

ლოგიკა, რომელსაც AWS იყენებს იმის შესახებ, როდის დააყენოს და როდის შეაჩეროს ერთდროული შესრულებები, ეფუძნება თქვენი ტრაფიკის პროგნოზირებად გაგებას + საჭიროებას + ნებისმიერ პარამეტრებს, რაც გაქვთ დანიშნული უზრუნველყოფილი ტევადობისთვის.

კრებული გამოყენებისას ნებისმიერი გამოძახების დროს, რომელიც იყენებს არსებულ კონტეინერს, გლობალური ცვლადები შენარჩუნდება - რადგან ეს იგივე გარემოა. ეს არის მიზეზი, რის გამოც გლობალური ცვლადები არ უნდა გამოიყენოთ Lambda-ს შესრულების დროს ნებისმიერი რამისთვის, რაც შეიძლება შეიცვალოს. თქვენ ვერ გაიგებთ კონკურენტულ შესრულებებს და რომ თქვენ იმავე კონტეინერში იყავით, როგორც წინა შესრულების დროს, და ვერ გაიგებთ, რომ ეს არ იქნება ერთ-ერთი.