azure-functions

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Azure Functions

Azure Functions

Overview

概述

Azure Functions enables serverless computing on Microsoft Azure. Build event-driven applications with automatic scaling, flexible bindings to various Azure services, and integrated monitoring through Application Insights.
Azure Functions 可在Microsoft Azure上实现无服务器计算。借助自动缩放、与各类Azure服务的灵活绑定以及通过Application Insights实现的集成监控,构建事件驱动型应用。

When to Use

适用场景

  • HTTP APIs and webhooks
  • Message-driven processing (Service Bus, Event Hub)
  • Scheduled jobs and CRON expressions
  • File and blob processing
  • Queue-based workflows
  • Real-time data processing
  • Microservices and backend logic
  • Integration with Azure ecosystem services
  • HTTP API与Webhook
  • 消息驱动处理(Service Bus、Event Hub)
  • 定时任务与CRON表达式
  • 文件与Blob处理
  • 基于队列的工作流
  • 实时数据处理
  • 微服务与后端逻辑
  • 与Azure生态系统服务集成

Implementation Examples

实现示例

1. Azure Function Creation with Azure CLI

1. 使用Azure CLI创建Azure Function

bash
undefined
bash
undefined

Install Azure Functions Core Tools

Install Azure Functions Core Tools

Login to Azure

Login to Azure

az login
az login

Create resource group

Create resource group

az group create --name myapp-rg --location eastus
az group create --name myapp-rg --location eastus

Create storage account (required for Functions)

Create storage account (required for Functions)

az storage account create
--name myappstore
--location eastus
--resource-group myapp-rg
--sku Standard_LRS
az storage account create
--name myappstore
--location eastus
--resource-group myapp-rg
--sku Standard_LRS

Create Function App

Create Function App

az functionapp create
--resource-group myapp-rg
--consumption-plan-location eastus
--runtime node
--runtime-version 18
--functions-version 4
--name myapp-function
--storage-account myappstore
az functionapp create
--resource-group myapp-rg
--consumption-plan-location eastus
--runtime node
--runtime-version 18
--functions-version 4
--name myapp-function
--storage-account myappstore

Create function in app

Create function in app

func new --name HttpTrigger --template "HTTP trigger"
func new --name HttpTrigger --template "HTTP trigger"

Configure authentication

Configure authentication

az functionapp auth update
--resource-group myapp-rg
--name myapp-function
--enabled true
--action RedirectToLoginPage
--default-provider AzureActiveDirectory
az functionapp auth update
--resource-group myapp-rg
--name myapp-function
--enabled true
--action RedirectToLoginPage
--default-provider AzureActiveDirectory

Deploy function

Deploy function

func azure functionapp publish myapp-function
func azure functionapp publish myapp-function

Check deployment

Check deployment

az functionapp list --output table
az functionapp list --output table

Get function details

Get function details

az functionapp function show
--resource-group myapp-rg
--name myapp-function
--function-name HttpTrigger
undefined
az functionapp function show
--resource-group myapp-rg
--name myapp-function
--function-name HttpTrigger
undefined

2. Azure Function Implementation (Node.js)

2. Azure Function的Node.js实现

javascript
// HttpTrigger/index.js
module.exports = async function (context, req) {
  context.log('HTTP trigger function processed request.');

  // Extract request data
  const name = req.query.name || (req.body && req.body.name);
  const requestId = context.traceContext.traceparent;

  try {
    // Validate input
    if (!name) {
      return {
        status: 400,
        body: { error: 'Name parameter is required' }
      };
    }

    // Business logic
    const response = {
      message: `Hello ${name}!`,
      timestamp: new Date().toISOString(),
      requestId: requestId
    };

    // Log to Application Insights
    context.log({
      level: 'info',
      message: 'Request processed successfully',
      name: name,
      requestId: requestId
    });

    return {
      status: 200,
      headers: {
        'Content-Type': 'application/json',
        'X-Request-ID': requestId
      },
      body: response
    };
  } catch (error) {
    context.log.error('Error processing request:', error);

    return {
      status: 500,
      body: { error: 'Internal server error' }
    };
  }
};

// TimerTrigger/index.js
module.exports = async function (context, myTimer) {
  const timeStamp = new Date().toISOString();

  if (myTimer.isPastDue) {
    context.log('Timer function is running late!');
  }

  // Process scheduled job
  context.log(`Timer trigger function ran at ${timeStamp}`);
  context.log('Processing batch job...');

  // Simulate work
  await new Promise(resolve => setTimeout(resolve, 1000));

  context.log('Batch job completed');
};

// ServiceBusQueueTrigger/index.js
module.exports = async function (context, mySbMsg) {
  context.log('ServiceBus queue trigger function processed message:', mySbMsg);

  try {
    const messageBody = typeof mySbMsg === 'string' ? JSON.parse(mySbMsg) : mySbMsg;

    // Process message
    await processMessage(messageBody);

    context.log('Message processed successfully');
  } catch (error) {
    context.log.error('Error processing message:', error);
    throw error; // Re-queue message
  }
};

async function processMessage(messageBody) {
  // Business logic here
  return true;
}
javascript
// HttpTrigger/index.js
module.exports = async function (context, req) {
  context.log('HTTP trigger function processed request.');

  // Extract request data
  const name = req.query.name || (req.body && req.body.name);
  const requestId = context.traceContext.traceparent;

  try {
    // Validate input
    if (!name) {
      return {
        status: 400,
        body: { error: 'Name parameter is required' }
      };
    }

    // Business logic
    const response = {
      message: `Hello ${name}!`,
      timestamp: new Date().toISOString(),
      requestId: requestId
    };

    // Log to Application Insights
    context.log({
      level: 'info',
      message: 'Request processed successfully',
      name: name,
      requestId: requestId
    });

    return {
      status: 200,
      headers: {
        'Content-Type': 'application/json',
        'X-Request-ID': requestId
      },
      body: response
    };
  } catch (error) {
    context.log.error('Error processing request:', error);

    return {
      status: 500,
      body: { error: 'Internal server error' }
    };
  }
};

// TimerTrigger/index.js
module.exports = async function (context, myTimer) {
  const timeStamp = new Date().toISOString();

  if (myTimer.isPastDue) {
    context.log('Timer function is running late!');
  }

  // Process scheduled job
  context.log(`Timer trigger function ran at ${timeStamp}`);
  context.log('Processing batch job...');

  // Simulate work
  await new Promise(resolve => setTimeout(resolve, 1000));

  context.log('Batch job completed');
};

// ServiceBusQueueTrigger/index.js
module.exports = async function (context, mySbMsg) {
  context.log('ServiceBus queue trigger function processed message:', mySbMsg);

  try {
    const messageBody = typeof mySbMsg === 'string' ? JSON.parse(mySbMsg) : mySbMsg;

    // Process message
    await processMessage(messageBody);

    context.log('Message processed successfully');
  } catch (error) {
    context.log.error('Error processing message:', error);
    throw error; // Re-queue message
  }
};

async function processMessage(messageBody) {
  // Business logic here
  return true;
}

3. Azure Functions with Terraform

3. 使用Terraform部署Azure Functions

hcl
undefined
hcl
undefined

functions.tf

functions.tf

terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = "~> 3.0" } } }
provider "azurerm" { features { virtual_machine { delete_os_disk_on_delete = true graceful_shutdown = false skip_shutdown_and_force_delete = false } } }
variable "environment" { default = "dev" }
variable "location" { default = "eastus" }
terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = "~> 3.0" } } }
provider "azurerm" { features { virtual_machine { delete_os_disk_on_delete = true graceful_shutdown = false skip_shutdown_and_force_delete = false } } }
variable "environment" { default = "dev" }
variable "location" { default = "eastus" }

Resource group

Resource group

resource "azurerm_resource_group" "main" { name = "myapp-rg-${var.environment}" location = var.location }
resource "azurerm_resource_group" "main" { name = "myapp-rg-${var.environment}" location = var.location }

Storage account for Function App

Storage account for Function App

resource "azurerm_storage_account" "function_storage" { name = "myappstore${var.environment}" resource_group_name = azurerm_resource_group.main.name location = azurerm_resource_group.main.location account_tier = "Standard" account_replication_type = "LRS"
identity { type = "SystemAssigned" }
tags = { environment = var.environment } }
resource "azurerm_storage_account" "function_storage" { name = "myappstore${var.environment}" resource_group_name = azurerm_resource_group.main.name location = azurerm_resource_group.main.location account_tier = "Standard" account_replication_type = "LRS"
identity { type = "SystemAssigned" }
tags = { environment = var.environment } }

Application Insights

Application Insights

resource "azurerm_application_insights" "main" { name = "myapp-insights-${var.environment}" location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name application_type = "web"
retention_in_days = 30 }
resource "azurerm_application_insights" "main" { name = "myapp-insights-${var.environment}" location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name application_type = "web"
retention_in_days = 30 }

App Service Plan

App Service Plan

resource "azurerm_service_plan" "function_plan" { name = "myapp-plan-${var.environment}" location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name os_type = "Linux" sku_name = "Y1" # Consumption plan
tags = { environment = var.environment } }
resource "azurerm_service_plan" "function_plan" { name = "myapp-plan-${var.environment}" location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name os_type = "Linux" sku_name = "Y1" # Consumption plan
tags = { environment = var.environment } }

Function App

Function App

resource "azurerm_linux_function_app" "main" { name = "myapp-function-${var.environment}" location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name service_plan_id = azurerm_service_plan.function_plan.id
storage_account_name = azurerm_storage_account.function_storage.name storage_account_access_key = azurerm_storage_account.function_storage.primary_access_key
app_settings = { APPINSIGHTS_INSTRUMENTATIONKEY = azurerm_application_insights.main.instrumentation_key APPLICATIONINSIGHTS_CONNECTION_STRING = azurerm_application_insights.main.connection_string AzureWebJobsStorage = azurerm_storage_account.function_storage.primary_blob_connection_string WEBSITE_NODE_DEFAULT_VERSION = "~18" FUNCTIONS_EXTENSION_VERSION = "~4" FUNCTIONS_WORKER_RUNTIME = "node" ENABLE_INIT_LOGGING = true WEBSITE_RUN_FROM_PACKAGE = 1 }
site_config { application_insights_key = azurerm_application_insights.main.instrumentation_key application_insights_connection_string = azurerm_application_insights.main.connection_string
cors {
  allowed_origins = ["https://example.com"]
}

http2_enabled = true
}
https_only = true identity { type = "SystemAssigned" }
tags = { environment = var.environment } }
resource "azurerm_linux_function_app" "main" { name = "myapp-function-${var.environment}" location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name service_plan_id = azurerm_service_plan.function_plan.id
storage_account_name = azurerm_storage_account.function_storage.name storage_account_access_key = azurerm_storage_account.function_storage.primary_access_key
app_settings = { APPINSIGHTS_INSTRUMENTATIONKEY = azurerm_application_insights.main.instrumentation_key APPLICATIONINSIGHTS_CONNECTION_STRING = azurerm_application_insights.main.connection_string AzureWebJobsStorage = azurerm_storage_account.function_storage.primary_blob_connection_string WEBSITE_NODE_DEFAULT_VERSION = "~18" FUNCTIONS_EXTENSION_VERSION = "~4" FUNCTIONS_WORKER_RUNTIME = "node" ENABLE_INIT_LOGGING = true WEBSITE_RUN_FROM_PACKAGE = 1 }
site_config { application_insights_key = azurerm_application_insights.main.instrumentation_key application_insights_connection_string = azurerm_application_insights.main.connection_string
cors {
  allowed_origins = ["https://example.com"]
}

http2_enabled = true
}
https_only = true identity { type = "SystemAssigned" }
tags = { environment = var.environment } }

Key Vault for secrets

Key Vault for secrets

resource "azurerm_key_vault" "function_secrets" { name = "myappkv${var.environment}" location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name tenant_id = data.azurerm_client_config.current.tenant_id sku_name = "standard"
access_policy { tenant_id = data.azurerm_client_config.current.tenant_id object_id = azurerm_linux_function_app.main.identity[0].principal_id
secret_permissions = [
  "Get",
  "List"
]
}
tags = { environment = var.environment } }
resource "azurerm_key_vault" "function_secrets" { name = "myappkv${var.environment}" location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name tenant_id = data.azurerm_client_config.current.tenant_id sku_name = "standard"
access_policy { tenant_id = data.azurerm_client_config.current.tenant_id object_id = azurerm_linux_function_app.main.identity[0].principal_id
secret_permissions = [
  "Get",
  "List"
]
}
tags = { environment = var.environment } }

Store database password in Key Vault

Store database password in Key Vault

resource "azurerm_key_vault_secret" "db_password" { name = "db-password" value = "MySecurePassword123!" key_vault_id = azurerm_key_vault.function_secrets.id }
resource "azurerm_key_vault_secret" "db_password" { name = "db-password" value = "MySecurePassword123!" key_vault_id = azurerm_key_vault.function_secrets.id }

Diagnostic settings

Diagnostic settings

resource "azurerm_monitor_diagnostic_setting" "function_logs" { name = "function-logs" target_resource_id = azurerm_linux_function_app.main.id
log_analytics_workspace_id = azurerm_log_analytics_workspace.main.id
enabled_log { category = "FunctionAppLogs" }
metric { category = "AllMetrics" } }
resource "azurerm_monitor_diagnostic_setting" "function_logs" { name = "function-logs" target_resource_id = azurerm_linux_function_app.main.id
log_analytics_workspace_id = azurerm_log_analytics_workspace.main.id
enabled_log { category = "FunctionAppLogs" }
metric { category = "AllMetrics" } }

Log Analytics Workspace

Log Analytics Workspace

resource "azurerm_log_analytics_workspace" "main" { name = "myapp-logs-${var.environment}" location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name sku = "PerGB2018"
retention_in_days = 30 }
data "azurerm_client_config" "current" {}
output "function_app_url" { value = "https://${azurerm_linux_function_app.main.default_hostname}" }
output "app_insights_key" { value = azurerm_application_insights.main.instrumentation_key sensitive = true }
undefined
resource "azurerm_log_analytics_workspace" "main" { name = "myapp-logs-${var.environment}" location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name sku = "PerGB2018"
retention_in_days = 30 }
data "azurerm_client_config" "current" {}
output "function_app_url" { value = "https://${azurerm_linux_function_app.main.default_hostname}" }
output "app_insights_key" { value = azurerm_application_insights.main.instrumentation_key sensitive = true }
undefined

4. Function Bindings Configuration

4. 函数绑定配置

json
{
  "scriptFile": "index.js",
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": ["get", "post"],
      "route": "api/{*route}"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    },
    {
      "type": "queue",
      "direction": "out",
      "name": "myQueueItem",
      "queueName": "myqueue",
      "connection": "AzureWebJobsStorage"
    },
    {
      "type": "serviceBus",
      "direction": "in",
      "name": "mySbMsg",
      "queueName": "myqueue",
      "connection": "ServiceBusConnection",
      "cardinality": "one"
    },
    {
      "type": "blob",
      "direction": "in",
      "name": "inputBlob",
      "path": "input/{name}",
      "connection": "AzureWebJobsStorage"
    },
    {
      "type": "blob",
      "direction": "out",
      "name": "outputBlob",
      "path": "output/{name}",
      "connection": "AzureWebJobsStorage"
    }
  ]
}
json
{
  "scriptFile": "index.js",
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": ["get", "post"],
      "route": "api/{*route}"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    },
    {
      "type": "queue",
      "direction": "out",
      "name": "myQueueItem",
      "queueName": "myqueue",
      "connection": "AzureWebJobsStorage"
    },
    {
      "type": "serviceBus",
      "direction": "in",
      "name": "mySbMsg",
      "queueName": "myqueue",
      "connection": "ServiceBusConnection",
      "cardinality": "one"
    },
    {
      "type": "blob",
      "direction": "in",
      "name": "inputBlob",
      "path": "input/{name}",
      "connection": "AzureWebJobsStorage"
    },
    {
      "type": "blob",
      "direction": "out",
      "name": "outputBlob",
      "path": "output/{name}",
      "connection": "AzureWebJobsStorage"
    }
  ]
}

Best Practices

最佳实践

✅ DO

✅ 建议

  • Use managed identity for Azure services
  • Store secrets in Key Vault
  • Enable Application Insights
  • Implement idempotent functions
  • Use durable functions for long-running operations
  • Handle exceptions and failures
  • Monitor function execution
  • Use bindings instead of SDK calls
  • 对Azure服务使用托管标识
  • 在Key Vault中存储密钥
  • 启用Application Insights
  • 实现幂等函数
  • 对长时间运行的操作使用Durable Functions
  • 处理异常与故障
  • 监控函数执行情况
  • 使用绑定而非SDK调用

❌ DON'T

❌ 不建议

  • Store secrets in code or configuration
  • Ignore Application Insights
  • Create functions without error handling
  • Use blocking operations
  • Create long-running functions without Durable Functions
  • Ignore monitoring and logging
  • 在代码或配置中存储密钥
  • 忽略Application Insights
  • 创建无错误处理的函数
  • 使用阻塞操作
  • 在未使用Durable Functions的情况下创建长时间运行的函数
  • 忽略监控与日志

Monitoring

监控

  • Application Insights for tracing and metrics
  • Azure Monitor for overall health
  • Log Analytics for log analysis
  • Function metrics (execution count, duration)
  • Custom telemetry and events
  • 使用Application Insights进行追踪与指标收集
  • 使用Azure Monitor查看整体健康状况
  • 使用Log Analytics进行日志分析
  • 函数指标(执行次数、持续时间)
  • 自定义遥测与事件

Resources

相关资源