快速入門:使用 Azure Functions 處理即時事件

在本文中,你使用 Azure Developer CLI(azd) 來建立一個 Event Hubs 觸發函式,用於 Azure Functions 中的即時事件處理。 在本地驗證程式碼後,你會部署到一個新的無伺服器函式應用程式,該應用程式在 Azure 的 Flex Consumption 計畫中運行。

專案原始碼用 azd 來建立函式應用程式及相關資源,並將程式碼部署到 Azure。 此部署遵循目前安全且可擴展的 Azure Functions 部署最佳實務。

預設情況下,Flex Consumption 方案採用按 使用量付費 的計費模式,這表示你可以完成本文,且在 Azure 帳戶中只需花費幾美元或更少的費用。

本文支援Azure Functions Node.js 程式設計模型的第四版。

本文支援 Azure Functions 的 Python 程式設計模型第二版。

先決條件

初始化專案

使用命令 azd init 從範本建立本機 Azure Functions 程式碼專案。

在您的本機終端機或命令提示字元中,於空白資料夾中執行此 azd init 命令:

azd init --template functions-quickstart-dotnet-azd-eventhub -e eventhub-dotnet

此指令會從 template 儲存庫 拉取專案檔案,並在目前資料夾中初始化專案。 -e 旗標會設定目前環境的名稱。 在 azd 中,該環境會為您的應用程式維護一個唯一的部署內容,而您可以定義多個部署內容。 環境名稱也會用在你在 Azure 建立的資源群組名稱中。

在您的本機終端機或命令提示字元中,於空白資料夾中執行此 azd init 命令:

azd init --template functions-quickstart-typescript-azd-eventhub -e eventhub-ts

此指令會從 template 儲存庫 拉取專案檔案,並在目前資料夾中初始化專案。 -e 旗標會設定目前環境的名稱。 在 azd 中,該環境會為您的應用程式維護一個唯一的部署內容,而您可以定義多個部署內容。 環境名稱也會用在你在 Azure 建立的資源群組名稱中。

在您的本機終端機或命令提示字元中,於空白資料夾中執行此 azd init 命令:

azd init --template functions-quickstart-python-azd-eventhub -e eventhub-py

此指令會從 template 儲存庫 拉取專案檔案,並在目前資料夾中初始化專案。 -e 旗標會設定目前環境的名稱。 在 azd 中,該環境會為您的應用程式維護一個唯一的部署內容,而您可以定義多個部署內容。 環境名稱也會用在你在 Azure 建立的資源群組名稱中。

建立並啟用虛擬環境

在根資料夾中,執行下列命令來建立並啟用名為 .venv 的虛擬環境:

python3 -m venv .venv
source .venv/bin/activate

如果 Python 沒有在你的 Linux 發行版安裝 venv 套件,請執行以下指令:

sudo apt-get install python3-venv

在您的本機終端機或命令提示字元中,於空白資料夾中執行此 azd init 命令:

azd init --template functions-quickstart-java-azd-eventhub -e eventhub-java

此指令會從 template 儲存庫 拉取專案檔案,並在目前資料夾中初始化專案。 -e 旗標會設定目前環境的名稱。 在 azd 中,該環境會為您的應用程式維護一個唯一的部署內容,而您可以定義多個部署內容。 環境名稱也會用在你在 Azure 建立的資源群組名稱中。

在您的本機終端機或命令提示字元中,於空白資料夾中執行此 azd init 命令:

azd init --template functions-quickstart-javascript-azd-eventhub -e eventhub-js

此指令會從 template 儲存庫 拉取專案檔案,並在目前資料夾中初始化專案。 -e 旗標會設定目前環境的名稱。 在 azd 中,該環境會為您的應用程式維護一個唯一的部署內容,而您可以定義多個部署內容。 環境名稱也會用在你在 Azure 建立的資源群組名稱中。

在您的本機終端機或命令提示字元中,於空白資料夾中執行此 azd init 命令:

azd init --template functions-quickstart-powershell-azd-eventhub -e eventhub-ps

此指令會從 template 儲存庫 拉取專案檔案,並在目前資料夾中初始化專案。 -e 旗標會設定目前環境的名稱。 在 azd 中,該環境會為您的應用程式維護一個唯一的部署內容,而您可以定義多個部署內容。 環境名稱也會用在你在 Azure 建立的資源群組名稱中。

創建 Azure 資源

在你能在本地執行函式之前,你需要在 Azure 中建立一個 Event Hubs 命名空間和一個 Hub。 用 azd provision 來建立這些資源,並透過新增所需的 local.settings.json 檔案來設定本地設定。

  1. 執行下列命令以登入 Azure:

    azd auth login
    

    依照指示使用 Azure 帳號進行驗證。

  2. 從根目錄執行以下指令來建立你的 Azure 資源:

    azd provision
    
  3. 出現提示時,請提供這些必要的部署參數:

    參數 說明
    Azure 訂用帳戶 訂閱制,讓你創建資源。
    Azure 位置 Azure 區域,用來建立包含新 Azure 資源的資源群組。 只會顯示目前支援彈性使用量方案的區域。
    vnetEnabled 使用數值 False 以避免建立虛擬網路資源時的額外開銷。

    此 azd provision 指令建立所需的 Azure 資源,包括事件中心命名空間與樞紐、Flex Consumption 功能應用程式、Application Insights 以及儲存帳號。 它也會用 Event Hubs 的連線資訊來設定你的 local.settings.json 檔案。

在您的本機環境中執行

  1. 在另一個終端機視窗中,啟動 Azurite 儲存模擬器:

    azurite
    

    本機 Functions 主機程序會使用 Azurite 模擬器,作為執行階段所需之內部儲存體連線 (AzureWebJobsStorage)。

  1. 要啟動函式應用程式,請在終端機或命令提示字元執行以下指令,前往 src 專案資料夾並啟動函式應用程式:

    cd src
    func start
    
  1. 要啟動函式應用程式,請在終端機或命令提示字元執行以下指令:

    func start
    
  1. 要建立並啟動函式應用程式,請在終端機或命令提示字元執行以下指令:

    mvn clean package
    mvn azure-functions:run
    
  1. 要安裝依賴項並啟動函式應用,請在終端機或命令提示字元視窗中執行以下指令:

    npm install
    npm start  
    
  1. 要安裝依賴項並啟動函式應用,請在終端機或命令提示字元視窗中執行以下指令:

    cd src
    npm install
    npm start  
    
  1. 要啟動函式應用程式,請在終端機或命令提示字元執行以下指令:

    func start
    
  1. 若有提示,允許透過防火牆呼叫核心工具(func.exe)。

  2. 當 Functions 主機在你本地專案資料夾啟動時,它會把你的函式資訊寫入終端機輸出。

    此範例包含計時器觸發功能,每 10 秒自動產生新聞文章並傳送至事件中心。 事件中心觸發功能接著處理這些事件,並執行情緒分析與互動追蹤。

    你會看到類似這個範例的輸出:

     [2026-03-02T22:37:30.151Z] Executing 'Functions.EventHubsTrigger'
     [2026-03-02T22:37:30.159Z] Trigger Details: PartitionId: 24, OffsetString: 0, EnqueueTimeUtc: 2026-03-02T22:37:29.1790000+00:00, SequenceNumber: 0, Count: 1, Offset: 0, PartionId: 24
     [2026-03-02T22:37:30.169Z] ⭐ High-engagement article NEWS-20260302-0580CB82 (Views: 6123, Sentiment: 0.57) featured!
     [2026-03-02T22:37:30.174Z] 🔥 Viral article: NEWS-20260302-0580CB82 - 6,123 views
     [2026-03-02T22:37:30.181Z] 🌟 Featured article: NEWS-20260302-0580CB82
     [2026-03-02T22:37:30.185Z] ✅ Successfully processed article NEWS-20260302-0580CB82 - 'Technology Breakthrough in Renewable Energy Technology' by Sarah Johnson
     [2026-03-02T22:37:30.191Z] 📰 Processed 1 news articles, 0 failed in batch of 1
     [2026-03-02T22:37:30.196Z] 📊 NEWS BATCH SUMMARY: 1 articles | Total Views: 6,123 | Avg Views: 6,123 | Avg Sentiment: 0.57 | Status: [Featured: 1]
     [2026-03-02T22:37:30.200Z] 📂 Top Categories: [Health: 1] | Top Sources: [Innovation Weekly: 1]
     [2026-03-02T22:37:30.204Z] 🔥 Viral articles in batch: 1
     [2026-03-02T22:37:30.207Z] Executed 'Functions.EventHubsTrigger' (Succeeded, Duration=55ms)
     
  3. 當您完成時,請在終端機視窗中按 Ctrl+C 以停止 func.exe 主機程序。

  4. 關閉 Azurite 正在運行的視窗。

  1. 執行 deactivate 以關閉虛擬環境。

檢閱程式碼 (選用)

你可以查看定義事件中心觸發函數的程式碼:

using System.Text.Json;
using Azure.Messaging.EventHubs;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace function_app;

public class EventHubsTrigger
{
    private readonly ILogger<EventHubsTrigger> _logger;
    private readonly NewsProcessingService _newsService;

    public EventHubsTrigger(ILogger<EventHubsTrigger> logger, NewsProcessingService newsService)
    {
        _logger = logger;
        _newsService = newsService;
    }

    [Function(nameof(EventHubsTrigger))]
    public async Task Run([EventHubTrigger("news", Connection = "EventHubConnection")] EventData[] input)
    {
        var processedArticles = new List<NewsArticle>();
        var failedEvents = 0;
        
        foreach (var message in input)
        {
            try
            {
                var messageBody = message.EventBody.ToString();

                // Parse the news article event
                var article = ParseNewsArticleEvent(messageBody);

                if (article != null)
                {
                    processedArticles.Add(article);
                }
                else
                {
                    failedEvents++;
                }
            }
            catch (Exception ex)
            {
                failedEvents++;
                _logger.LogWarning($"Error processing message: {ex.Message}");
            }
        }

        // Log summary of this execution
        _logger.LogInformation($"📰 Processed {processedArticles.Count} news articles, {failedEvents} failed in batch of {input.Length}");

你可以查看完整的範本專案here。

package com.function;

import com.microsoft.azure.functions.*;
import com.microsoft.azure.functions.annotation.*;

import java.time.Instant;
import java.util.*;
import java.util.logging.Logger;

/**
 * Azure Function that processes messages from an input Event Hub,
 * adds metadata, and sends processed messages to an output Event Hub.
 */
public class EventHubsTriggerFunction {

    @FunctionName("EventHubsTrigger")
    public void run(
            @EventHubTrigger(
                name = "messages",
                eventHubName = "%INPUT_EVENTHUB_NAME%",
                connection = "EventHubConnection",
                cardinality = Cardinality.MANY)
            List<String> messages,
            @EventHubOutput(
                name = "output",
                eventHubName = "%OUTPUT_EVENTHUB_NAME%",
                connection = "EventHubConnection")
            OutputBinding<List<String>> output,
            final ExecutionContext context) {

        Logger logger = context.getLogger();
        logger.info(String.format("🔄 Event hub function processing %d message(s)", messages.size()));

        List<String> processedMessages = new ArrayList<>();

        for (String message : messages) {
            try {
                logger.info("📨 Processing event: " + message);

                // Create processed message with additional metadata
                String processedMessage = String.format(
                    "{\"id\":\"%s\",\"message\":%s,\"timestamp\":\"%s\"}",
                    UUID.randomUUID().toString(),
                    message,
                    Instant.now().toString());

                processedMessages.add(processedMessage);
                logger.info("\u2728 Message processed: " + processedMessage);

            } catch (Exception e) {
                logger.severe("\u274C Error processing message: " + e.getMessage());
            }
        }

        // Send processed messages to output Event Hub
        if (!processedMessages.isEmpty()) {
            output.setValue(processedMessages);
            logger.info(String.format("📤 Sent %d message(s) to output Event Hub", processedMessages.size()));
        }
    }
}

你可以查看完整的範本專案here。

const { app, output } = require("@azure/functions");

const eventHubOutput = output.eventHub({
    connection: 'EventHubConnection',
    eventHubName: '%OUTPUT_EVENTHUB_NAME%'
});

async function EventHubsTrigger(messages, context) {
    context.log(`🔄 Event hub function processing ${messages.length} message(s)`);
    
    const processedMessages = [];
    
    for (const message of messages) {
        try {
            // Parse the incoming message
            const eventData = typeof message === 'string' ? JSON.parse(message) : message;
            context.log('📨 Processing event:', eventData);
            
            // Create processed message with additional metadata
            const processedMessage = {
                id: eventData.id || crypto.randomUUID(),
                message: eventData.message || JSON.stringify(eventData),
                timestamp: new Date().toISOString()
            };
            
            processedMessages.push(processedMessage);
            context.log('✨ Message processed:', processedMessage);
            
        } catch (error) {
            context.error(`❌ Error processing message: ${error}`);
        }
    }
    
    // Send processed messages to output Event Hub
    if (processedMessages.length > 0) {
        context.extraOutputs.set(eventHubOutput, processedMessages);
        context.log(`📤 Sent ${processedMessages.length} message(s) to output Event Hub`);
    }
}

app.eventHub('EventHubsTrigger', {
    connection: 'EventHubConnection',
    eventHubName: '%INPUT_EVENTHUB_NAME%',
    cardinality: 'many',
    extraOutputs: [eventHubOutput],
    handler: EventHubsTrigger
});

你可以查看完整的範本專案here。

import { app, InvocationContext, output } from "@azure/functions";

interface EventMessage {
    id: string;
    message: string;
    timestamp: string;
}

const eventHubOutput = output.eventHub({
    connection: 'EventHubConnection',
    eventHubName: '%OUTPUT_EVENTHUB_NAME%'
});

export async function EventHubsTrigger(messages: unknown[], context: InvocationContext): Promise<void> {
    context.log(`🔄 Event hub function processing ${messages.length} message(s)`);
    
    const processedMessages: EventMessage[] = [];
    
    for (const message of messages) {
        try {
            // Parse the incoming message
            const eventData = typeof message === 'string' ? JSON.parse(message) : message;
            context.log('📨 Processing event:', eventData);
            
            // Create processed message with additional metadata
            const processedMessage: EventMessage = {
                id: eventData.id || crypto.randomUUID(),
                message: eventData.message || JSON.stringify(eventData),
                timestamp: new Date().toISOString()
            };
            
            processedMessages.push(processedMessage);
            context.log('✨ Message processed:', processedMessage);
            
        } catch (error) {
            context.error(`❌ Error processing message: ${error}`);
        }
    }
    
    // Send processed messages to output Event Hub
    if (processedMessages.length > 0) {
        context.extraOutputs.set(eventHubOutput, processedMessages);
        context.log(`📤 Sent ${processedMessages.length} message(s) to output Event Hub`);
    }
}

app.eventHub('EventHubsTrigger', {
    connection: 'EventHubConnection',
    eventHubName: '%INPUT_EVENTHUB_NAME%',
    cardinality: 'many',
    extraOutputs: [eventHubOutput],
    handler: EventHubsTrigger
});

你可以查看完整的範本專案here。

param($InputEvents, $TriggerMetadata)

Write-Host "🔄 Event hub function processing $($InputEvents.Count) message(s)"

$processedMessages = @()

foreach ($message in $InputEvents) {
    try {
        # Parse the incoming message
        $eventData = $message | ConvertFrom-Json -ErrorAction SilentlyContinue
        if (-not $eventData) {
            $eventData = @{ message = $message }
        }

        Write-Host "📨 Processing event: $($eventData | ConvertTo-Json -Compress)"

        # Create processed message with additional metadata
        $processedMessage = @{
            id        = if ($eventData.id) { $eventData.id } else { [guid]::NewGuid().ToString() }
            message   = if ($eventData.message) { $eventData.message } else { ($eventData | ConvertTo-Json -Compress) }
            timestamp = (Get-Date).ToUniversalTime().ToString('o')
        }

        $processedMessages += $processedMessage
        Write-Host "✨ Message processed: $($processedMessage | ConvertTo-Json -Compress)"
    }
    catch {
        Write-Error "❌ Error processing message: $_"
    }
}

# Send processed messages to output Event Hub
if ($processedMessages.Count -gt 0) {
    Push-OutputBinding -Name OutputEvents -Value ($processedMessages | ConvertTo-Json -Compress)
    Write-Host "📤 Sent $($processedMessages.Count) message(s) to output Event Hub"
}

觸發器定義於對應的 function.json。

你可以查看完整的範本專案here。

import azure.functions as func
import logging
import json
from datetime import datetime, timezone
import random
import uuid
from typing import List

app = func.FunctionApp()

# News article data model
class NewsArticle:
            title=random.choice(titles_templates).format(topic=topic),
            content=f"Comprehensive coverage of the latest developments in {topic}. " * random.randint(10, 20),
            author=random.choice(authors),
            source=random.choice(sources),
            category=random.choice(categories),
            published_date=datetime.now(timezone.utc),
            view_count=random.randint(100, 10000),
            sentiment_score=round(random.uniform(-1.0, 1.0), 2),
            status=random.choice(["Published", "Featured"]),
            tags=[random.choice(topics) for _ in range(random.randint(3, 5))]
        )
        articles.append(article)
    
    # Send articles to Event Hub
    events_json = json.dumps([article.to_dict() for article in articles])
    event.set(events_json)
    
    logging.info(f'✅ HIGH-THROUGHPUT: Successfully generated {num_articles} news articles in ~10 seconds')


# Event Hub trigger - processes news articles
@app.event_hub_message_trigger(arg_name="events", event_hub_name="news",
                                connection="EventHubConnection")
def EventHubsTrigger(events: List[func.EventHubEvent]):
    """Process news articles from Event Hub with sentiment analysis and engagement tracking"""
    
    # Handle both single event and list of events
    if not isinstance(events, list):
        events = [events]
    
    batch_articles = []
    failed_count = 0
    
    for event in events:
        try:
            # Parse the event data
            event_data = json.loads(event.get_body().decode('utf-8'))
            
            # Handle both single article and array of articles
            articles = event_data if isinstance(event_data, list) else [event_data]
            
            for article_data in articles:
                # Process each article
                article_id = article_data.get('ArticleId')
                title = article_data.get('Title')
                author = article_data.get('Author')

你可以查看完整的範本專案here。

在你本地驗證功能後,就可以發佈到 Azure。

部署至 Azure

此專案已設定為使用 azd up 命令,將程式碼部署至 Azure 之彈性使用量方案中的新函數應用程式。 既然你已經配置好資源,這個指令會把你的程式碼部署到現有的函式應用程式。

小提示

此專案包含一組 Bicep 檔案,azd 會使用它們來建立遵循最佳做法、可安全部署到彈性使用量方案的部署。

從 repository root 資料夾執行以下指令,將你的程式碼專案部署到 Azure 的函式應用程式中:

azd deploy

部署會把你的程式碼打包並部署到 function 應用程式。 指令完成後,你會看到連結到你建立的資源。

確認部署

部署完成後,您的 Event Hubs 觸發程序函式會在 Event Hub 中有事件到達時,自動開始處理事件。

  1. 在 Azure 入口網站,進入你的新函數應用。

  2. 從左側選單選擇 日誌串流 ,即可即時監控你的函式執行。

  3. 你會看到日誌條目,顯示你的事件中心觸發函數正在處理由計時器觸發產生的事件。

重新部署程式碼

請重複執行 azd up 指令,以便同時配置 Azure 資源並將程式碼更新部署到函數應用程式。

備註

最新的部署套件一律會覆寫已部署的程式碼檔案。

您對 azd 提示的初始回應,以及 azd 所產生的任何環境變數都會儲存在本機的具名環境中。 使用 azd env get-values 命令來檢閱您環境中建立 Azure 資源時所使用的所有變數。

清理資源

當你完成函式應用程式及相關資源的運作後,請使用此指令從 Azure 刪除函式應用程式及其相關資源,避免產生任何額外費用:

azd down --no-prompt

備註

--no-prompt 選項會指示 azd 刪除您的資源群組,而不需要您確認。

此命令不會影響您的本機程式碼專案。