เครือข่ายการจัดส่งเนื้อหา (CDN) เช่น Amazon CloudFront จนกระทั่งเมื่อไม่นานมานี้โครงสร้างพื้นฐานของเว็บเป็นส่วนที่ค่อนข้างเรียบง่าย ตามเนื้อผ้าเว็บแอปพลิเคชันได้รับการออกแบบมาโดยรอบโดยถือว่าส่วนใหญ่เป็นแคชแบบพาสซีฟแทนที่จะเป็นส่วนประกอบที่ใช้งานอยู่
[ป้องกันอีเมล] และเทคโนโลยีที่คล้ายคลึงกันได้เปลี่ยนแปลงสิ่งเหล่านี้และเปิดโลกแห่งความเป็นไปได้โดยการนำเสนอชั้นของตรรกะใหม่ระหว่างเว็บแอปพลิเคชันและผู้ใช้ วางจำหน่ายตั้งแต่กลางปี 2560 [ป้องกันอีเมล] เป็นคุณลักษณะใหม่ใน AWS ที่แนะนำแนวคิดของการเรียกใช้โค้ดในรูปแบบของ Lambdas โดยตรงบนเซิร์ฟเวอร์ Edge ของ CloudFront
หนึ่งในความเป็นไปได้ใหม่ที่ [ป้องกันอีเมล] ข้อเสนอเป็นโซลูชันที่สะอาดสำหรับการทดสอบ A / B ฝั่งเซิร์ฟเวอร์ การทดสอบ A / B เป็นวิธีการทั่วไปในการทดสอบประสิทธิภาพของรูปแบบต่างๆของเว็บไซต์โดยแสดงพร้อมกันกับกลุ่มเป้าหมายต่างๆของเว็บไซต์
ความท้าทายทางเทคนิคหลักในการทดสอบ A / B คือการแบ่งกลุ่มการเข้าชมที่เข้ามาอย่างเหมาะสมโดยไม่ส่งผลกระทบต่อคุณภาพของข้อมูลการทดสอบหรือตัวเว็บไซต์ แต่อย่างใด
มีสองเส้นทางหลักสำหรับการใช้งาน: ด้านลูกค้า และ ฝั่งเซิร์ฟเวอร์ .
ด้วยเหตุนี้คุณอาจสงสัยว่าทำไมทุกคนไม่ใช้การทดสอบ A / B ฝั่งเซิร์ฟเวอร์เพียงอย่างเดียว น่าเสียดายที่แนวทางฝั่งเซิร์ฟเวอร์นั้นไม่ง่ายที่จะนำไปใช้เหมือนกับแนวทางฝั่งไคลเอ็นต์และการตั้งค่าการทดสอบมักจะต้องมีการแทรกแซงบางรูปแบบกับโค้ดฝั่งเซิร์ฟเวอร์หรือการกำหนดค่าเซิร์ฟเวอร์
เพื่อทำให้สิ่งต่างๆซับซ้อนยิ่งขึ้นไปกว่านั้นเว็บแอปพลิเคชันสมัยใหม่เช่น SPA มักจะทำหน้าที่เป็นกลุ่มของรหัสคงที่โดยตรงจากที่เก็บ S3 โดยไม่ต้องเกี่ยวข้องกับเว็บเซิร์ฟเวอร์ แม้ว่าจะมีส่วนเกี่ยวข้องกับเว็บเซิร์ฟเวอร์ แต่ก็มักจะไม่สามารถเปลี่ยนตรรกะฝั่งเซิร์ฟเวอร์เพื่อตั้งค่าการทดสอบ A / B ได้ การมี CDN ก่อให้เกิดอุปสรรคอีกประการหนึ่งเนื่องจากการแคชอาจส่งผลต่อขนาดกลุ่มหรือในทางกลับกันการแบ่งกลุ่มการเข้าชมประเภทนี้สามารถลดประสิทธิภาพของ CDN ได้
อะไร [ป้องกันอีเมล] ข้อเสนอเป็นวิธีกำหนดเส้นทางคำขอของผู้ใช้ข้ามการทดสอบรูปแบบต่างๆก่อนที่จะถึงเซิร์ฟเวอร์ของคุณ ก ตัวอย่างพื้นฐาน ของกรณีการใช้งานนี้สามารถพบได้โดยตรงในเอกสาร AWS แม้ว่าจะมีประโยชน์ในการพิสูจน์แนวคิด แต่สภาพแวดล้อมการผลิตที่มีการทดลองหลายครั้งพร้อมกันอาจต้องการสิ่งที่ยืดหยุ่นและแข็งแกร่งกว่า
ยิ่งไปกว่านั้นหลังจากทำงานกับ [ป้องกันอีเมล] คุณอาจจะรู้ว่ามีความแตกต่างบางประการที่ต้องระวังเมื่อสร้างสถาปัตยกรรมของคุณ
ตัวอย่างเช่นการปรับใช้ Edge Lambdas ต้องใช้เวลาและบันทึกของพวกเขาจะกระจายไปตามภูมิภาค AWS โปรดคำนึงถึงสิ่งนี้หากคุณต้องการดีบักการกำหนดค่าของคุณเพื่อหลีกเลี่ยงข้อผิดพลาด 502
บทแนะนำนี้จะแนะนำ นักพัฒนา AWS เป็นวิธีการดำเนินการทดสอบ A / B ฝั่งเซิร์ฟเวอร์โดยใช้ [ป้องกันอีเมล] ในลักษณะที่สามารถใช้ซ้ำได้ในการทดลองโดยไม่ต้องปรับเปลี่ยนและปรับใช้ Lambdas ขอบใหม่ สร้างขึ้นจากแนวทางของตัวอย่างในเอกสาร AWS และบทช่วยสอนอื่น ๆ ที่คล้ายคลึงกัน แต่แทนที่จะเข้ารหัสกฎการจัดสรรปริมาณการใช้งานใน Lambda เองกฎจะถูกดึงมาจากไฟล์การกำหนดค่าบน S3 เป็นระยะซึ่งคุณสามารถเปลี่ยนแปลงได้ตลอดเวลา
แนวคิดพื้นฐานที่อยู่เบื้องหลังแนวทางนี้คือให้ CDN กำหนดผู้ใช้แต่ละรายให้กับเซ็กเมนต์จากนั้นกำหนดเส้นทางผู้ใช้ไปยังการกำหนดค่าต้นทางที่เกี่ยวข้อง CloudFront ช่วยให้การกระจายชี้ไปที่ S3 หรือต้นทางที่กำหนดเองและในแนวทางนี้เราสนับสนุนทั้งสองอย่าง
การแมปเซ็กเมนต์กับตัวแปรทดสอบจะถูกเก็บไว้ในไฟล์ JSON บน S3 S3 ถูกเลือกที่นี่เพื่อความเรียบง่าย แต่ยังสามารถดึงข้อมูลจากฐานข้อมูลหรือพื้นที่เก็บข้อมูลรูปแบบอื่น ๆ ที่ Edge Lambda สามารถเข้าถึงได้
บันทึก: มีข้อ จำกัด บางประการ - ตรวจสอบบทความ ใช้ประโยชน์จากข้อมูลภายนอกใน[ป้องกันอีเมล] ในบล็อก AWS สำหรับข้อมูลเพิ่มเติม
[ป้องกันอีเมล] สามารถถูกกระตุ้นโดยเหตุการณ์ CloudFront สี่ประเภท:
ในกรณีนี้เราจะเรียกใช้ Lambda ในแต่ละเหตุการณ์สามเหตุการณ์ต่อไปนี้:
แต่ละเหตุการณ์จะใช้ขั้นตอนในกระบวนการต่อไปนี้:
เรามาตั้งค่าที่เก็บข้อมูล S3 สามรายการโดยสองรายการจะมีเนื้อหาของตัวแปรของการทดสอบแต่ละรายการในขณะที่ชุดที่สามจะมีไฟล์ JSON พร้อมกับแผนที่การจัดสรรการเข้าชม
สำหรับบทช่วยสอนนี้ถังจะมีลักษณะดังนี้:
ก่อนอื่นมาเริ่มต้นด้วยแผนที่การจัดสรรการจราจร:
map.json
{ 'segments': [ { 'weight': 0.7, 'host': 'abtesting-ttblog-a.s3.amazonaws.com', 'origin': { 's3': { 'authMethod': 'none', 'domainName': 'abtesting-ttblog-a.s3.amazonaws.com', 'path': '', 'region': 'eu-west-1' } } }, { 'weight': 0.3, 'host': 'abtesting-ttblog-b.s3.amazonaws.com', 'origin': { 's3': { 'authMethod': 'none', 'domainName': 'abtesting-ttblog-b.s3.amazonaws.com', 'path': '', 'region': 'eu-west-1' } } } ] }
แต่ละกลุ่มมีน้ำหนักการเข้าชมซึ่งจะใช้ในการจัดสรรปริมาณการเข้าชมที่สอดคล้องกัน นอกจากนี้เรายังรวมการกำหนดค่าต้นทางและโฮสต์ รูปแบบการกำหนดค่าต้นทาง ได้อธิบายไว้ในเอกสาร AWS
abtesting-lambda-vreq
'use strict'; const aws = require('aws-sdk'); const COOKIE_KEY = 'abtesting-unique-id'; const s3 = new aws.S3({ region: 'eu-west-1' }); const s3Params = { Bucket: 'abtesting-ttblog-map', Key: 'map.json', }; const SEGMENT_MAP_TTL = 3600000; // TTL of 1 hour const fetchSegmentMapFromS3 = async () => { const response = await s3.getObject(s3Params).promise(); return JSON.parse(response.Body.toString('utf-8')); } // Cache the segment map across Lambda invocations let _segmentMap; let _lastFetchedSegmentMap = 0; const fetchSegmentMap = async () => { if (!_segmentMap || (Date.now() - _lastFetchedSegmentMap) > SEGMENT_MAP_TTL) { _segmentMap = await fetchSegmentMapFromS3(); _lastFetchedSegmentMap = Date.now(); } return _segmentMap; } // Just generate a random UUID const getRandomId = () => { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) 0x8); return v.toString(16); ); }; // This function will hash any string (our random UUID in this case) // to a [0, 1) range const hashToInterval = (s) => { let hash = 0, i = 0; while (i { const segmentMap = await fetchSegmentMap(); let weight = 0; for (const segment of segmentMap.segments) { weight += segment.weight; if (p { const request = event.Records[0].cf.request; const headers = request.headers; let uniqueId = getCookie(headers, COOKIE_KEY); if (uniqueId === null) { // This is what happens on the first visit: we'll generate a new // unique ID, then leave it the cookie header for the // viewer response lambda to set permanently later uniqueId = getRandomId(); const cookie = `${COOKIE_KEY}=${uniqueId}`; headers.cookie = headers.cookie || []; headers.cookie.push({ key: 'Cookie', value: cookie }); } // Get a value between 0 and 1 and use it to // resolve the traffic segment const p = hashToInterval(uniqueId); const segment = await getSegment(p); // Pass the origin data as a header to the origin request lambda // The header key below is whitelisted in Cloudfront const headerValue = JSON.stringify({ host: segment.host, origin: segment.origin }); headers['x-abtesting-segment-origin'] = [{ key: 'X-ABTesting-Segment-Origin', value: headerValue }]; callback(null, request); };
ที่นี่เราสร้างรหัสเฉพาะสำหรับบทช่วยสอนนี้อย่างชัดเจน แต่เป็นเรื่องปกติที่เว็บไซต์ส่วนใหญ่จะมีรหัสไคลเอ็นต์อื่นแฝงอยู่ซึ่งสามารถใช้แทนได้ นอกจากนี้ยังช่วยขจัดความจำเป็นในการตอบสนองของผู้ชม Lambda
สำหรับข้อพิจารณาด้านประสิทธิภาพกฎการจัดสรรปริมาณการใช้งานจะถูกแคชไว้ในการเรียกใช้ Lambda แทนที่จะดึงข้อมูลจาก S3 ในทุกคำขอ ในตัวอย่างนี้เราตั้งค่า TTL แคชเป็นเวลา 1 ชั่วโมง
ความแตกต่างระหว่างศิลปะกับการออกแบบ
โปรดทราบว่าไฟล์ X-ABTesting-Segment-Origin
ส่วนหัวต้องอยู่ในรายการที่อนุญาตพิเศษใน CloudFront มิฉะนั้นจะถูกลบออกจากคำขอก่อนที่จะไปถึง Lambda ของคำขอต้นทาง
abtesting-lambda-oreq
'use strict'; const HEADER_KEY = 'x-abtesting-segment-origin'; // Origin Request handler exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; const headers = request.headers; const headerValue = headers[HEADER_KEY] && headers[HEADER_KEY][0] && headers[HEADER_KEY][0].value; if (headerValue) { const segment = JSON.parse(headerValue); headers['host'] = [{ key: 'host', value: segment.host }]; request.origin = segment.origin; } callback(null, request); };
แลมด้าขอต้นทางค่อนข้างตรงไปตรงมา การกำหนดค่าต้นทางและโฮสต์ถูกอ่านจากไฟล์ X-ABTesting-Origin
ส่วนหัวที่สร้างขึ้นในขั้นตอนก่อนหน้าและฉีดเข้าไปในคำขอ สิ่งนี้สั่งให้ CloudFront กำหนดเส้นทางการร้องขอไปยังต้นทางที่เกี่ยวข้องในกรณีที่แคชพลาด
abtesting-lambda-vres
'use strict'; const COOKIE_KEY = 'abtesting-unique-id'; const getCookie = (headers, cookieKey) => { if (headers.cookie) { for (let cookieHeader of headers.cookie) { const cookies = cookieHeader.value.split(';'); for (let cookie of cookies) { const [key, val] = cookie.split('='); if (key === cookieKey) { return val; } } } } return null; } const setCookie = function (response, cookie) { console.log(`Setting cookie ${cookie}`); response.headers['set-cookie'] = response.headers['set-cookie'] || []; response.headers['set-cookie'] = [{ key: 'Set-Cookie', value: cookie }]; } exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; const headers = request.headers; const response = event.Records[0].cf.response; const cookieVal = getCookie(headers, COOKIE_KEY); if (cookieVal != null) { setCookie(response, `${COOKIE_KEY}=${cookieVal}`); callback(null, response); return; } console.log(`no ${COOKIE_KEY} cookie`); callback(null, response); }
สุดท้ายการตอบสนองของผู้ชม Lambda รับผิดชอบในการส่งคืนคุกกี้ ID เฉพาะที่สร้างขึ้นในไฟล์ Set-Cookie
หัวข้อ. ดังที่ได้กล่าวไว้ข้างต้นหากมีการใช้รหัสไคลเอ็นต์ที่ไม่ซ้ำกันแล้วคุณสามารถละ Lambda นี้ได้ทั้งหมด
ในความเป็นจริงแม้ในกรณีนี้คุกกี้สามารถตั้งค่าด้วยการเปลี่ยนเส้นทางโดยคำขอ Lambda ของผู้ดู อย่างไรก็ตามสิ่งนี้อาจเพิ่มเวลาในการตอบสนองได้ดังนั้นในกรณีนี้เราชอบที่จะทำในรอบการตอบสนองคำขอเดียว
รหัสสามารถพบได้บน GitHub .
เช่นเดียวกับ Edge Lambda คุณสามารถใช้พิมพ์เขียว CloudFront เมื่อสร้าง Lambda มิฉะนั้นคุณจะต้องสร้างบทบาทที่กำหนดเองและแนบ 'พื้นฐาน [ป้องกันอีเมล] สิทธิ์” เทมเพลตนโยบาย
สำหรับ Lambda คำขอวิวเวอร์คุณจะต้องอนุญาตการเข้าถึงที่เก็บข้อมูล S3 ที่มีไฟล์การจัดสรรทราฟฟิกด้วย
การตั้งค่า Edge Lambdas ค่อนข้างแตกต่างจากเวิร์กโฟลว์ Lambda มาตรฐาน ในหน้าการกำหนดค่าของ Lamba ให้คลิก 'เพิ่มทริกเกอร์' แล้วเลือก CloudFront สิ่งนี้จะเปิดกล่องโต้ตอบเล็ก ๆ ที่ให้คุณเชื่อมโยง Lambda นี้กับการกระจาย CloudFront
เลือกเหตุการณ์ที่เหมาะสมสำหรับ Lambdas ทั้งสามและกด“ Deploy” ขั้นตอนนี้จะเริ่มต้นกระบวนการปรับใช้โค้ดฟังก์ชันกับเซิร์ฟเวอร์ Edge ของ CloudFront
บันทึก: หากคุณต้องการแก้ไข Edge Lambda และปรับใช้ใหม่คุณจะต้องเผยแพร่เวอร์ชันใหม่ด้วยตนเองก่อน
เพื่อให้การกระจาย CloudFront สามารถกำหนดเส้นทางการรับส่งข้อมูลไปยังต้นทางได้คุณจะต้องตั้งค่าแต่ละรายการแยกกันในแผงต้นทาง
การตั้งค่าการกำหนดค่าเดียวที่คุณต้องเปลี่ยนคือการอนุญาตพิเศษ X-ABTesting-Segment-Origin
หัวข้อ. บน คอนโซล CloudFront เลือกการแจกจ่ายของคุณจากนั้นกดแก้ไขเพื่อเปลี่ยนการตั้งค่าการแจกจ่าย
การเขียนโปรแกรมจำนวนเต็มผสมคืออะไร
บน แก้ไขพฤติกรรม หน้าให้เลือก รายการที่อนุญาต จากเมนูแบบเลื่อนลงบน แคชขึ้นอยู่กับส่วนหัวของคำขอที่เลือก ตัวเลือกและเพิ่มแบบกำหนดเอง X-ABTesting-Segment-Origin ส่วนหัวของรายการ:
หากคุณปรับใช้ Edge Lambdas ตามที่อธิบายไว้ในส่วนก่อนหน้านี้ควรเชื่อมโยงกับการแจกจ่ายของคุณแล้วและแสดงอยู่ในส่วนสุดท้ายของ แก้ไขพฤติกรรม หน้า.
การทดสอบ A / B ฝั่งเซิร์ฟเวอร์อาจเป็นเรื่องยากที่จะนำไปใช้อย่างเหมาะสมสำหรับเว็บไซต์ที่มีการเข้าชมสูงซึ่งติดตั้งใช้งานหลังบริการ CDN เช่น CloudFront ในบทความนี้เราได้สาธิตวิธีการ [ป้องกันอีเมล] สามารถใช้เป็นแนวทางใหม่ในการแก้ปัญหานี้ได้โดยซ่อนรายละเอียดการใช้งานไว้ใน CDN เองในขณะเดียวกันก็นำเสนอโซลูชันที่สะอาดและเชื่อถือได้ในการเรียกใช้การทดลอง A / B
อย่างไรก็ตาม [ป้องกันอีเมล] มีข้อเสียเล็กน้อย สิ่งสำคัญที่สุดคือการเรียกใช้ Lambda เพิ่มเติมเหล่านี้ระหว่างเหตุการณ์ CloudFront สามารถรวมกันได้ทั้งในแง่ของเวลาในการตอบสนองและต้นทุนดังนั้นจึงควรวัดผลกระทบที่มีต่อการกระจาย CloudFront อย่างรอบคอบก่อน
ยิ่งไปกว่านั้น [ป้องกันอีเมล] เป็นคุณสมบัติที่ค่อนข้างใหม่ล่าสุดและยังคงพัฒนาอยู่ของ AWS ดังนั้นโดยธรรมชาติแล้วมันยังคงรู้สึกหยาบเล็กน้อยที่ขอบ ผู้ใช้ที่ระมัดระวังมากขึ้นอาจต้องการรอสักครู่ก่อนที่จะวางไว้ที่จุดวิกฤตของโครงสร้างพื้นฐาน
ดังที่กล่าวมาโซลูชันที่ไม่เหมือนใครที่นำเสนอทำให้เป็นคุณลักษณะที่ขาดไม่ได้ของ CDN ดังนั้นจึงไม่มีเหตุผลที่จะคาดหวังว่าจะได้รับการยอมรับอย่างกว้างขวางมากขึ้นในอนาคต
[ป้องกันอีเมล] เป็นคุณลักษณะของ CloudFront ที่ช่วยให้คุณสามารถรันโค้ดที่กำหนดเองเพื่อตอบสนองต่อเหตุการณ์ของ CloudFront ในรูปแบบของฟังก์ชัน AWS Lambda ซึ่งดำเนินการใกล้เคียงกับเซิร์ฟเวอร์ขอบของ CloudFront ฟังก์ชันเหล่านี้สามารถใช้เพื่อแก้ไขพฤติกรรมของ CloudFront ณ จุดใดก็ได้ของวงจรการตอบสนองคำขอ
[ป้องกันอีเมล] ใช้ฟังก์ชัน AWS Lambda มาตรฐานที่แนบมากับทริกเกอร์เหตุการณ์ CloudFront ซึ่งสอดคล้องกับสี่ขั้นตอนที่เป็นไปได้ที่ CloudFront ป้อนได้เมื่อตอบสนองต่อคำขอ HTTP ในระหว่างการดำเนินการที่ทริกเกอร์แต่ละครั้ง Lambda สามารถอ่านและแก้ไขคำขอหรืออ็อบเจ็กต์การตอบกลับก่อนที่จะส่งไปยังขั้นตอนถัดไป
AWS [ป้องกันอีเมล] สามารถใช้ในการตัดสินใจเกี่ยวกับวิธีจัดการคำขอก่อนที่จะไปถึงจุดเริ่มต้นของ CloudFront กรณีการใช้งานที่เป็นที่นิยมคือการเลือกต้นทางสำหรับการทดสอบ A / B แต่ยังสามารถใช้ในลักษณะที่คล้ายกันเพื่อจัดเตรียมเนื้อหาที่กำหนดเองซึ่งได้รับการปรับให้เหมาะสมกับประเภทอุปกรณ์หรือภูมิภาคของผู้ใช้โดยเฉพาะ กรณีการใช้งานอื่น ๆ ได้แก่ การพิสูจน์ตัวตนผู้ใช้ผ่าน CloudFront (เช่นการยืนยันข้อมูลประจำตัวของผู้ใช้เมื่อให้บริการเนื้อหาแบบคงที่) และการเพิ่มประสิทธิภาพแคชแบบละเอียดบางรูปแบบ
ในขณะที่เขียนไม่มีอะไรคล้ายกับ [ป้องกันอีเมล] บน Microsoft Azure หรือ Google Cloud Platform ทางเลือกที่แข่งขันกันในปัจจุบันคือฟีเจอร์ Workers ของ CloudFlare ซึ่งโดยหลักการแล้วควรทำให้สามารถใช้โซลูชันที่คล้ายกันสำหรับการทดสอบ A / B ได้ อย่างไรก็ตามสิ่งนี้อาจเปลี่ยนแปลงได้ในไม่ช้าเนื่องจากบริการคลาวด์ทั้งสองอาจเริ่มนำเสนอสิ่งที่คล้ายกันในอนาคต
เนื่องจาก CloudFront ถูกเรียกเก็บเงินตามปริมาณการทดสอบ A / B รูปแบบใด ๆ ที่นำไปใช้อย่างเหมาะสมไม่ควรส่งผลกระทบอย่างมีนัยสำคัญต่อปริมาณการใช้งาน CDN [ป้องกันอีเมล] อย่างไรก็ตามการเรียกเก็บเงินจะถูกเรียกเก็บเงินแยกกันในลักษณะเดียวกับฟังก์ชัน AWS Lambda นั่นคือขึ้นอยู่กับจำนวนการเรียกใช้และระยะเวลารวมของการดำเนินการของ Lambda แต่ละรายการ