0Pricing
Cloud & IT Cert Prep · บทเรียน

Durable Functions สำหรับเวิร์กโฟลว์ที่มีสถานะ

จัดการเวิร์กโฟลว์ที่ทำงานเป็นเวลานานโดยใช้รูปแบบตัวประสานงานของ Durable Functions (กระจายงาน/รวมผล การเชื่อมโยง การตรวจสอบ) และทำความเข้าใจวิธีบันทึกจุดตรวจสอบสถานะ

Durable Functions สำหรับเวิร์กโฟลว์ที่มีสถานะ เป็นบทเรียน Cloud & IT Cert Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Cloud & IT Cert Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Cloud & IT Cert Prep มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดจึงต้องใช้ Durable Functions

Azure Functions ทั่วไปไม่มีสถานะ — การเรียกใช้แต่ละครั้งทำงานอย่างอิสระและไม่มีหน่วยความจำจากการเรียกใช้ก่อนหน้า Durable Functions เพิ่มความสามารถให้ Azure Functions ในการเขียน เวิร์กโฟลว์ที่มีสถานะและทำงานเป็นเวลานาน ด้วยโค้ด async/await แบบปกติ Durable Task Framework จะบันทึกจุดตรวจสอบสถานะไปยัง Azure Storage โดยอัตโนมัติหลังจบแต่ละขั้นตอน ดังนั้นเวิร์กโฟลว์จึงทำงานต่อได้หลังเซิร์ฟเวอร์เริ่มการทำงานใหม่ หมดเวลา หรือมีการบำรุงรักษาตามแผน โดยกลับมาทำงานต่อจากจุดเดิมได้อย่างแม่นยำ

ฟังก์ชันสามประเภท

Durable Functions มีฟังก์ชันอยู่สามประเภท ฟังก์ชันตัวประสานงานจะควบคุมเวิร์กโฟลว์โดยรวม — เรียกใช้ฟังก์ชันกิจกรรมและรอผลลัพธ์ด้วย yield หรือ await โดยไม่บล็อกเธรดจริง ๆ ฟังก์ชันกิจกรรมทำงานหนึ่งหน่วย (เช่น เรียก API หรือเขียนข้อมูลลงฐานข้อมูล) และเป็นสถานที่เดียวที่ควรเกิดผลข้างเคียง ส่วน ฟังก์ชันเอนทิตีจะดูแลส่วนเล็ก ๆ ของสถานะที่คงอยู่ (เช่น ตัวนับและแฟล็ก) ข้ามการเรียกใช้แต่ละครั้ง

// Client function (HTTP trigger) — starts the orchestration
module.exports = async function (context, req) {
  const client = df.getClient(context);
  const orderId = req.body.orderId;
  const instanceId = await client.startNew('OrderOrchestrator', undefined, { orderId });
  return client.createCheckStatusResponse(context.bindingData.req, instanceId);
};

รูปแบบการเชื่อมโยง

รูปแบบการเชื่อมโยงจะเรียกใช้ฟังก์ชันกิจกรรมตามลำดับ โดยส่งเอาต์พุตของฟังก์ชันหนึ่งไปเป็นอินพุตของฟังก์ชันถัดไป ตัวประสานงานจะรอแต่ละกิจกรรมตามลำดับ หากกิจกรรมใดล้มเหลว เวิร์กโฟลว์จะหยุดลงและสามารถเริ่มใหม่จากขั้นตอนที่ล้มเหลวได้ นี่เป็นรูปแบบ Durable Functions ที่ง่ายที่สุด และเหมาะสำหรับเวิร์กโฟลว์ที่แต่ละขั้นตอนต้องอาศัยผลลัพธ์จากขั้นตอนก่อนหน้า เช่น ไปป์ไลน์ประมวลผลคำสั่งซื้อ

// Orchestrator: chaining pattern
const df = require('durable-functions');
module.exports = df.orchestrator(function* (context) {
  const orderId = context.df.getInput().orderId;

  const validated = yield context.df.callActivity('ValidateOrder', orderId);
  const charged   = yield context.df.callActivity('ChargePayment', validated);
  const shipped   = yield context.df.callActivity('ShipOrder', charged);

  return { status: 'shipped', trackingId: shipped.trackingId };
});

รูปแบบ Fan-Out / Fan-In

รูปแบบ fan-out/fan-inจะเปิดใช้ฟังก์ชันกิจกรรมหลายรายการพร้อมกัน และรอให้ทั้งหมดทำงานเสร็จก่อนดำเนินการต่อ ตัวประสานงานจะเริ่มงานทั้งหมดพร้อมกันด้วย callActivity โดยไม่รอผลลัพธ์ทันที จากนั้นรวบรวมอ็อบเจ็กต์งานไว้ในอาร์เรย์ แล้วใช้ Task.all() เพื่อรอทั้งหมด วิธีนี้เร็วกว่าแบบประมวลผลตามลำดับอย่างมากสำหรับงานอิสระ เช่น การประมวลผลไฟล์หลายไฟล์ การเรียก API หลายรายการ หรือการดำเนินการแบบกลุ่ม

// Orchestrator: fan-out / fan-in
module.exports = df.orchestrator(function* (context) {
  const items = context.df.getInput().items;

  // Fan-out: start all tasks in parallel
  const tasks = items.map(item => context.df.callActivity('ProcessItem', item));

  // Fan-in: wait for all tasks to complete
  const results = yield context.df.Task.all(tasks);

  return results;
});

รูปแบบการตรวจสอบ

รูปแบบการตรวจสอบจะสอบถามระบบภายนอกเป็นระยะจนกว่าเงื่อนไขจะเป็นจริง ซึ่งคล้ายกับลูปสอบถามสถานะ แต่มีความคงทนอย่างสมบูรณ์ ตัวประสานงานจะเรียกกิจกรรมเพื่อตรวจสอบสถานะ รอเป็นช่วงเวลาที่กำหนดค่าได้ด้วย createTimer แล้วจึงวนซ้ำ เนื่องจากสถานะถูกบันทึกจุดตรวจสอบลงในพื้นที่จัดเก็บระหว่างการสอบถามแต่ละครั้ง ตัวประสานงานจึงไม่ใช้ทรัพยากรการประมวลผลระหว่างรอ ทำให้มีประสิทธิภาพมากกว่าวิธีใช้ตัวจับเวลาที่หยุดรออย่างมาก

// Orchestrator: monitor pattern (poll until job completes)
module.exports = df.orchestrator(function* (context) {
  const jobId = context.df.getInput().jobId;
  const expiry = new Date(context.df.currentUtcDateTime);
  expiry.setHours(expiry.getHours() + 24); // 24-hour timeout

  while (context.df.currentUtcDateTime < expiry) {
    const status = yield context.df.callActivity('GetJobStatus', jobId);
    if (status === 'completed') return { jobId, status };
    if (status === 'failed') throw new Error('Job failed');
    // Wait 30 seconds before next poll
    const nextCheck = new Date(context.df.currentUtcDateTime);
    nextCheck.setSeconds(nextCheck.getSeconds() + 30);
    yield context.df.createTimer(nextCheck);
  }
  throw new Error('Workflow timed out');
});

รูปแบบการโต้ตอบกับมนุษย์

รูปแบบการโต้ตอบกับมนุษย์จะหยุดการประสานงานชั่วคราวและรอเหตุการณ์ภายนอก เช่น การอนุมัติจากผู้จัดการ ตัวประสานงานจะใช้ waitForExternalEvent เพื่อรอ ซึ่งอาจรอเป็นวันหรือสัปดาห์ได้โดยไม่ใช้ทรัพยากรการประมวลผล ระบบภายนอก (ลิงก์อนุมัติทางอีเมล แอปบนอุปกรณ์เคลื่อนที่ หรือเว็บฮุก) จะเรียก API HTTP ของ Durable Functions เพื่อส่งเหตุการณ์ ทำให้การประสานงานดำเนินต่อได้ หากไม่มีการตอบกลับ ให้ใช้ร่วมกับตัวจับเวลาเพื่อหมดเวลาและยกระดับการแจ้งเตือนโดยอัตโนมัติ

// Orchestrator: wait for human approval with timeout
module.exports = df.orchestrator(function* (context) {
  const request = context.df.getInput();

  yield context.df.callActivity('SendApprovalEmail', request);

  const timeout = df.Task.createTimer(context, new Date(Date.now() + 48 * 3600 * 1000));
  const approval = context.df.waitForExternalEvent('ApprovalResponse');

  const winner = yield context.df.Task.any([approval, timeout]);

  if (winner === approval) {
    const approved = winner.result;
    return approved ? 'Approved' : 'Rejected';
  } else {
    return 'Timed out — escalated';
  }
});

ข้อจำกัดของตัวประสานงาน

ฟังก์ชันตัวประสานงานมีข้อจำกัดสำคัญ เนื่องจากอาจถูกเล่นซ้ำจากประวัติหลายครั้งเพื่อสร้างสถานะขึ้นใหม่ ฟังก์ชันเหล่านี้ต้อง ให้ผลลัพธ์แน่นอน — ห้ามใช้ Date.now(), Math.random() หรือดำเนินการ I/O โดยตรง แต่ให้ใช้ context.df.currentUtcDateTime สำหรับการประทับเวลา และเรียกฟังก์ชันกิจกรรมสำหรับ I/O ทั้งหมด การบันทึกข้อมูลในตัวเนื้อหาของตัวประสานงานจะทำให้มีรายการบันทึกซ้ำระหว่างการเล่นซ้ำ ดังนั้นควรใช้ฟังก์ชันกิจกรรมสำหรับการบันทึกข้อมูลแทน

// WRONG — non-deterministic, will cause replay bugs
module.exports = df.orchestrator(function* (context) {
  const now = new Date();          // Don't use Date()
  const rand = Math.random();       // Don't use Math.random()
  const data = await fetch('/api'); // Don't make HTTP calls directly
});

// CORRECT
module.exports = df.orchestrator(function* (context) {
  const now = context.df.currentUtcDateTime; // OK
  const data = yield context.df.callActivity('FetchData', null); // OK
});

การจัดการอินสแตนซ์: สถานะและการยุติการทำงาน

การทำงานประสานงานแต่ละครั้งมี รหัสอินสแตนซ์ ที่ไม่ซ้ำกัน ซึ่งคุณสามารถใช้สอบถามสถานะ ส่งเหตุการณ์ หรือยุติการทำงานได้ API การจัดการผ่าน HTTP ของ Durable Functions มีปลายทางสำหรับตรวจสอบสถานะ (GET /instances/{id}) ส่งเหตุการณ์ (POST /instances/{id}/raiseEvent/{name}) และยุติการทำงาน (POST /instances/{id}/terminate) ใช้การเชื่อมโยงไคลเอ็นต์ Durable ในฟังก์ชันของคุณเพื่อเข้าถึงการดำเนินการเหล่านี้ผ่านโปรแกรม

// Client function: check orchestration status
module.exports = async function (context, req) {
  const client = df.getClient(context);
  const instanceId = req.params.instanceId;

  const status = await client.getStatus(instanceId, true, true, true);
  return {
    status: 200,
    body: {
      instanceId,
      runtimeStatus: status.runtimeStatus,
      customStatus: status.customStatus,
      output: status.output
    }
  };
};

แบ็กเอนด์พื้นที่จัดเก็บและประสิทธิภาพ

Durable Functions จัดเก็บประวัติการประสานงาน สถานะอินสแตนซ์ และคิวข้อความระหว่างฟังก์ชันไว้ใน บัญชี Azure Storage (หรือแบ็กเอนด์ Azure SQL/เนเธอไรต์สำหรับปริมาณงานที่สูงขึ้น) จุดตรวจสอบทุกจุดจะเขียนข้อมูลลง Azure Table Storage และ Azure Queue Storage สำหรับสถานการณ์ที่มีปริมาณงานสูง (การประสานงานพร้อมกันหลายพันรายการ) แบ็กเอนด์พื้นที่จัดเก็บเนเธอไรต์จะใช้ Azure Event Hubs เพื่อให้มีประสิทธิภาพดีขึ้นอย่างมาก ควรตรวจสอบความลึกของคิวการประสานงานเพื่อค้นหาคอขวด

// host.json: configure the Durable Task storage provider
{
  'version': '2.0',
  'extensions': {
    'durableTask': {
      'hubName': 'MyTaskHub',
      'storageProvider': {
        'type': 'azure',
        'connectionStringName': 'AzureWebJobsStorage',
        'controlQueueBatchSize': 32,
        'maxQueuePollingInterval': '00:00:02'
      }
    }
  }
}

การจัดการข้อผิดพลาดและการลองใหม่

ฟังก์ชันกิจกรรมสามารถโยนข้อยกเว้น ซึ่งจะส่งต่อกลับไปยังตัวประสานงานในรูปแบบ TaskFailedException ใช้บล็อก try-catch ในตัวประสานงานเพื่อจัดการความล้มเหลวอย่างเหมาะสม สำหรับข้อผิดพลาดชั่วคราว ให้กำหนดค่า การลองใหม่โดยอัตโนมัติ พร้อมการเพิ่มช่วงเวลารอด้วย callActivityWithRetry โดยระบุจำนวนครั้งสูงสุด ช่วงเวลาก่อนลองใหม่ครั้งแรก และค่าสัมประสิทธิ์การเพิ่มช่วงเวลารอ นี่เป็นรูปแบบที่แนะนำสำหรับกิจกรรมที่เรียก API หรือฐานข้อมูลภายนอก

// Orchestrator: retry an activity with exponential backoff
module.exports = df.orchestrator(function* (context) {
  const retryOptions = new df.RetryOptions(
    5000,  // firstRetryIntervalInMilliseconds
    3      // maxNumberOfAttempts
  );
  retryOptions.backoffCoefficient = 2; // 5s, 10s, 20s

  try {
    const result = yield context.df.callActivityWithRetry(
      'CallExternalAPI',
      retryOptions,
      context.df.getInput()
    );
    return result;
  } catch (e) {
    yield context.df.callActivity('SendFailureAlert', e.message);
    throw e;
  }
});

เอนทิตีแบบ Durable

เอนทิตีแบบ Durable (ฟังก์ชันเอนทิตี) ใช้สำหรับจัดการส่วนเล็ก ๆ ของสถานะที่คงอยู่และเข้าถึงได้ด้วยข้อมูลระบุตัวตน ซึ่งคล้ายกับตัวแสดงเสมือน เอนทิตีมีรหัสและสถานะที่คงอยู่ระหว่างการเรียกใช้แต่ละครั้ง คุณสามารถเรียกการดำเนินการบนเอนทิตีจากตัวประสานงานหรือไคลเอ็นต์ได้ และเอนทิตีจะประมวลผลทีละรายการตามลำดับ การใช้งานทั่วไป ได้แก่ ตัวนับ เครื่องสถานะการอนุมัติ ตัวจำกัดอัตรา และตะกร้าสินค้า — กล่าวคือ สถานการณ์ใด ๆ ที่ต้องการสถานะซึ่งคงอยู่และอัปเดตได้โดยไม่ต้องใช้ฐานข้อมูล

// Counter entity function
const df = require('durable-functions');
module.exports = df.entity(function (context) {
  let count = context.df.getState(() => 0);
  const operation = context.df.operationName;

  if (operation === 'add') count += context.df.getInput();
  if (operation === 'reset') count = 0;
  if (operation === 'get') context.df.return(count);

  context.df.setState(count);
});

// From orchestrator, increment counter entity
// const entityId = new df.EntityId('Counter', 'myCounter');
// yield context.df.callEntity(entityId, 'add', 1);

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทดสอบความเข้าใจแนวคิด Microsoft Azure Fundamentals (AZ-900) จากบทเรียนนี้

สรุปบทเรียน

ในบทเรียนนี้ คุณได้เรียนรู้ว่า Durable Functions ช่วยให้สร้างเวิร์กโฟลว์ที่มีสถานะและทำงานเป็นเวลานานได้ โดยบันทึกจุดตรวจสอบสถานะของตัวประสานงานลงใน Azure Storage รูปแบบสำคัญ ได้แก่ การเชื่อมโยง, fan-out/fan-in, การตรวจสอบ และการโต้ตอบกับมนุษย์ และ ตัวประสานงานต้องให้ผลลัพธ์แน่นอน — การดำเนินการ I/O และการเรียกใช้ที่ไม่ให้ผลลัพธ์แน่นอนทั้งหมดต้องทำผ่านฟังก์ชันกิจกรรม ต่อไปเราจะศึกษา Azure Logic Apps

คำถามที่พบบ่อย

บทเรียน “Durable Functions สำหรับเวิร์กโฟลว์ที่มีสถานะ” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “Durable Functions สำหรับเวิร์กโฟลว์ที่มีสถานะ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Cloud & IT Cert Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Cloud & IT Cert Prep มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “Durable Functions สำหรับเวิร์กโฟลว์ที่มีสถานะ”

จัดการเวิร์กโฟลว์ที่ทำงานเป็นเวลานานโดยใช้รูปแบบตัวประสานงานของ Durable Functions (กระจายงาน/รวมผล การเชื่อมโยง การตรวจสอบ) และทำความเข้าใจวิธีบันทึกจุดตรวจสอบสถานะ คุณปฏิบัติ Cloud & IT Cert Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Cloud & IT Cert Prep หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Cloud & IT Cert Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “Durable Functions สำหรับเวิร์กโฟลว์ที่มีสถานะ” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Cloud & IT Cert Prep นี้ได้ไหม

ได้ บทเรียน Cloud & IT Cert Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ทริกเกอร์และการผูกของ Azure Functions
  2. Durable Functions สำหรับเวิร์กโฟลว์ที่มีสถานะ
  3. Azure Logic Apps
  4. Event Grid และสถาปัตยกรรมที่ขับเคลื่อนด้วยเหตุการณ์
← กลับไปที่ Cloud & IT Cert Prep