Inicio rápido: Procesamiento de eventos en tiempo real mediante Azure Functions

En este artículo, usará la CLI para desarrolladores de Azure (azd) para crear una función de desencadenador de Event Hubs para el procesamiento de eventos en tiempo real en Azure Functions. Después de comprobar el código localmente, se implementa en una nueva aplicación de funciones sin servidor que se ejecuta en un plan de consumo flexible en Azure.

El origen del proyecto usa azd para crear la aplicación de funciones y los recursos relacionados y para implementar el código en Azure. Esta implementación sigue los procedimientos recomendados actuales para implementaciones de Azure Functions seguras y escalables.

De forma predeterminada, el plan flex Consumption sigue un modelo de facturación de pago por uso , lo que significa que puede completar este artículo y solo incurrirá en un pequeño costo de unos pocos centavos de USD o menos en su cuenta de Azure.

En este artículo se admite la versión 4 del modelo de programación de Node.js para Azure Functions.

En este artículo se admite la versión 2 del modelo de programación de Python para Azure Functions.

Prerrequisitos

  • kit para desarrolladores de Java 21
    • Establezca la variable de entorno JAVA_HOME en la ubicación de instalación de la versión correcta del kit de desarrollo de Java (JDK).
  • Apache Maven 3.8.x

Inicialización del proyecto

Use el azd init comando para crear un proyecto de código local de Azure Functions a partir de una plantilla.

En el terminal local o el símbolo del sistema, ejecute este comando azd init en una carpeta vacía:

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

Este comando extrae los archivos del proyecto del repositorio template e inicializa el proyecto en la carpeta actual. La marca -e establece un nombre para el entorno actual. En azd, el entorno mantiene un contexto de implementación único para la aplicación y puede definir más de uno. El nombre del entorno también se usa en el nombre del grupo de recursos que crea en Azure.

En el terminal local o el símbolo del sistema, ejecute este comando azd init en una carpeta vacía:

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

Este comando extrae los archivos del proyecto del repositorio template e inicializa el proyecto en la carpeta actual. La marca -e establece un nombre para el entorno actual. En azd, el entorno mantiene un contexto de implementación único para la aplicación y puede definir más de uno. El nombre del entorno también se usa en el nombre del grupo de recursos que crea en Azure.

En el terminal local o el símbolo del sistema, ejecute este comando azd init en una carpeta vacía:

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

Este comando extrae los archivos del proyecto del repositorio template e inicializa el proyecto en la carpeta actual. La marca -e establece un nombre para el entorno actual. En azd, el entorno mantiene un contexto de implementación único para la aplicación y puede definir más de uno. El nombre del entorno también se usa en el nombre del grupo de recursos que crea en Azure.

Creación y activación de un entorno virtual

En la carpeta raíz, ejecute estos comandos para crear y activar un entorno virtual denominado .venv:

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

Si Python no instala el paquete venv en la distribución de Linux, ejecute el siguiente comando:

sudo apt-get install python3-venv

En el terminal local o el símbolo del sistema, ejecute este comando azd init en una carpeta vacía:

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

Este comando extrae los archivos del proyecto del repositorio template e inicializa el proyecto en la carpeta actual. La marca -e establece un nombre para el entorno actual. En azd, el entorno mantiene un contexto de implementación único para la aplicación y puede definir más de uno. El nombre del entorno también se usa en el nombre del grupo de recursos que crea en Azure.

En el terminal local o el símbolo del sistema, ejecute este comando azd init en una carpeta vacía:

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

Este comando extrae los archivos del proyecto del repositorio template e inicializa el proyecto en la carpeta actual. La marca -e establece un nombre para el entorno actual. En azd, el entorno mantiene un contexto de implementación único para la aplicación y puede definir más de uno. El nombre del entorno también se usa en el nombre del grupo de recursos que crea en Azure.

En el terminal local o el símbolo del sistema, ejecute este comando azd init en una carpeta vacía:

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

Este comando extrae los archivos del proyecto del repositorio template e inicializa el proyecto en la carpeta actual. La marca -e establece un nombre para el entorno actual. En azd, el entorno mantiene un contexto de implementación único para la aplicación y puede definir más de uno. El nombre del entorno también se usa en el nombre del grupo de recursos que crea en Azure.

Creación de recursos de Azure

Para poder ejecutar la función localmente, debe crear un espacio de nombres y un centro de Event Hubs en Azure. Use azd provision para crear estos recursos y configurar la configuración local agregando el archivo local.settings.json necesario.

  1. Ejecute el comando siguiente para iniciar sesión en Azure:

    azd auth login
    

    Siga las indicaciones para autenticarse mediante su cuenta de Azure.

  2. En la carpeta raíz, ejecute el siguiente comando para crear los recursos de Azure:

    azd provision
    
  3. Cuando se le solicite, proporcione estos parámetros de implementación necesarios:

    Parámetro Descripción
    Suscripción a Azure Suscripción en la que creas tus recursos.
    Ubicación de Azure Región de Azure en la que se creará el grupo de recursos que contiene los nuevos recursos de Azure. Solo se muestran las regiones que admiten actualmente el Plan de consumo flexible.
    vnetEnabled Use un valor de False para evitar la sobrecarga adicional de crear recursos de red virtual.

    El comando azd provision crea los recursos necesarios de Azure, incluido un espacio de nombres y un centro de Event Hubs, una aplicación de función Consumo flexible, Application Insights y una cuenta de almacenamiento. También configura el archivo local.settings.json con la información de conexión de Event Hubs.

Ejecución en el entorno local

  1. En una ventana de terminal independiente, inicie el emulador de almacenamiento de Azurite:

    azurite
    

    El proceso de host local de Functions utiliza el emulador de Azurite para la conexión de almacenamiento interna (AzureWebJobsStorage) requerida por el tiempo de ejecución.

  1. Para iniciar la aplicación de funciones, ejecute estos comandos en un terminal o símbolo del sistema para ir a la carpeta del proyecto src e iniciar la aplicación de funciones:

    cd src
    func start
    
  1. Para iniciar la aplicación de funciones, ejecute este comando en un terminal o símbolo del sistema:

    func start
    
  1. Para compilar e iniciar la aplicación de funciones, ejecute estos comandos en un terminal o editor de comandos:

    mvn clean package
    mvn azure-functions:run
    
  1. Para instalar las dependencias e iniciar la aplicación de funciones, ejecute estos comandos en un terminal o símbolo del sistema:

    npm install
    npm start  
    
  1. Para instalar las dependencias e iniciar la aplicación de funciones, ejecute estos comandos en un terminal o símbolo del sistema:

    cd src
    npm install
    npm start  
    
  1. Para iniciar la aplicación de funciones, ejecute este comando en un terminal o símbolo del sistema:

    func start
    
  1. Si se le solicita, permita que se llame a Core Tools (func.exe) a través del firewall.

  2. Cuando el host de Functions se inicia en la carpeta del proyecto local, escribe información sobre las funciones en la salida del terminal.

    Este ejemplo incluye una función de desencadenador de temporizador que genera automáticamente artículos de noticias cada 10 segundos y los envía a Event Hubs. A continuación, la función de desencadenador de Event Hubs procesa estos eventos y realiza el análisis de sentimiento y el seguimiento de la interacción.

    Verá una salida similar a la de este ejemplo:

     [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. Cuando haya terminado, presione Ctrl+C en la ventana del terminal para detener el proceso de host de func.exe.

  4. Cierre la ventana en la que se ejecuta Azurite.

  1. Ejecute deactivate para apagar el entorno virtual.

Revisión del código (opcional)

Puede revisar el código que define la función de desencadenador de Event Hubs:

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}");

Puede revisar el proyecto de plantilla completo 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()));
        }
    }
}

Puede revisar el proyecto de plantilla completo 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
});

Puede revisar el proyecto de plantilla completo 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
});

Puede revisar el proyecto de plantilla completo 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"
}

El desencadenador se define en el function.json correspondiente.

Puede revisar el proyecto de plantilla completo 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')

Puede revisar el proyecto de plantilla completo here.

Después de comprobar la función localmente, es el momento de publicarla en Azure.

Implementar en Azure

Este proyecto está configurado para usar el comando azd up para implementar tu código en una nueva aplicación de funciones en un plan de consumo flexible en Azure. Puesto que ya ha aprovisionado recursos, este comando implementa el código en la aplicación de funciones existente.

Sugerencia

Este proyecto incluye un conjunto de archivos de Bicep que azd usa para crear una implementación segura en un plan de Consumo flexible que sigue los procedimientos recomendados.

En la carpeta raíz del repositorio, ejecute el siguiente comando para implementar el proyecto de código en la aplicación de funciones en Azure:

azd deploy

La implementación empaqueta tu código y lo implementa en la aplicación de función. Cuando finalice el comando, verá vínculos a los recursos que creó.

Comprobación de la implementación

Una vez finalizada la implementación, la función de desencadenador de Event Hubs inicia automáticamente el procesamiento de eventos a medida que llegan al centro de eventos.

  1. En Azure Portal, vaya a la nueva aplicación de funciones.

  2. Seleccione Flujo de registro en el menú de la izquierda para supervisar las ejecuciones de funciones en tiempo real.

  3. Verá entradas de registro que muestran cómo su función de desencadenador de Event Hubs procesa eventos generados por el desencadenador de temporizador.

Reimplementación del código

Ejecute el comando azd up tantas veces como necesite aprovisionar los recursos de Azure e implementar actualizaciones de código en la aplicación de funciones.

Nota:

El paquete de implementación más reciente siempre sobrescribe los archivos de código implementados.

Las respuestas iniciales a azd mensajes y las variables de entorno generadas por azd se almacenan localmente en el entorno con nombre. Use el comando azd env get-values para revisar todas las variables del entorno que se usaron al crear recursos de Azure.

Limpieza de recursos

Cuando haya terminado de trabajar con la aplicación de funciones y los recursos relacionados, use este comando para eliminar la aplicación de funciones y sus recursos relacionados de Azure y evitar incurrir en costos adicionales:

azd down --no-prompt

Nota:

La --no-prompt opción indica azd que elimine el grupo de recursos sin una confirmación de usted.

Este comando no afecta al proyecto de código local.