Course-এর সূচি

11.3

CloudFront Functions বনাম Lambda@Edge

চারটা event point, দুটোর সীমা পাশাপাশি, আর কোন কাজে কোনটা মানায়।

20 মিনিট পড়া + Animation

টিপস: ডটেড-আন্ডারলাইন করা যেকোনো শব্দে ট্যাপ বা Hover করলে তার অর্থ দেখবে।

এই লেসন শেষে তুমি পারবে

  • Edge function কী, CDN-এর ভেতরে code চালানোর দরকার কেন পড়ে, আর origin-এর চেয়ে কোন সমস্যাগুলো এটা ভালো মেটায়, সেটা বোঝাতে।
  • CloudFront-এর চারটা event point-এর নাম বলতে, প্রতিটা ঠিক কখন চলে বলতে, আর cache hit, miss, origin-এর error বা function-এর নিজের বানানো response-এ কোনগুলো চলবে আগেই বলে দিতে।
  • আজকের সীমা ধরে CloudFront Functions আর Lambda@Edge-কে তুলনা করতে: runtime, scale, কতক্ষণ চলে, memory, package size, network আর body access, কোথায় চলে, আর দাম।
  • Redeploy ছাড়াই বদলানো যায় এমন setting-এর জন্য CloudFront KeyValueStore ব্যবহার করতে, আর নতুন origin modification helper-গুলো চিনতে।
  • Lambda@Edge ঠিকভাবে deploy করতে (us-east-1, নম্বর দেওয়া version, replication, যে Region-এ চলেছে সেখানে log), আর edge function থেকে আসা 502 আর 503 error ধরতে।
  • কোনো পরিস্থিতিতে ঠিক tool বেছে নিতে, সস্তা উত্তরগুলো সহ: viewer event-এর বদলে origin event, বা একেবারেই function ছাড়া।

#CDN-এর ভেতরে code

#Edge function জিনিসটা কী

CloudFront (লেসন ১১.১) তোমার content শত শত edge location-এ cache করে রাখে। বেশিরভাগ সময় সে শুধু bytes জমায় আর পাঠায়। কিন্তু আজকের অনেক site-এর পথের মাঝখানে একটু logic লাগে: পুরোনো link-কে নতুন page-এ পাঠানো, security header জোড়া, login token যাচাই, কোনো পরীক্ষার জন্য page-এর একটা সংস্করণ বেছে দেওয়া, ফোনের জন্য ছবি ছোট করা।

এসব origin-এ বসেও করা যায়। তখন এমন প্রতিটা request-কে origin-এর Region পর্যন্ত যেতে হয়, origin-কে সেই চাপ সামলানোর মতো বড় হতে হয়, আর এর অনেকটাই cache করা যায় না। Edge function হলো এমন code, যেটা তুমি লিখে একটা CloudFront distribution-এর সাথে জুড়ে দাও, যাতে সেটা viewer-এর কাছেই চলে, CDN-এর ভেতরে, cache-এর আগে বা পরে।

Slide-এ পুরো ব্যাপারটা কয়েক কথায় বলা আছে, নিজের ভাষায় মনে রাখার মতো:

  • Code জোড়া হয় distribution-এর একটা cache behaviour-এর সাথে; CloudFront সেটা তোমার user-দের কাছে চালায়, তাই বাড়তি latency খুবই সামান্য।
  • সামলানোর মতো কোনো server নেই, Region ধরে ধরে deploy করারও কিছু নেই: CloudFront নিজেই code সব জায়গায় পৌঁছে দেয়।
  • পুরোপুরি serverless, আর যতটুকু চলে ততটুকুরই দাম।
  • উদ্দেশ্য একটাই: CDN যা পৌঁছে দেয়, সেটাকে নিজের মতো সাজানো।

CloudFront দুই রকম দেয়: CloudFront Functions আর Lambda@Edge। দূর থেকে দুটোকে একই রকম মনে হয়, কাছে গেলে দেখা যায় পুরো আলাদা।

#মানুষ এগুলো দিয়ে কী করে

Edge function সাধারণত কোন কোন কাজে লাগে, AWS তার একটা তালিকা দেয়। নিচে প্রতিটার সাথে ঢাকার একটা online shop, Haatbazar-এর রোজকার উদাহরণ দেওয়া হলো; shop-টা d111111abcdef8.cloudfront.net দিয়ে shop.example.com-এ চলে:

কাজHaatbazar-এর উদাহরণসাধারণত
Website-এর security আর privacyHSTS আর clickjacking ঠেকানোর header জোড়া; Server header সরিয়ে দেওয়াCloudFront Functions (বা response headers policy)
Edge-এ dynamic web applicationএকটা cookie আর database থেকে পড়ে ছোট একটা নিজস্ব banner বানানোLambda@Edge
Search engine optimisationএকই page-এর নানা URL-কে একটা canonical URL-এ redirect; crawler-কে আগে থেকে render করা page দেওয়াRedirect-এ CloudFront Functions, prerender-এ Lambda@Edge
বুদ্ধি খাটিয়ে origin বেছে পাঠানোWholesale ক্রেতাদের অন্য catalogue origin-এ পাঠানোযেকোনোটা (নিচে origin modification দেখো)
Edge-এই bot ঠেকানোবৈধ signed cookie ছাড়া আসা request আটকানোCloudFront Functions; আসল bot management-এর জন্য AWS WAF Bot Control
সাথে সাথে ছবি বদলানোফোনের জন্য পণ্যের ৪ MB-র ছবিকে ৪০০ pixel-এ ছোট করাLambda@Edge
A/B testing১০% ক্রেতাকে নতুন checkout দেখানোKeyValueStore সহ CloudFront Functions
User-এর authentication আর authorisationসদস্যদের price list-এর আগে একটা JWT যাচাইCloudFront Functions; যাচাইয়ের জন্য identity service-কে call করতে হলে Lambda@Edge
User-কে অগ্রাধিকার দেওয়াঈদের sale-এ login করা ক্রেতাদের waiting room পার করে দেওয়াযেকোনোটা
User tracking আর analyticsপ্রথমবার আসার সময় একটা visitor ID cookie বসানোCloudFront Functions

#চারটা event point

CloudFront দিয়ে যাওয়া প্রতিটা request চারটা জায়গা পার হয়, যেখানে code জোড়া যায়। পরীক্ষায় সবচেয়ে বেশি প্রশ্ন আসে এই অংশ থেকেই।

  1. Viewer request

    CloudFront যখন viewer-এর কাছ থেকে request পায়, তখন চলে, cache দেখার আগেই। সে যা বদলায় (URL, header, cookie, query string), তা দিয়েই cache key তৈরি হয়। চাইলে সে নিজেই উত্তর দিয়ে দিতে পারে, যেমন একটা redirect বা 401। চলে প্রতিটা request-এ, hit হোক বা miss।

  2. Origin request

    চলে কেবল তখন, যখন CloudFront request-টা origin-এ পাঠাতে যাচ্ছে, মানে cache miss হলে (বা object-এর মেয়াদ ফুরোলে)। Hit হলে একেবারেই চলে না। Origin বেছে নেওয়া, একটা গোপন header জোড়া, বা এমন কিছু খোঁজার জন্য ভালো, যার ফল পরে cache হবে।

  3. Origin response

    CloudFront origin-এর উত্তর পাওয়ার পরে আর সেটা cache করার আগে চলে। Origin error দিলেও চলে, তাই একটা 404 বা 503-কে বদলে দিতে পারে। এখানে যা বদলায়, সবার জন্য সেটাই cache হয়।

  4. Viewer response

    CloudFront viewer-কে response ফেরত দেওয়ার ঠিক আগে চলে, hit আর miss দুটোতেই। এখানের বদল প্রত্যেক viewer-এর নিজের, cache হয় না; যেমন একটা cookie বসানো।

দুই ধরনের মূল তফাতটা শুরু হয় ঠিক এখান থেকেই:

  • CloudFront Functions চলতে পারে শুধু viewer request আর viewer response-এ।
  • Lambda@Edge চলতে পারে চারটাতেই।

একটা miss, একটা hit, আর যেসব ক্ষেত্রে কোনো trigger বাদ পড়ে, দেখে নাও:

একটা request-এর পথে চারটা event point

ওপরের সারি: request viewer থেকে origin-এর দিকে যায়। নিচের সারি: response ফিরে আসে। Viewer-এর দুটো event-এ দুই ধরনের function-ই বসানো যায়; origin-এর দুটো event-এ বসে শুধু Lambda@Edge, আর সেগুলো চলে কেবল তখন, যখন CloudFront সত্যিই origin-এ যায়।

পরিস্থিতি

এই edge-এ এখনো কেউ চায়নি এমন একটা product page প্রথম ক্রেতা চাইল।

Viewerঢাকায়
Viewer requestযেকোনো ধরনচলে
Edge cachehit না miss?
Origin requestশুধু Lambda@Edge
Originap-south-1
Origin responseশুধু Lambda@Edge
Viewer responseযেকোনো ধরন
GET /product/42
ধাপ 1 / 8
1

GET /product/42 edge location-এ পৌঁছাল। সবার আগে চলে viewer request function, CloudFront cache-এ খোঁজার আগেই। তাই সে URL, header বা cookie বদলে cache key-টাই বদলে দিতে পারে, কিংবা নিজেই উত্তর দিয়ে দিতে পারে।

#কখন একটা trigger চলে না

সব ঠিকঠাক চললে হিসাব সহজ। ব্যতিক্রমগুলোতেই production-এর চমক আর পরীক্ষার ভুল বিকল্পগুলো লুকিয়ে থাকে:

Triggerচলে না যখন…
Viewer requestCloudFront নিজেই HTTP থেকে HTTPS-এ redirect করে (viewer protocol policy); CloudFront একটা custom error page আনে
Origin requestObject cache-এ আছে আর এখনো তাজা (একটা hit)
Origin responseObject এসেছে cache থেকে; response-টা বানিয়েছে একটা origin request function
Viewer responseOrigin ৪০০ বা তার বেশি দিয়েছে; custom error page ফেরত যাচ্ছে; response-টা বানিয়েছে একটা viewer request function; HTTP থেকে HTTPS-এর redirect

Design-এ এর দুটো ফল খুব জরুরি। এক, origin event-এর logic চলে শুধু miss-এ: ৯৫% hit ratio হলে প্রতি ২০টা request-এ ১টায় চলে, দামও দিতে হয় ২০টায় ১টার। দুই, প্রতিটা response-এ, error সহ, যা লাগবেই, সেটা শুধু viewer response function-এ রেখো না; response headers policy error response-ও ঢেকে দেয়।

#প্রতি event-এ একটা function, আর দুই ধরন একসাথে কীভাবে চলে

প্রতিটা cache behaviour-এ প্রতি event type-এ একটা function বসে, তাই সব মিলিয়ে সর্বোচ্চ চারটা। দুই ধরন মেশানো যায়, একটা নিয়ম মেনে: একই behaviour-এর viewer event-এ CloudFront Functions আর Lambda@Edge একসাথে চলে না। তাই “viewer request-এ CloudFront Function + origin request-এ Lambda@Edge” চলে, আর এটা খুব চেনা নকশা; কিন্তু “viewer request-এ CloudFront Function + viewer response-এ Lambda@Edge” চলে না।

প্রতিটা function নিজের চলার সময়টুকু request-এর সাথে যোগও করে: CloudFront সামনে এগোনোর আগে তার শেষ হওয়ার অপেক্ষা করে। এই কারণেই viewer request function, যেটা প্রতিটা request-এ চলে, তাকে দ্রুত হতেই হবে।

নিজেকে যাচাই করোপ্রশ্ন

Haatbazar-এর product page-এর cache hit ratio ৯৬%। একটা function একটা header জোড়ে; origin-এ পৌঁছানো প্রতিটা request-এ একবার চললেই চলবে, আর তার ফল cache হওয়া উচিত। এটা কোন event-এ বসবে?

#CloudFront Functions: সাইকেল

#এগুলো কী

CloudFront Functions হলো ছোট ছোট JavaScript function, যেগুলো edge location-এর ভেতরেই, request-এর পথের মধ্যে, খুব হালকা একটা আলাদা করা runtime-এ চলে। এটা CloudFront-এর নিজের feature: তুমি CloudFront console বা API-তেই এগুলো লেখো, test করো আর publish করো; Lambda-র কোনো ভূমিকা নেই, Region বাছারও কিছু নেই।

এদের বিশেষত্ব হলো সব কিছুতে কড়া সীমা:

  • ভাষা: শুধু JavaScript, একটা সীমিত runtime-এ (language standard-এর ৫.১ version, সাথে বাছাই করা কিছু নতুন feature; runtime 2.0-তে আসে const, let, async/await, একটা crypto module আর KeyValueStore)।
  • কতক্ষণ চলে: sub-millisecond। CloudFront এটা মাপে compute utilization দিয়ে, অনুমোদিত সময়ের ০ থেকে ১০০%; কোনো function সীমা ছাড়ালে থামিয়ে দেওয়া হয়, আর viewer পায় error।
  • Memory: 2 MB। Code size: 10 KB, ভেতরে যা data বসাবে সব মিলিয়ে।
  • Network access নেই, file system নেই, request body নেই, timer নেই, eval নেই। Function যা জানে, সবই আসে request থেকে (method, URI, query string, header, cookie, viewer-এর IP) আর তার KeyValueStore থেকে।
  • Geolocation আর device header, যেমন CloudFront-Viewer-Country, পাওয়া যায় (cache বা origin request policy-তে যোগ করলে)।
  • Scale: সেকেন্ডে লাখ লাখ request, সাথে সাথেই।
  • Event: শুধু viewer request আর viewer response।
  • দাম: প্রতি ১০ লাখ invocation-এ $0.10, duration-এর কোনো দাম নেই, আর মাসের প্রথম ২০ লাখ বিনা পয়সায়। নোটের “প্রায় ৬ গুণ সস্তা” কথাটা এখান থেকেই: Lambda@Edge duration ধরার আগেই প্রতি ১০ লাখ request-এ নেয় $0.60।

#যে কাজের জন্য এগুলো বানানো

AWS চারটা কাজের নাম বলে, আর নোটের সাথে হুবহু মেলে:

  1. Cache key normalisation। /Product/42?utm_source=fb&fbclid=x9 আর এরকম আরও শখানেক URL-কে /product/42 বানিয়ে দেওয়া, যাতে সবাই একটাই cache করা কপি ভাগ করে নেয়। Hit ratio বাড়ে, origin-এর চাপ কমে।
  2. Header manipulation। Request বা response-এর header জোড়া, বদলানো বা মুছে ফেলা: origin-এর জন্য True-Client-IP জোড়া, security header বসানো, যে header ভেতরের খবর ফাঁস করে সেগুলো সরানো।
  3. URL redirect আর rewrite। Path অটুট রেখে oldsite.example থেকে newsite.example-এ পাঠানো, বা S3 origin-এর জন্য /about-কে /about/index.html বানানো।
  4. Request authorisation। JWT-এর মতো hash করা token যাচাই করা (signature আর মেয়াদ), আর কাউকে call না করেই edge-এ 401 দিয়ে দেওয়া।

পুরো একটা redirect function মাত্র কয়েক লাইনের:

function handler(event) {
  var req = event.request;
  if (req.headers.host && req.headers.host.value === 'oldsite.example') {
    return {
      statusCode: 301,
      statusDescription: 'Moved Permanently',
      headers: { location: { value: 'https://newsite.example' + req.uri } },
    };
  }
  return req; // not the old host: carry on to the cache
}

Request ফেরত দিলে সেটা সামনে এগোয়; একটা response object ফেরত দিলে viewer সাথে সাথে উত্তর পেয়ে যায়। Viewer response function পায় response (আর request-ও), আর বদলে নিয়ে response-টাই ফেরত দেয়।

#KeyValueStore: redeploy ছাড়াই setting

১০ KB-র একটা function-এ ৫,০০০ পুরোনো URL-এর তালিকা আঁটে না, আর একটা পরীক্ষা ১০% থেকে ৫০% করতে code বদলানো ধীর আর ঝুঁকির কাজ। CloudFront KeyValueStore দুটো সমস্যাই মেটায়: global, খুব কম latency-র একটা key-value datastore, যেটা একটা CloudFront Function edge-এই পড়তে পারে।

  • তুমি একটা store বানাও, console, CLI বা API দিয়ে key যোগ করো, আর function-এর সাথে জুড়ে দাও (প্রতি function-এ একটা store; একটা store সর্বোচ্চ ১০০টা function-কে সেবা দিতে পারে)।
  • Function value পড়ে await kvs.get(key) দিয়ে (runtime 2.0)। পড়াটা edge-এর স্থানীয়, কোনো network call না।
  • বদল কয়েক সেকেন্ডের মধ্যে সব edge location-এ পৌঁছে যায়, function আবার deploy করতে হয় না।
  • সীমা: key সর্বোচ্চ ৫১২ byte, value সর্বোচ্চ ১ KB, প্রতি store 5 MB। পড়ার দাম প্রতি ১০ লাখে $0.03 (মাসে ২০ লাখ বিনা পয়সায়); অন্য API call প্রতি ১,০০০-এ $1।
  • Function-এর দিক থেকে এটা শুধু পড়া যায়, আর ব্যবহার করতে পারে শুধু CloudFront Functions, Lambda@Edge না।

সাধারণত এতে থাকে: redirect-এর তালিকা, A/B-র ভাগ আর feature flag, partner ID-র allow list, JWT-র signature যাচাইয়ের গোপন key।

#CloudFront Function থেকে origin বেছে নেওয়া

২০২৪-এর শেষ থেকে viewer request-এর একটা CloudFront Function (runtime 2.0) helper method দিয়ে request-এর origin-ও বদলাতে পারে: cf.updateRequestOrigin() (origin-এর domain, timeout, header, OAC… বদলানো বা বসানো), cf.selectRequestOriginById() (distribution-এ আগে থেকে থাকা অন্য origin-এ সরে যাওয়া) আর cf.createRequestOriginGroup() (চলতে চলতেই একটা failover জোড়া বানানো)। আগে এটা পারত শুধু origin request-এর Lambda@Edge।

খরচের একটা হিসাব AWS নিজেই মনে করিয়ে দেয়: viewer request function চলে প্রতিটা request-এ, আর Lambda@Edge-এর origin request function চলে শুধু miss-এ। খুব বেশি cache হয় এমন content-এ origin বেছে দেওয়ার জন্য Lambda@Edge-ই সস্তা পড়তে পারে। পরীক্ষার জন্য, network-এ খুঁজে “dynamic origin selection” এখনো Lambda@Edge-এর দিকেই দেখায়; CloudFront Functions-এর helper-গুলো একটা ভালো পাশের কথা।

চেনা কাজগুলো দেখো, আর দেখো কোন সীমার কারণে কাজ অন্য জায়গায় চলে যায়:

কাজের মাঝে CloudFront Functions

Edge location-এ প্রতিটা request-এ ছোট আর দ্রুত কাজ: redirect, cache key পরিষ্কার করা, header, KeyValueStore থেকে পড়া A/B ভাগ, token যাচাই। তারপর এমন দুটো কাজ, যা CloudFront Function পারে না।

পরিস্থিতি

Shop oldsite.example থেকে newsite.example-এ সরে গেছে; পুরোনো link সব জায়গায় ছড়ানো।

Viewerbrowser
CloudFront Functionedge-এ
KeyValueStoreশুধু পড়া
Edge cache
Originap-south-1
GET oldsite.example/eid-sale
ধাপ 1 / 3
1

Facebook post-এর একটা পুরোনো link। Distribution দুটো নামই serve করে, আর behaviour-এ একটা viewer request function লাগানো।

#Lambda@Edge: স্পোর্টস কার

#এটা কী

Lambda@Edge হলো AWS Lambda-রই একটা বাড়তি রূপ (Lambda বিস্তারিত আসবে chapter ১৫, Lambda basics-এ)। এই লেসনের জন্য এটুকু জানলেই চলবে: Lambda function হলো এমন code, যেটা কোনো event এলে AWS চালায়, প্রতি request আর চলার প্রতি millisecond-এর হিসাবে দাম, আর একটা IAM execution role তাকে অনুমতি দেয়। Lambda@Edge এমন একটা function নিয়ে CloudFront-এর event দিয়ে তাকে চালানোর ব্যবস্থা করে।

  • ভাষা: Node.js আর Python, সাথে তুমি যে library জুড়ে দাও, AWS SDK সহ।
  • Event: চারটাই: viewer request, viewer response, origin request, origin response।
  • কতক্ষণ চলে: viewer event-এ সর্বোচ্চ ৫ সেকেন্ড, origin event-এ ৩০ সেকেন্ড।
  • Memory: viewer event-এ 128 MB; origin event-এ সর্বোচ্চ 10,240 MB (10 GB), memory-র সাথে CPU-ও বাড়ে।
  • Package size: compress করা অবস্থায় সর্বোচ্চ 50 MB, আজ দুই ধরনের event-এই (আগে viewer event-এ ছিল 1 MB)।
  • Network access: আছে। DynamoDB, S3, যেকোনো AWS service বা internet-এর যেকোনো API-কে call করতে পারে।
  • File system (/tmp) আর request body access: আছে। Body দেওয়া হয় শুধু include body-তে টিক দিলে; সেটা আসে base64 করা অবস্থায়, viewer request-এ ৪০ KB আর origin request-এ ১ MB-তে কেটে।
  • Geolocation আর device header: শুধু origin event-এ (CloudFront এগুলো জোড়ে viewer request-এর পরে)।
  • Scale: Region প্রতি সেকেন্ডে মোটামুটি ১০,০০০ request পর্যন্ত, আর Region-এর Lambda concurrency quota (default ১,০০০) সে তোমার অন্য Lambda function-গুলোর সাথে ভাগ করে নেয়।
  • দাম: প্রতি ১০ লাখ request-এ $0.60, সাথে চলার সময়ের জন্য প্রতি GB-second-এ $0.00005001, প্রতি millisecond ধরে মাপা। কোনো free tier নেই।

#কোথায় চলে, আর সেখানে পৌঁছায় কীভাবে

Lambda@Edge function বানানো যায় শুধু US East (N. Virginia), us-east-1-এ। তুমি একটা নম্বর দেওয়া version publish করো (কখনো $LATEST বা alias না), আর সেই version-এর ARN-কে একটা cache behaviour আর একটা event-এর সাথে জুড়ে দাও। তারপর CloudFront function-টাকে সারা পৃথিবীর AWS Region-এ replicate করে, এতে কয়েক মিনিট লাগে।

Event এলে function চলে, যে edge location request পেয়েছে, তার সবচেয়ে কাছের AWS Region-এ: Regional Edge Cache-এর (লেসন ১১.১) একই স্তরে, edge location-এর ভেতরে না। এটা CloudFront Function-এর চেয়ে viewer থেকে একটু দূরে, আর viewer event-এর Lambda@Edge বেশি latency যোগ করার এটাও একটা কারণ।

এর দুটো হাতে-কলমে ফল:

  • Log জমে যেখানে function চলেছে সেখানে। CloudWatch Logs-এ /aws/lambda/us-east-1.<function-name> নামের একটা log group তৈরি হয় প্রতিটা Region-এ, যেখানে সে চলেছে। ঢাকার একজন viewer-এর log যায় ap-south-1-এ (মুম্বাই), us-east-1-এ না।
  • মুছতে ধৈর্য লাগে। Replica থাকা পর্যন্ত function মোছা যায় না: প্রতিটা distribution থেকে সরাও, CloudFront replica মুছে ফেলা পর্যন্ত অপেক্ষা করো (কয়েক ঘণ্টাও লাগতে পারে), তারপর মোছো।

Lambda-র কিছু feature edge-এ চলে না: environment variable, VPC access, layer, arm64 architecture, container image, dead-letter queue, X-Ray, provisioned concurrency, আর 512 MB-র বেশি ephemeral storage। Execution role-কে lambda.amazonaws.com আর edgelambda.amazonaws.com দুজনকেই বিশ্বাস করতে হবে।

Lambda@Edge: লেখা us-east-1-এ, চলে সব জায়গায়

Function একবারই বানাও US East (N. Virginia)-তে। CloudFront একটা নম্বর দেওয়া version সারা পৃথিবীর AWS Region-এ copy করে, আর প্রত্যেক viewer-এর edge location-এর সবচেয়ে কাছেরটায় চালায়।

পরিস্থিতি

Shop-এর প্রথম Lambda@Edge function চালু হচ্ছে।

us-east-1
ap-south-1
eu-west-2
Developer
edge-fn:3version 3
CloudFrontdistribution
Viewerঢাকায়
create, Node.js
ধাপ 1 / 5
1

Developer function-টা বানায় us-east-1-এ, একমাত্র Region যেখানে Lambda@Edge function বানানো যায়। এর execution role-কে lambda.amazonaws.com আর edgelambda.amazonaws.com দুজনকেই বিশ্বাস করতে হবে।

#যে কাজের জন্য এটা বানানো

Lambda@Edge-এর জন্য AWS-এর তালিকাটা যেন CloudFront Functions-এর সীমাগুলোর আয়না:

  • যে function চলতে কয়েক millisecond বা তার বেশি নেয়;
  • যার CPU বা memory বাড়ানো-কমানো দরকার;
  • যে code third-party library-র ওপর নির্ভর করে, অন্য AWS service-এর জন্য AWS SDK সহ;
  • বাইরের service ব্যবহার করতে যার network access লাগে;
  • যার file system access বা HTTP request-এর body লাগে।

নোটের ভাষায় এর মানে:

  • Dynamic content তৈরি: প্রতি request-এ একটা page বা তার অংশ বানানো, যেমন ক্রেতার segment দেখে তার জন্য একটা offer।
  • বাইরের API আর database call: third-party service-এ session খোঁজা, বা DynamoDB-তে user-এর tier দেখা (exam trick ২)।
  • ছবি optimise করা: device-এর screen দেখে সাথে সাথে ছবি ছোট করা, কোনো মাপ না থাকলে origin response-এ, আর ফলটা রেখে দেওয়া।

কাজগুলো দেখো, দেখো একটা hit কীভাবে function-কে পুরো এড়িয়ে যায়, আর ধীরগতি কী ঘটায়:

কাজের মাঝে Lambda@Edge

যে কাজে আসল Lambda function লাগে: origin-এর আগে DynamoDB-তে খোঁজা, miss-এ ছবি ছোট করা, request body যাচাই। তারপর hit হলে কী হয়, আর Lambda@Edge ধীর হলে বা throttle হলে কী হয়।

পরিস্থিতি

Wholesale ক্রেতারা অন্য একটা catalogue origin পায়; কে কোথায় যাবে সেটা DynamoDB-তে লেখা।

Viewer
Edge cachemiss
Lambda@Edgeকাছের Region
DynamoDBglobal table
Originap-south-1
GET /catalogue (cookie: shop=17)
ধাপ 1 / 6
1

Cache key-তে shop cookie আছে, তাই প্রতিটা দোকানের আলাদা cache করা catalogue। এটা এখনো cache-এ নেই: miss।

#পাশাপাশি তুলনা

এই ছকে আজকের AWS সীমা ধরা হয়েছে; নোট আর slide-এর পুরোনো মান শেষ কলামে ঠিক করে দেওয়া আছে।

CloudFront FunctionsLambda@Edgeনোট/slide-এর সংশোধন
Runtimeশুধু JavaScriptNode.js আর Python—
EventViewer request, viewer responseচারটাই—
কোথায় চলেEdge location (viewer-এর সবচেয়ে কাছে)Edge location-এর সবচেয়ে কাছের AWS Region (Regional Edge Cache-এর স্তর)নোটে ছিল “Regional Edge Cache”; একই স্তর, আরও ঠিক করে বললে সবচেয়ে কাছের Region
Scaleসেকেন্ডে লাখ লাখ requestRegion প্রতি সেকেন্ডে প্রায় ১০,০০০ পর্যন্তSlide-এ “হাজার হাজার”; সেটাই quota
সর্বোচ্চ সময়Sub-millisecondViewer-এ ৫ সেকেন্ড, origin-এ ৩০ সেকেন্ডনোটের “৫ থেকে ৩০ সেকেন্ড” = viewer বনাম origin; slide-এর “৫–১০ সেকেন্ড” পুরোনো
সর্বোচ্চ memory2 MBViewer-এ 128 MB, origin-এ 10 GB পর্যন্ত—
Code + library10 KB50 MB (viewer আর origin দুটোতেই)নোটের “50 MB” ঠিক; slide-এর “1 MB – 50 MB” হলো viewer-এর পুরোনো সীমা
Network, file systemনেইআছে—
Request bodyনেইআছে (include body; viewer-এ ৪০ KB, origin-এ ১ MB)—
Geolocation/device headerআছেশুধু origin event-এ—
KeyValueStoreআছে (runtime 2.0)নেই—
CloudFront-এর ভেতরেই বানানো আর testহ্যাঁনা (Lambda-তে, us-east-1-এ)—
দামপ্রতি ১০ লাখে $0.10, মাসে ২০ লাখ বিনা পয়সায়প্রতি ১০ লাখে $0.60 + GB-second, free tier নেই“প্রায় ৬ গুণ সস্তা” শুধু request-এর দাম ধরে

CloudFront FunctionsLambda@Edge

বেছে নাও যখন কাজটা ছোট আর প্রতিটা request-এ চলে: redirect আর rewrite, cache key normalisation, header বদল, JWT যাচাই, KeyValueStore থেকে A/B ভাগ, viewer-এর দেশ দেখে logic।

পরীক্ষার শব্দ: sub-millisecond, lightweight, highest scale, lowest latency, lowest cost, URL redirect, header manipulation, cache key।

বেছে নাও যখন কাজটায় আরও কিছু লাগে: DynamoDB বা কোনো API-কে call, request body, একটা library বা AWS SDK, কয়েক millisecond-এর বেশি সময়, Python, বা origin request/response event।

পরীক্ষার শব্দ: query a database at the edge, external network call, heavy computation, image resize, modify the request before it reaches the origin।

হিসাবগুলো নিজে মিলিয়ে দেখো। কাজটার কী লাগে টিক দাও, বা একটা উদাহরণ থেকে শুরু করো:

কোন edge function মানায়?

কাজটার কী কী লাগে টিক দাও, বা একটা উদাহরণ থেকে শুরু করো। রায়টা AWS-এর তুলনার ছক মেনে আসে, আর বলে দেয় কোন চাহিদাটা সিদ্ধান্ত নিল।

উদাহরণ

কাজটার কী লাগে

রায় দেখতে অন্তত একটা চাহিদায় টিক দাও।

#খরচ কত, আর event কেন জরুরি

Code কোথায় চলে, সেটাই ঠিক করে কতবার দাম দেবে। ধরো Haatbazar-এর মাসে ১০ কোটি request, hit ratio ৯০%, আর function চলে ৫ ms, 128 MB-তে:

  • Viewer request-এ CloudFront Function: ১০ কোটি invocation, ২০ লাখ বিনা পয়সার বাদ দিয়ে = ৯ কোটি ৮০ লাখ × প্রতি ১০ লাখে $0.10 = $9.80।
  • Viewer request-এ Lambda@Edge: ১০ কোটি × প্রতি ১০ লাখে $0.60 = $60, সাথে ১০ কোটি × ০.০০৫ সেকেন্ড × ০.১২৫ GB = ৬২,৫০০ GB-s × $0.00005001 ≈ $3.13, মোট ≈ $63।
  • Origin request-এ Lambda@Edge: শুধু ১ কোটি miss: $6 + $0.31 ≈ $6.31।

মানে সাইকেল প্রতিবার চলায় সবচেয়ে সস্তা, কিন্তু origin event-এ রাখা স্পোর্টস কার আরও সস্তা পড়তে পারে, কারণ সে চলে দশ গুণ কম। সংখ্যাগুলো বদলে দেখো:

Edge-এর কাজটার খরচ কত?

Traffic আর cache hit ratio বেছে নাও। একই কাজের দাম তিনভাবে হিসাব করা হলো: কোথায় চলে, সেটাই ঠিক করে কতবার দাম দেবে।

মাসে request (মিলিয়ন)

Cache hit ratio

Lambda@Edge-এর গড় সময়

Lambda@Edge memory

CloudFront Function, viewer request$9.80 প্রতি মাসে

100M বার চলে (প্রতিটা request)

Lambda@Edge, viewer request$63.13 প্রতি মাসে

100M বার চলে (প্রতিটা request)

Lambda@Edge, origin request$6.31 প্রতি মাসেসবচেয়ে সস্তা

10M বার চলে (শুধু cache miss)

তালিকার দাম; Lambda@Edge-এর কোনো free tier নেই, CloudFront Function-এর মাসে ২০ লাখ invocation বিনা পয়সায়। CloudFront-এর নিজের data transfer আর request-এর দাম তিনটাতেই সমান, তাই বাদ রাখা হলো। CloudFront Function শুধু হালকা কাজ পারে, তাই কাজ যখন এমনিতেই ভারী, তখন তৃতীয় সারিটাই আসল।

#কোথায় গিয়ে ভাঙে

লক্ষণসম্ভাব্য কারণসমাধান
কিছু বা সব viewer পায় 503Function error ছুড়েছে বা সময় পেরিয়েছে (Lambda@Edge: ৫ / ৩০ সেকেন্ড), বা CloudFront Function তার compute বাজেট ছাড়িয়েছেTest করো (test-function, compute utilization), error ধরো, network call-এ ছোট timeout আর একটা বিকল্প উত্তর রাখো
শুধু ভিড়ের সময় 503, Lambda@EdgeThrottle: Region-এর Lambda concurrency বা সেকেন্ডে ১০,০০০ request-এর quotaযেসব Region থেকে viewer আসে সেখানে concurrency quota বাড়াও; কাজ origin event-এ সরাও; CloudFront Function ব্যবহার করো
Deploy-এর ঠিক পরে 502Function ভুল response দিয়েছে: নিষিদ্ধ header (Connection, Keep-Alive…), read-only header বদলানো, সীমার বেশি body (viewer-এ ৪০ KB, origin-এ ১ MB), বা viewer request function CloudFront-Viewer-Country জুড়েছেসীমার মধ্যে থেকে শুধু অনুমোদিত field ফেরত দাও
Origin request function “কখনো চলে না”Object-গুলো cache hitএটাই হওয়ার কথা; প্রতিবার চলতেই হলে viewer request ব্যবহার করো
Error page-এ security header নেইStatus ৪০০ বা বেশি হলে viewer response বাদ পড়েResponse headers policy ব্যবহার করো, বা origin response-এ বসাও
Viewer response status বদলাতে পারে নাLambda@Edge-এর viewer response function status code বদলাতে পারে নাOrigin response-এ করো, বা viewer request-এ response বানাও
জোড়ার সময় function তালিকায় নেইLambda function us-east-1-এর বাইরে বানানো, বা $LATEST/alias বাছা হয়েছেus-east-1-এ বানাও আর একটা version publish করো
Lambda@Edge-এর “কোনো log নেই”খোঁজা হচ্ছে us-east-1-এViewer-দের কাছের Region-এ খোঁজো: /aws/lambda/us-east-1.<name>
অন্য user-দের কাছে ভুল content cache হয়ে যাচ্ছেViewer request function এমন header বা cookie ধরে response বদলাচ্ছে, যেটা cache key-তে নেইওই value cache key-তে ঢোকাও (cache policy), বা URI বদলাও যাতে key আলাদা হয়
Lambda function মোছা যাচ্ছে নাReplica এখনো আছেসব association সরাও, replica চলে যাওয়া পর্যন্ত অপেক্ষা করো, তারপর মোছো

#System design-এ edge function

  • Serverless সদর দরজা। S3-এ static site, সামনে OAC সহ CloudFront (লেসন ১০.৩ আর ১১.১), redirect, পরিষ্কার URL আর security-র জন্য একটা CloudFront Function, আর আসল API থাকে API Gateway আর Lambda-তে (chapter ১৫)। কোথাও কোনো server নেই।
  • Origin-কে আগলে রাখা। খারাপ token, মাপের চেয়ে বড় request আর আবর্জনা path edge-এই বাতিল করো, যাতে origin শুধু কাজের জিনিসটুকু দেখে। হামলার ধরনের জন্য (SQL injection, XSS, rate limit, bot) হাতে নিয়ম না লিখে distribution-এ AWS WAF ব্যবহার করো (লেসন ১১.২)।
  • Hit ratio বাড়ানো। CloudFront Function দিয়ে cache key normalise করো; পুরো stack-এ প্রায়ই এটাই সবচেয়ে সস্তায় গতি বাড়ানোর উপায়।
  • Cache না হারিয়েই personalise। Segment-টা (দেশ, device, A/B group, দোকানের tier) cache key-তে ঢোকাও, যাতে প্রতিটা segment একবার cache হয়, প্রতিটা page origin-এ বানাতে না হয়।
  • Origin আর Region-এর মধ্যে বেছে পাঠানো। দেশ দেখে, DynamoDB থেকে user-এর tier দেখে, বা KeyValueStore-এর একটা ভার দেখে origin বেছে নাও। শুধু availability-র failover-এর জন্য origin group-এ (লেসন ১১.১) কোনো code লাগে না; TCP/UDP-র গতি আর static IP-র জন্য Global Accelerator দেখো (লেসন ১১.৪)।
  • কখন ব্যবহার করবে না, সেটাও জানো। স্থির header → response headers policy। দেশ ধরে আটকানো → geo restriction (লেসন ১১.২)। Private content → signed URL বা cookie (লেসন ১১.২)। ভারী business logic → origin। Edge function তখনই ঠিক tool, যখন logic-টাকে viewer-এর কাছে চলতেই হবে আর কোনো তৈরি setting কাজটা করে না।

#নিজে করে দেখো

AWS CLI দিয়ে শুরু থেকে শেষ পর্যন্ত CloudFront Functions। redirect.js-এ ওপরের redirect function-টা আছে:

# 1. Create the function (it starts in the DEVELOPMENT stage)
aws cloudfront create-function --name haat-redirect \
  --function-config Comment="old host to new",Runtime=cloudfront-js-2.0 \
  --function-code fileb://redirect.js

# 2. Test it with a sample viewer request event; look at FunctionOutput and ComputeUtilization
aws cloudfront describe-function --name haat-redirect          # note the ETag
aws cloudfront test-function --name haat-redirect --if-match <ETag> \
  --event-object fileb://event-old-host.json --stage DEVELOPMENT

# 3. Publish to LIVE, then attach it to a cache behaviour (FunctionAssociations, EventType viewer-request)
aws cloudfront publish-function --name haat-redirect --if-match <ETag>
aws cloudfront get-distribution-config --id E1A2B3C4D5E6F7 > dist.json   # edit, then update-distribution

# 4. KeyValueStore for settings
aws cloudfront create-key-value-store --name haat-settings
aws cloudfront-keyvaluestore put-key --kvs-arn <store ARN> --key checkout_b_percent --value 10 --if-match <ETag>

Lambda@Edge (এটা us-east-1-এই হতে হবে):

aws lambda create-function --region us-east-1 --function-name haat-resize \
  --runtime nodejs22.x --handler index.handler --role arn:aws:iam::111122223333:role/edge-role \
  --zip-file fileb://resize.zip --timeout 30 --memory-size 1024
aws lambda publish-version --region us-east-1 --function-name haat-resize    # returns version 1
# associate arn:aws:lambda:us-east-1:111122223333:function:haat-resize:1 with EventType origin-response

# Where did it run? Logs are in the Region near the viewers:
aws logs describe-log-groups --region ap-south-1 --log-group-name-prefix /aws/lambda/us-east-1.haat-resize

তারপর বাইরে থেকে edge-টাকে দেখো:

curl -sI https://oldsite.example/eid-sale | grep -i -E '^(HTTP|location|x-cache|x-amz-cf-pop)'
# HTTP/2 301, location: https://newsite.example/eid-sale, x-cache: FunctionGeneratedResponse from cloudfront

curl -sI "https://shop.example.com/Product/42?utm_source=fb" | grep -i -E '^(x-cache|age|x-amz-cf-pop)'
curl -sI "https://shop.example.com/product/42?utm_source=x" | grep -i -E '^(x-cache|age|x-amz-cf-pop)'
# the second one should say Hit from cloudfront: both normalised to the same cache key

x-cache দেখায় Hit, Miss, RefreshHit বা FunctionGeneratedResponse; age দেখায় object কতক্ষণ ধরে cache-এ আছে; x-amz-cf-pop বলে কোন edge location (airport-এর মতো একটা code, যেমন মুম্বাইয়ের জন্য BOM বা সিঙ্গাপুরের জন্য SIN দিয়ে শুরু)।

#সারসংক্ষেপ

মূল কথা

  • Edge function হলো CloudFront-এর একটা cache behaviour-এ জোড়া code, যেটা viewer-এর কাছে চলে; serverless, CloudFront নিজেই সারা পৃথিবীতে deploy করে, যতটুকু চলে ততটুকুর দাম। দুই ধরন: CloudFront Functions (সাইকেল) আর Lambda@Edge (স্পোর্টস কার)।
  • চারটা event: viewer request (cache-এর আগে, প্রতিটা request), origin request (শুধু miss), origin response (cache-এর আগে, error হলেও), viewer response (৪০০-এর নিচের প্রতিটা response)। CloudFront Functions: শুধু viewer event। Lambda@Edge: চারটাই।
  • প্রতি behaviour-এ প্রতি event type-এ একটা function; একই behaviour-এর viewer event-এ দুই ধরন একসাথে চলে না, কিন্তু viewer-এ CloudFront Function + origin-এ Lambda@Edge চলে।
  • CloudFront Functions: JavaScript, sub-millisecond, 2 MB memory, 10 KB code, network নেই, body নেই, file system নেই, সেকেন্ডে লাখ লাখ request, edge location-এ চলে, প্রতি ১০ লাখে $0.10 (২০ লাখ বিনা পয়সায়)। কাজ: cache key normalisation, header, redirect/rewrite, JWT যাচাই। KeyValueStore তাদের বদলানো যায় এমন setting দেয় (প্রতি store 5 MB)।
  • Lambda@Edge: Node.js বা Python, us-east-1-এ বানানো, নম্বর দেওয়া version, replicate হয়, সবচেয়ে কাছের Region-এ চলে; viewer event-এ ৫ সেকেন্ড / 128 MB, origin event-এ ৩০ সেকেন্ড / 10 GB পর্যন্ত, 50 MB package; network, body আর file system access; Region প্রতি সেকেন্ডে প্রায় ১০,০০০ request; প্রতি ১০ লাখে $0.60 + duration, free tier নেই। কাজ: DynamoDB বা API call, ছবি ছোট করা, dynamic content, body পরীক্ষা।
  • Exam trick: sub-ms / header / highest scale / lowest latency / সবচেয়ে সস্তা redirect → CloudFront Functions; database বা network call / ভারী হিসাব / origin request → Lambda@Edge; শুধু স্থির header → response headers policy।
  • Error: 503 = function ব্যর্থ, সময় পেরিয়েছে বা throttle হয়েছে; 502 = সে ভুল কিছু ফেরত দিয়েছে। Lambda@Edge-এর log থাকে যে Region-এ সে চলেছে সেখানে।