使用说明
必应接地API
用于Azure AI代理服务的基于FastAPI的REST API和模型上下文协议(MCP)服务器,具有Bing基础功能。通过REST和MCP接口提供基于人工智能的自动引文提取响应。
特性
✅ REST API 基于Bing的Azure AI代理包装器
✅ 模型上下文协议(MCP)服务器 通过Azure API管理
✅ 带引用的结构化JSON响应
✅ 用于多区域部署的区域跟踪元数据
✅ Docker容器化,易于部署
✅ 健康检查端点
✅ Azure容器应用程序就绪
✅ 线程管理和清理
✅ APIM负载平衡与断路器模式
✅ 会话关联性(粘性会话)
✅ 自动故障转移和恢复
✅ 使用Azure Developer CLI(azd)自动部署
✅ 在配置过程中自动创建的12个AI代理
✅ 用于标准化AI工具集成的MCP端点
快速入门:配置并部署到Azure
最快的入门方法是使用Azure Developer CLI:
# 1. Login to Azure
azd auth login
# 2. Create environment (first time only)
azd env new <environment-name>
# 3. Provision and deploy everything
azd up
就是这样! 一个命令可以完成所有事情:
- ✅ 提供所有Azure资源(容器应用程序、AI Foundry、APIM等)
- ✅ 自动创建12个基于Bing的GPT-4o AI代理(新API)
- ✅ 构建和部署Docker容器
- ✅ 配置托管身份和RBAC
- ✅ 使用负载平衡设置API管理
整个过程大约需要8-15分钟。
您的API将在输出中显示的端点处可用。
常用命令
| 命令 | 它的作用 | 何时使用 |
|---|---|---|
azd up |
提供+部署一切 | 用于初始设置和更新 |
azd deploy |
仅部署代码(跳过配置) | 快速更新现有资源的代码 |
azd down |
删除所有Azure资源 | 清理/拆除环境 |
azd env list |
显示可用环境 | 检查存在哪些环境 |
📚 有关详细的配置步骤,请参阅 部署到Azure 在......下面
💡 通过APIM连接MCP服务器:Azure API管理本机将REST API转换为模型上下文协议(MCP)服务器。MCP客户端(如GitHub Copilot、Semantic Kernel或Azure OpenAI Responses API)通过HTTP/SSE传输连接到APIM的MCP端点,以作为标准化工具访问您的API。看 APIM作为MCP服务器 了解详情。
⚠️ 部署后需要手动执行步骤:The
azd deploypostdeploy钩子将显示在APIM门户中创建MCP服务器的说明(1-2分钟)。此步骤目前是手动的,因为ARM/Diber模板中尚未提供MCP服务器资源。
建筑
当前架构:具有代理池的单个项目
graph TB
subgraph External["External Clients"]
Client[LLM Suite / MCP Client]
end
subgraph APIM["Azure API Management"]
Gateway[API Gateway<br/>• Circuit Breaker<br/>• Rate Limiting<br/>• Session Affinity]
end
subgraph ContainerApps["Container Apps Environment"]
CA1[Container App 1<br/>12 Agent Endpoints]
CA2[Container App 2<br/>12 Agent Endpoints]
CA3[Container App 3<br/>12 Agent Endpoints]
end
subgraph Foundry["Azure AI Foundry (Single Project)"]
Project[AI Project]
GPT4O[GPT-4o Deployment<br/>10K TPM Capacity]
subgraph Agents["Agent Pool (12 Agents)"]
Agent1[Agent 1]
Agent2[Agent 2]
Agent12[Agent 12]
end
Bing[Bing Grounding<br/>Connection]
end
Client -->|HTTPS Requests| Gateway
Gateway -->|Load Balance| CA1
Gateway -->|Load Balance| CA2
Gateway -->|Load Balance| CA3
CA1 & CA2 & CA3 -->|Managed Identity| Project
Project --> Agents
Agent1 & Agent2 & Agent12 -->|Use| GPT4O
Agent1 & Agent2 & Agent12 -->|Search| Bing
style Gateway fill:#0078d4,color:#fff
style CA1 fill:#00bcf2,color:#000
style CA2 fill:#00bcf2,color:#000
style CA3 fill:#00bcf2,color:#000
style Project fill:#50e6ff,color:#000
style GPT4O fill:#ff6b6b,color:#fff
style Bing fill:#00b294,color:#fff
特点:
- ✅ TPM容量: 10K TPM(在所有代理之间共享)
- ✅ 代理池: 12个负载分配代理
- ✅ 高可用性: 3个容器应用程序实例
- ✅ APIM负载平衡: 仅跨容器应用程序
- ⚠️ 单个TPM配额: 所有代理共享相同的GPT-4o部署
用例: 开发、试点项目、中等生产工作量(高达约30万次查询/月)
每月费用: 约2000美元(见 成本分析 在......下面
横向扩展策略
随着您的工作负载增长到超过10K TPM容量,您有几个扩展选项。每种策略在复杂性、成本和LLM Suite集成方面都有不同的权衡。
策略1:垂直规模(每个项目增加TPM)
graph TB
subgraph External["External Clients"]
Client[LLM Suite / MCP Client]
end
subgraph APIM["Azure API Management"]
Gateway[API Gateway]
end
subgraph ContainerApps["Container Apps (3 instances)"]
CA[Container Apps<br/>12 Agent Endpoints]
end
subgraph Foundry["Azure AI Foundry (Single Project)"]
Project[AI Project]
GPT4O[GPT-4o Deployment<br/>⬆️ 100K TPM<br/>Provisioned Throughput]
Agents[Agent Pool<br/>12 Agents]
Bing[Bing Grounding]
end
Client -->|HTTPS| Gateway
Gateway -->|Load Balance| CA
CA -->|Managed Identity| Project
Project --> Agents
Agents -->|Use| GPT4O
Agents -->|Search| Bing
style Gateway fill:#0078d4,color:#fff
style CA fill:#00bcf2,color:#000
style GPT4O fill:#ff6b6b,color:#fff
style Project fill:#50e6ff,color:#000
实施:
- 将GPT-4o部署从10K增加到100K TPM(或更高)
- 使用预留吞吐量单位(PTU)保证容量
- 无需更改架构
特点:
- ✅ 最简单的方法 -无代码更改
- ✅ 单端点 LLM套房
- ✅ 高达1M TPM 带PTU
- ⚠️ 成本更高 -PTU定价(约540美元/PTU/月)
- ⚠️ 单点故障 (一个项目)
LLM套件集成:
- 无需更改 -相同的端点结构
- 继续使用
/bing-grounding/gpt4o_{1-12}端点
每月费用: 根据PTU分配,约为5K-50K美元
何时使用: 当您需要快速扩展而无需更改架构时
策略2:多项目横向规模(APIM管理)
graph TB
subgraph External["External Clients"]
Client[LLM Suite / MCP Client<br/>Single Endpoint]
end
subgraph APIM["Azure API Management - Backend Pool"]
Gateway[API Gateway<br/>Round-Robin LB<br/>Circuit Breaker]
end
subgraph Backend1["Environment 1"]
CA1[Container Apps<br/>12 Agents]
Project1[AI Project 1<br/>GPT-4o: 10K TPM]
end
subgraph Backend2["Environment 2"]
CA2[Container Apps<br/>12 Agents]
Project2[AI Project 2<br/>GPT-4o: 10K TPM]
end
subgraph Backend3["Environment 3"]
CA3[Container Apps<br/>12 Agents]
Project3[AI Project 3<br/>GPT-4o: 10K TPM]
end
Client -->|HTTPS| Gateway
Gateway -->|Route 33%| CA1
Gateway -->|Route 33%| CA2
Gateway -->|Route 34%| CA3
CA1 --> Project1
CA2 --> Project2
CA3 --> Project3
style Gateway fill:#0078d4,color:#fff
style CA1 fill:#00bcf2,color:#000
style CA2 fill:#00bcf2,color:#000
style CA3 fill:#00bcf2,color:#000
style Project1 fill:#50e6ff,color:#000
style Project2 fill:#50e6ff,color:#000
style Project3 fill:#50e6ff,color:#000
实施:
-
部署多个环境:
# Create 3 separate environments azd env new prod-foundry-1 azd up azd env new prod-foundry-2 azd up azd env new prod-foundry-3 azd up -
配置APIM后端池:
<backends> <backend id="foundry-pool"> <backend> <url>https://ca-foundry1.azurecontainerapps.io</url> </backend> <backend> <url>https://ca-foundry2.azurecontainerapps.io</url> </backend> <backend> <url>https://ca-foundry3.azurecontainerapps.io</url> </backend> </backend> </backends> <inbound> <set-backend-service backend-id="foundry-pool" /> </inbound>
特点:
- ✅ 线性容量扩展 (3个项目×10K=30K TPM)
- ✅ 容错 -项目失败不会影响他人
- ✅ 成本效益 -按使用付费定价
- ✅ 单端点 用于LLM套件(APIM处理路由)
- ⚠️ 更多基础设施 管理(3个环境)
- ⚠️ 需要APIM配置 更新
LLM套件集成:
- 无需更改 -LLM套件看到单个APIM端点
- APIM透明地路由到可用的Foundry项目
- 保持不变
/bing-grounding/gpt4o_{1-12}端点结构
每月费用: 约6000美元(3个环境×每个环境2K美元)
何时使用:
- 需要20K-50K TPM容量
- 希望跨项目容错
- 相较于PTU定价,更倾向于按次付费
策略3:横向扩展与客户端负载平衡
graph TB
subgraph External["External Clients"]
Client[LLM Suite / MCP Client<br/>⬆️ Client-Side LB Logic]
end
subgraph APIM["Azure API Management"]
Gateway[API Gateway<br/>Shared Policies]
end
subgraph Backend1["Environment 1"]
CA1[Container Apps<br/>12 Agents]
Project1[AI Project 1<br/>GPT-4o: 10K TPM]
end
subgraph Backend2["Environment 2"]
CA2[Container Apps<br/>12 Agents]
Project2[AI Project 2<br/>GPT-4o: 10K TPM]
end
subgraph Backend3["Environment 3"]
CA3[Container Apps<br/>12 Agents]
Project3[AI Project 3<br/>GPT-4o: 10K TPM]
end
Client -->|33% Traffic| Gateway
Client -->|33% Traffic| Gateway
Client -->|34% Traffic| Gateway
Gateway -->|/project1/*| CA1
Gateway -->|/project2/*| CA2
Gateway -->|/project3/*| CA3
CA1 --> Project1
CA2 --> Project2
CA3 --> Project3
style Client fill:#ffa500,color:#fff
style Gateway fill:#0078d4,color:#fff
style CA1 fill:#00bcf2,color:#000
style CA2 fill:#00bcf2,color:#000
style CA3 fill:#00bcf2,color:#000
style Project1 fill:#50e6ff,color:#000
style Project2 fill:#50e6ff,color:#000
style Project3 fill:#50e6ff,color:#000
实施:
-
使用不同的路径部署多个环境:
azd env new prod-foundry-1 azd up # Endpoint: https://apim.azure-api.net/project1/bing-grounding azd env new prod-foundry-2 azd up # Endpoint: https://apim.azure-api.net/project2/bing-grounding azd env new prod-foundry-3 azd up # Endpoint: https://apim.azure-api.net/project3/bing-grounding -
配置APIM路由:
<choose> <when condition="@(context.Request.Url.Path.StartsWith("/project1"))"> <set-backend-service base-url="https://ca-foundry1.azurecontainerapps.io" /> </when> <when condition="@(context.Request.Url.Path.StartsWith("/project2"))"> <set-backend-service base-url="https://ca-foundry2.azurecontainerapps.io" /> </when> <when condition="@(context.Request.Url.Path.StartsWith("/project3"))"> <set-backend-service base-url="https://ca-foundry3.azurecontainerapps.io" /> </when> </choose> -
更新LLM套件配置:
# LLM Suite config foundry_endpoints: - url: https://apim.azure-api.net/project1/bing-grounding weight: 33 capacity: 10000 # TPM - url: https://apim.azure-api.net/project2/bing-grounding weight: 33 capacity: 10000 - url: https://apim.azure-api.net/project3/bing-grounding weight: 34 capacity: 10000 load_balancing: strategy: round-robin # or weighted, least-connections health_check_interval: 30s
特点:
- ✅ 完全控制 LLM套件中的路由逻辑
- ✅ 项目特定路线 用于工作负载隔离
- ✅ 自定义故障转移 逻辑可能
- ✅ 成本可见性 每个项目端点
- ⚠️ LLM套件需要更改 (配置+逻辑)
- ⚠️ 复杂的 客户端实现
- ⚠️ 手动端点管理
LLM套件集成:
- 需要更改配置 -多个端点
- 需要负载平衡逻辑 -客户端循环/加权
- 建议进行健康监测 -检查端点可用性
- 每个代理端点:
- 项目1:
/project1/bing-grounding/gpt4o_{1-12} - 项目2:
/project2/bing-grounding/gpt4o_{1-12} - 项目3:
/project3/bing-grounding/gpt4o_{1-12}
- 项目1:
每月费用: 约6000美元(3个环境×每个环境2K美元)
何时使用:
- 需要高级路由逻辑(租户隔离、工作负载优先级)
- 希望对流量分布进行精细控制
- LLM套件已经具有负载平衡功能
- 每个项目的成本跟踪需求
策略4:混合动力-PTU+多项目
graph TB
subgraph External["External Clients"]
Client[LLM Suite / MCP Client]
end
subgraph APIM["Azure API Management - Weighted LB"]
Gateway[API Gateway<br/>80% to PTU<br/>20% to Standard]
end
subgraph PrimaryProject["Primary Project - PTU"]
CA_PTU[Container Apps<br/>12 Agents]
Project_PTU[AI Project<br/>GPT-4o PTU<br/>100K TPM<br/>Guaranteed]
end
subgraph FallbackProjects["Fallback Projects - Standard"]
CA_STD1[Container Apps<br/>12 Agents]
Project_STD1[AI Project 1<br/>GPT-4o: 10K TPM]
CA_STD2[Container Apps<br/>12 Agents]
Project_STD2[AI Project 2<br/>GPT-4o: 10K TPM]
end
Client -->|HTTPS| Gateway
Gateway -->|80% Primary| CA_PTU
Gateway -->|10% Spillover| CA_STD1
Gateway -->|10% Spillover| CA_STD2
CA_PTU --> Project_PTU
CA_STD1 --> Project_STD1
CA_STD2 --> Project_STD2
style Gateway fill:#0078d4,color:#fff
style CA_PTU fill:#4caf50,color:#fff
style Project_PTU fill:#ff6b6b,color:#fff
style CA_STD1 fill:#00bcf2,color:#000
style CA_STD2 fill:#00bcf2,color:#000
实施:
-
部署主PTU项目:
# Modify infra/resources.bicep to use PTU param openAiDeploymentType string = 'ProvisionedThroughput' param openAiCapacity int = 100 # 100 PTUs azd env new prod-primary azd up -
部署后备标准项目:
azd env new prod-fallback-1 azd up azd env new prod-fallback-2 azd up -
配置加权APIM路由:
<set-variable name="backendIndex" value="@{ var rand = new Random().Next(100); if (rand < 80) return "ptu"; // 80% to PTU if (rand < 90) return "std1"; // 10% to Standard 1 return "std2"; // 10% to Standard 2 }" /> <choose> <when condition="@(context.Variables["backendIndex"] == "ptu")"> <set-backend-service base-url="https://ca-ptu.azurecontainerapps.io" /> </when> <when condition="@(context.Variables["backendIndex"] == "std1")"> <set-backend-service base-url="https://ca-std1.azurecontainerapps.io" /> </when> <otherwise> <set-backend-service base-url="https://ca-std2.azurecontainerapps.io" /> </otherwise> </choose>
特点:
- ✅ 保证容量 (PTU提供的10万TPM)
- ✅ 突发容量 (标准外增加20K TPM)
- ✅ 成本优化 -PTU为基准,按使用量付费
- ✅ 高可用性 -多个后备项目
- ⚠️ 复杂的配置 -加权路由+健康检查
- ⚠️ 基础成本较高 -PTU承诺
LLM套件集成:
- 无需更改 -单个APIM端点
- APIM自动处理加权路由
- 透明地切换到标准项目
每月费用: 约25000美元(PTU:21000美元+2个标准项目:4K美元)
何时使用:
- 需要有保证的基线容量(10万TPM)
- 预计PTU分配之外的流量峰值
- 希望通过突发功能实现成本可预测性
- 需要SLA的关键任务工作负载
比较矩阵
| 策略 | 最大TPM | HA | 成本/月 | LLM套件更改 | 复杂性 | 最适合 |
|---|---|---|---|---|---|---|
| 策略1:垂直(PTU) | 1M+ | 中等 | 5K-50K美元 | 无 | 低 | 快速扩展,可预测负载 |
| 策略2:横向(APIM LB) | 50000+ | 高 | 6000+美元 | 无 | 中等 | 成本效益,容错 |
| 策略3:横向(客户LB) | 50K+ | 高 | 6K+美元 | 配置+逻辑 | 高 | 高级路由,租户隔离 |
| 策略4:混合动力(PTU+多功能) | 12万+ | 非常高 | 2.5万+美元 | 无 | 高 | 关键任务,有保证的容量 |
按工作量推荐
试点/开发(<10K TPM):
- 使用当前的单一项目架构
- 费用:约2K美元/月
- 规模策略:无需
生产-轻型(10K-30K TPM):
- 推荐: 策略2(与APIM LB横向)
- 部署2-3个项目
- 成本:约4K-6K/月
- LLM套件:无更改
生产-中等(30K-100K TPM):
- 推荐: 策略1(垂直PTU)
- 50-100个PTU的单个项目
- 成本:约27K-54K/月
- LLM套件:无更改
生产-重型(100K+TPM):
- 推荐: 策略4(混合PTU+多项目)
- PTU基线+标准回退
- 成本:约25000美元/月
- LLM套件:无更改
企业-关键任务:
- 推荐: 战略4+多区域
- 跨2-3个Azure区域部署
- 成本:约7.5万美元/月
- LLM套件:可选地理路由
多区域部署
在多个Azure区域部署Bing基础API,以实现地理负载分布、灾难恢复和降低全球用户的延迟。
好处
✅ 地理负荷分布 -将流量分散到各个地区
✅ 灾难恢复 -如果一个区域停机,则自动故障转移
✅ 减少延迟 -用户连接到最近的地区
✅ 更好的配额利用率 -每个地区单独的TPM配额
✅ 区域跟踪 -了解每个请求的服务区域
建筑
graph TB
subgraph Clients["Global Clients"]
USClient[US Clients]
EUClient[EU Clients]
end
subgraph APIM["Azure API Management (Global Gateway)"]
Gateway[API Gateway<br/>• Geo-routing<br/>• Health Checks<br/>• Circuit Breaker]
end
subgraph EastUS["East US Region"]
CA_East[Container App<br/>eastus]
Foundry_East[AI Foundry<br/>5 Agents]
Bing_East[Bing Grounding]
end
subgraph WestUS["West US Region"]
CA_West[Container App<br/>westus]
Foundry_West[AI Foundry<br/>5 Agents]
Bing_West[Bing Grounding]
end
subgraph WestEU["West Europe Region"]
CA_EU[Container App<br/>westeurope]
Foundry_EU[AI Foundry<br/>5 Agents]
Bing_EU[Bing Grounding]
end
USClient --> Gateway
EUClient --> Gateway
Gateway -->|Geo-routing| CA_East
Gateway -->|Load balance| CA_West
Gateway -->|Geo-routing| CA_EU
CA_East --> Foundry_East
CA_West --> Foundry_West
CA_EU --> Foundry_EU
Foundry_East --> Bing_East
Foundry_West --> Bing_West
Foundry_EU --> Bing_EU
style Gateway fill:#0078d4,color:#fff
style CA_East fill:#00bcf2,color:#000
style CA_West fill:#00bcf2,color:#000
style CA_EU fill:#00bcf2,color:#000
区域跟踪
每个响应都包含元数据,显示哪个区域处理了请求:
{
"content": "AI-generated response...",
"citations": [...],
"metadata": {
"agent_route": "gpt4o_2",
"model": "gpt-4o",
"agent_id": "asst_abc123...",
"region": "westus" ← Region identifier
}
}
这使得:
- 监控 -跟踪区域交通分布
- 调试 -识别特定地区的问题
- 合规 -审计数据驻留要求
- 分析 -衡量区域绩效
部署步骤
1.部署其他区域
# Create new environment for westus
azd env new westus
azd env set AZURE_LOCATION westus
# Deploy (creates full stack: Foundry, agents, Container App, etc.)
azd up
# Get the Container App URL
azd env get-values | Select-String "CONTAINER_APP"
输出: 容器应用程序URL类似 ca-abc123.westus.azurecontainerapps.io
2.配置APIM多区域后端
选项A:随机负载平衡(最简单)
编辑您的APIM API操作策略(/bing-grounding 或 /bing-grounding-mcp):
<policies>
<inbound>
<set-variable name="backendUrl" value="@{
var backends = new[] {
"https://ca-vw5lt6yc7noze.eastus.azurecontainerapps.io",
"https://ca-abc123.westus.azurecontainerapps.io"
};
var random = new Random();
return backends[random.Next(backends.Length)];
}" />
<set-backend-service base-url="@((string)context.Variables["backendUrl"])" />
</inbound>
</policies>
选项B:地理路由(基于用户位置)
<policies>
<inbound>
<set-variable name="backendUrl" value="@{
// Get client location from X-Forwarded-For or request headers
string clientLocation = context.Request.Headers.GetValueOrDefault("X-Forwarded-For", "");
// Route based on geography
if (clientLocation.Contains("Europe") || clientLocation.Contains("EU"))
return "https://ca-eu.westeurope.azurecontainerapps.io";
else if (clientLocation.Contains("West") || clientLocation.Contains("Pacific"))
return "https://ca-west.westus.azurecontainerapps.io";
else
return "https://ca-east.eastus.azurecontainerapps.io";
}" />
<set-backend-service base-url="@((string)context.Variables["backendUrl"])" />
</inbound>
</policies>
选项C:使用断路器进行健康检查(生产)
<policies>
<inbound>
<base />
<set-variable name="healthyBackends" value="@{
var allBackends = new[] {
"https://ca-east.eastus.azurecontainerapps.io",
"https://ca-west.westus.azurecontainerapps.io",
"https://ca-eu.westeurope.azurecontainerapps.io"
};
var healthyList = new List<string>();
// Check cached health status
foreach (var backend in allBackends)
{
string cacheKey = "backend-health-" + backend;
string healthStatus;
if (context.Cache.TryGetValue(cacheKey, out healthStatus))
{
if (healthStatus == "healthy")
healthyList.Add(backend);
}
else
{
healthyList.Add(backend); // Assume healthy if no data
}
}
return healthyList.Count > 0 ? healthyList : allBackends;
}" />
<!-- Random selection from healthy backends -->
<set-backend-service base-url="@{
var backends = (List<string>)context.Variables["healthyBackends"];
var random = new Random();
return backends[random.Next(0, backends.Count)];
}" />
</inbound>
<outbound>
<base />
<!-- Cache health status based on response -->
<choose>
<when condition="@(context.Response.StatusCode >= 500)">
<cache-store-value
key="@("backend-health-" + context.Request.Url.Host)"
value="unhealthy"
duration="60" />
</when>
<otherwise>
<cache-store-value
key="@("backend-health-" + context.Request.Url.Host)"
value="healthy"
duration="300" />
</otherwise>
</choose>
</outbound>
</policies>
3.测试多区域设置
运行测试套件并观察区域轮换:
python test_mcp.py
预期产量:
Test 1: Region: eastus
Test 2: Region: westus
Test 3: Region: eastus
Test 4: Region: westus
...
各地区所需资源
每个区域部署都需要:
| 资源 | 必填 | 备注 |
|---|---|---|
| AI铸造中心+项目 | ✅ 是 | 每个地区的新实例 |
| Bing接地 | ✅ 是 | 必须与Foundry位于同一资源组中 |
| 容器应用程序 | ✅ 是 | 这是端点APIM路由到 |
| 容器应用程序环境 | ✅ 是 | 容器应用程序需要 |
| 日志分析 | ✅ 是 | 用于容器应用程序日志记录 |
| 存储帐户 | 推荐 | 更适合区域隔离 |
| 密钥库 | 推荐 | 更好的可用性 |
| 集装箱登记处 | 可选 | 可以从主区域重复使用 |
| APIM | ❌ 否 | 单个全球网关,跨区域重用 |
成本考虑
每个额外地区:
- 人工智能铸造项目:~$0(按使用付费)
- GPT-4o部署(10K TPM):约800美元/月
- 容器应用程序:~50-100美元/月
- 集装箱环境:约50美元/月
- Bing停飞(免费版):0美元
- 存储+密钥库+日志:约50美元/月
每个地区总计: 约950-1000美元/月
3区设置(美国东部、美国西部、西欧):
- 总计: 约3000美元/月
- 优点: 30000 TPM总容量+地理分布+灾难恢复
最佳实践
- 从两个地区开始 -主+故障转移
- 使用健康检查 -实施断路器模式
- 监控区域分布 -轨道
metadata.region领域 - 设置区域特定警报 -每个区域的Azure监视器
- 测试故障转移 -定期验证自动故障转移是否正常工作
- 缓存DNS -考虑使用Azure Front Door进行高级地理路由
监控多区域
Azure监视器查询(日志分析):
ContainerAppConsoleLogs_CL
| where TimeGenerated > ago(1h)
| extend region = tostring(parse_json(Log_s).metadata.region)
| summarize count() by region, bin(TimeGenerated, 5m)
| render timechart
APIM分析:
在APIM中跟踪后端分发→ 分析→ 自定义尺寸
先决条件
促进地方发展
- Python 3.11+ - 下载
- Azure命令行界面 - 安装指南
- Docker 桌面版 (可选,适用于Docker Compose)- 下载
- Azure订阅 可以访问:
- Azure AI 铸造厂
- Azure容器应用
- Azure API管理(可选,用于生产)
用于Azure部署
需要Azure权限
- 订阅贡献者 或 所有者 角色(创建资源组和资源)
- Azure人工智能开发人员 或 认知服务贡献者 (创建AI Foundry项目)
入门指南
本地开发
-
创建虚拟环境
_env_create.bat -
激活虚拟环境
_env_activate.bat -
安装依赖项
_install.bat -
配置环境变量
- 复制
env.sample到.env - 填写您的Azure AI代理凭据:
AZURE_AI_PROJECT_ENDPOINT="https://your-project.services.ai.azure.com/api/projects/yourProject" AZURE_AI_AGENT_ID="asst_xxxxxxxxxxxxx"
- 复制
-
启动服务器
_run_server.bat
API将于 http://localhost:8989
Docker开发
-
从Docker Compose开始
_up.bat -
停止Docker编写
_down.bat
API终点
GET/健康
验证服务是否正在运行的健康检查终结点。
例子:
curl http://localhost:8989/health
答复:
{
"status": "ok",
"service": "bing-grounding-api",
"region": "eastus",
"agents_loaded": 5
}
POST/bing接地
Azure AI Agent包装器端点,支持Bing基础和引用。
参数:
query(string,必填)-要处理的用户查询
例子:
curl -X POST "http://localhost:8989/bing-grounding?query=What+happened+in+finance+today?"
成功响应:
{
"content": "Today in finance, the U.S. stock market saw a sharp decline, with the Dow Jones Industrial Average plunging almost 800 points (down 1.6%), and both the Nasdaq and S&P 500 also posting significant losses...",
"citations": [
{
"id": 1,
"type": "url",
"url": "https://www.marketwatch.com/...",
"title": "Stock Market News Today"
},
{
"id": 2,
"type": "url",
"url": "https://www.cnbc.com/...",
"title": "Federal Reserve Commentary"
}
],
"metadata": {
"agent_route": "gpt4o_1",
"model": "gpt-4o",
"agent_id": "asst_abc123...",
"region": "eastus"
}
}
错误响应:
{
"error": "processing_error",
"message": "Error details...",
"metadata": {
"agent_route": "gpt4o_1",
"model": "gpt-4o",
"agent_id": "asst_abc123...",
"region": "eastus"
}
}
特征:
- ✅ 使用Bing搜索的固定响应
- ✅ 自动引文提取和格式化
- ✅ 干净的内容(删除内联引用标记)
- ✅ 结构化JSON响应
- ✅ 元数据中的区域跟踪
响应元数据(调试信息)
每个API响应都包含 metadata 带有调试信息的对象:
| 字段 | 类型 | 描述 | 示例 | 目的 |
|---|---|---|---|---|
region |
string | 为请求提供服务的Azure区域 | "eastus", "westus" |
跟踪多区域负载平衡;确定区域问题 |
model |
string | 用于生成的AI模型 | "gpt-4o", "gpt-4o-mini" |
验证模型部署是否正确;比较模型性能 |
agent_route |
string | 代理池标识符 | "gpt4o_1", "gpt4o_5" |
负载均衡验证;识别特定代理的问题 |
agent_id |
string | Azure AI代理实例ID | "asst_ElHsNtK1PSFxwha7..." |
跟踪特定代理人的行为;排除代理错误 |
为什么元数据对调试很重要:
- 多区域部署 -了解哪个区域处理了诊断延迟或区域中断的请求
- 负载平衡验证 -确认APIM正在跨代理池分发(
gpt4o_1通过gpt4o_5) - 性能分析 -比较不同地区、模型或代理的响应时间/质量
- 错误排除 -确定错误是否隔离到特定的代理、区域或模型
- 合规与审计 -根据监管要求跟踪数据驻留和模型使用情况
元数据成功响应示例:
{
"content": "Azure AI Foundry is a comprehensive platform for building, deploying, and managing AI applications...",
"citations": [
{
"id": 1,
"type": "url",
"url": "https://azure.microsoft.com/products/ai-studio",
"title": "Azure AI Foundry Documentation"
}
],
"metadata": {
"agent_route": "gpt4o_3", // ← Agent pool #3 (load balanced)
"model": "gpt-4o", // ← Using GPT-4o model
"agent_id": "asst_ElHsNtK1PSFxwha7tLWIFM7T", // ← Specific agent instance
"region": "eastus" // ← Request served from East US
}
}
元数据错误响应示例:
{
"error": "rate_limit_exceeded",
"message": "Model deployment TPM limit exceeded. Please retry.",
"metadata": {
"agent_route": "gpt4o_2", // ← Identifies which agent hit rate limit
"model": "gpt-4o",
"agent_id": "asst_abc123xyz",
"region": "westus" // ← Regional capacity issue
}
}
调试用例示例:
| 问题 | 检查内容 | 解决方案 |
|---|---|---|
| 某些请求的响应缓慢 | region 字段 |
可能表示一个区域过载;增加容量或调整APIM路由 |
| 间歇性429错误 | agent_route + agent_id |
特定代理的TPM配额可能较低;增加配额或重新分配负载 |
| 质量变化 | model + agent_id |
比较不同代理人的反应;可能需要及时调整 |
| 区域合规违规 | region 字段 |
审核日志显示在错误区域处理的数据;更新地理路由策略 |
| 所有请求都发送给一个代理 | agent_route 分布 |
APIM负载平衡中断;检查后端池配置 |
如何添加元数据(实现):
元数据填充在 app/main.py:
# Environment variable set by Bicep deployment
AZURE_REGION = os.getenv("AZURE_REGION", "unknown")
# On successful response (line ~133)
result["metadata"] = {
"agent_route": agent_route, # From URL path (gpt4o_1, gpt4o_2, etc.)
"model": model, # From agent configuration
"agent_id": AGENTS[agent_route]["agent_id"], # From agent pool
"region": AZURE_REGION # From container environment
}
# On error response (line ~147)
"metadata": {
"agent_route": agent_route,
"model": model,
"agent_id": AGENTS.get(agent_route, {}).get("agent_id", "unknown"),
"region": AZURE_REGION
}
这 AZURE_REGION 环境变量在部署过程中通过二头肌自动设置(infra/resources.bicep 第258行):
{
name: 'AZURE_REGION'
value: location // Resolves to deployment region (eastus, westus, etc.)
}
测试API
测试API直接端点
先决条件:
- 已部署服务(本地或Azure)
- 来自部署的终结点URL或
http://localhost:8989本地
基本健康检查:
# Local
curl http://localhost:8989/health
# Azure (Container App)
curl https://ca-vw5lt6yc7noze.eastus.azurecontainerapps.io/health
预期响应:
{
"status": "ok",
"service": "bing-grounding-api",
"region": "eastus",
"agents_loaded": 5
}
测试查询:
# Local
curl -X POST "http://localhost:8989/bing-grounding/gpt4o_1?query=What+is+Azure+AI+Foundry?"
# Azure (Container App)
curl -X POST "https://ca-vw5lt6yc7noze.eastus.azurecontainerapps.io/bing-grounding/gpt4o_1?query=What+is+Azure+AI+Foundry?"
预期响应:
{
"content": "Azure AI Foundry is Microsoft's unified platform...",
"citations": [
{
"id": 1,
"type": "url",
"url": "https://azure.microsoft.com/products/ai-studio",
"title": "Azure AI Foundry Overview"
}
],
"metadata": {
"agent_route": "gpt4o_1",
"model": "gpt-4o",
"agent_id": "asst_ElHsNtK1PSFxwha7tLWIFM7T",
"region": "eastus"
}
}
测试MCP端点(模型上下文协议)
MCP端点通过Azure API管理为人工智能模型消费提供标准化接口。
先决条件
- APIM部署 -API管理必须部署(包含在
azd up) - 订阅密钥 -APIM身份验证所需
获取您的订阅密钥:
# Option 1: Azure Portal
# Navigate to: APIM → Subscriptions → "Built-in all-access subscription" → Show keys
# Option 2: Azure CLI
az apim subscription show \
--resource-group rg-bing-grounding-mcp-dev \
--service-name apim-xxxxxx \
--sid master \
--query primaryKey -o tsv
配置环境变量
将这些添加到您的 .env 文件:
# MCP Server URL (from APIM)
APIM_MCP_SERVER_URL=https://apim-vw5lt6yc7noze.azure-api.net/bing-grounding-mcp/mcp
# Subscription Key (from APIM portal or CLI)
APIM_SUBSCRIPTION_KEY=70f2c804e2ee4f749cea4b8ab3246e7e
运行MCP测试
使用测试脚本:
# Activate virtual environment
_env_activate.bat
# Run tests
python test_mcp.py
预期产量:
=== Testing MCP Endpoint ===
MCP Server URL: https://apim-vw5lt6yc7noze.azure-api.net/bing-grounding-mcp/mcp
Test 1: What are the latest developments in AI?
RESULT: OK (10.6s)
Region: eastus ← Azure region that processed request
Model: gpt-4o ← AI model used for generation
Agent Route: gpt4o_2 ← Agent pool identifier (load balanced)
Agent ID: asst_ElHsNtK1PSFxwha7tLWIFM7T ← Specific agent instance ID
Citations: 3 ← Number of Bing grounding citations
[1] AI News December 2025: In-Depth and Concise
[2] Recent Developments in Generative AI Research
[3] OpenAI Announces GPT-4.5
Response: During December 2025, several notable advancements have been made in artificial intelligence...
Test 2: What happened in the stock market today?
RESULT: OK (8.2s)
Region: westus ← Different region (multi-region load balancing)
Model: gpt-4o
Agent Route: gpt4o_3 ← Different agent (load balanced across 5 agents)
Agent ID: asst_xyz789...
Citations: 4
[1] Market Watch - December 17, 2025
[2] CNBC Stock Market Update
[3] Bloomberg Markets Summary
[4] S&P 500 Daily Close
Response: Today's stock market showed mixed performance, with the S&P 500 closing up 0.3%...
Test 3: Explain quantum computing
RESULT: OK (12.1s)
Region: eastus ← Back to eastus (round-robin balancing)
Model: gpt-4o
Agent Route: gpt4o_1 ← Cycling through agent pool
Agent ID: asst_def456...
Citations: 5
[1] Quantum Computing Basics - Nature
[2] IBM Quantum - Overview
[3] Google Quantum AI Research
[4] Quantum Algorithms Explained
[5] Introduction to Qubits
Response: Quantum computing is a revolutionary approach to computation that leverages quantum mechanics...
===========================
Tests completed: 5
Success: 5 (100%)
Failed: 0 (0%)
Average response time: 9.4s
===========================
在测试输出中查找什么:
| 字段 | 它告诉你什么 | 很好✅ | 坏❌ |
|---|---|---|---|
| 区域 | 地理分布 | 跨地区轮换(东、西) | 始终是同一地区;“未知” |
| 代理路线 | 跨代理的负载平衡 | 通过gpt4o_1循环到gpt4i_5 | 始终使用相同的代理路由 |
| 响应时间 | 性能一致性 | 5-15秒典型 | >30秒;高方差 |
| 成功率 | 总体可靠性 | 90%+成功 | <80%成功;频繁故障 |
| 引用 | Bing接地质量 | 3-5次引用/响应 | 0次引用;通用答案 |
失败测试示例(用于调试):
Test 4: What are the benefits of cloud computing?
RESULT: FAILED (2.5s) - rate_limit_exceeded
Region: westus ← Helps isolate regional capacity issues
Model: gpt-4o
Agent Route: gpt4o_4 ← This specific agent hit rate limit
Agent ID: asst_ghi789...
Error: Model deployment TPM limit exceeded ← Error message
Action: Increase TPM quota for westus deployment or adjust load balancing
使用cURL进行手动MCP测试
使用订阅密钥标头进行测试:
curl -X POST "https://apim-vw5lt6yc7noze.azure-api.net/bing-grounding-mcp/mcp" \
-H "Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "bing_grounding",
"arguments": {
"query": "What is the weather like today?"
}
},
"id": 1
}'
预期响应:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "Today's weather varies by location. For specific weather information, please check your local forecast. As of December 17, 2025, many regions are experiencing seasonal winter conditions..."
}
],
"metadata": {
"agent_route": "gpt4o_1", // ← Which agent pool handled request
"model": "gpt-4o", // ← Model used
"agent_id": "asst_ElHsNtK1PSFxwha7tLWIFM7T", // ← Specific agent instance
"region": "eastus" // ← Region that processed request
}
}
}
非常适合调试:
# Add -v flag to see full request/response headers
curl -v -X POST "https://apim-vw5lt6yc7noze.azure-api.net/bing-grounding-mcp/mcp" \
-H "Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "bing_grounding",
"arguments": {
"query": "What is Azure AI Foundry?"
}
},
"id": 1
}' | jq '.'
预期详细输出(含调试信息):
< HTTP/2 200
< content-type: application/json
< ocp-apim-trace-location: https://apimst... ← APIM trace URL (if tracing enabled)
< x-backend-server: ca-vw5lt6yc7noze ← Which Container App served request
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "Azure AI Foundry is Microsoft's comprehensive platform for building, deploying, and managing AI applications. It provides a unified experience for developing custom AI solutions, integrating with Azure OpenAI Service, and leveraging pre-built AI models..."
}
],
"citations": [
{
"id": 1,
"type": "url",
"url": "https://azure.microsoft.com/en-us/products/ai-studio",
"title": "Azure AI Foundry - Microsoft Azure"
},
{
"id": 2,
"type": "url",
"url": "https://learn.microsoft.com/azure/ai-studio/",
"title": "Azure AI Foundry documentation"
}
],
"metadata": {
"agent_route": "gpt4o_2",
"model": "gpt-4o",
"agent_id": "asst_xyz789abc123def456",
"region": "eastus"
}
}
}
使用元数据调试清单:
✅ 地区正确 - "eastus" 或预期区域(不是 "unknown")
✅ 代理路由有效 -其中之一 gpt4o_1 通过 gpt4o_5
✅ 预计型号 -应该是 "gpt-4o" 对于所有代理
✅ 已填充代理ID -以开头的长字符串 asst_
✅ 引文存在 -Bing搜索结果数组
✅ 响应时间可接受 -通常为5-15秒
❌ 区域显示“未知” -容器应用程序缺少AZURE_REGION环境变量
❌ 每次都是同一个特工 -APIM负载平衡不起作用
❌ 无引用 -代理上未配置Bing接地
❌ 代理ID“未知” -代理池配置错误
常见测试问题
问题1:401访问被拒绝
{
"statusCode": 401,
"message": "Access denied due to missing subscription key"
}
解决方案: 将订阅密钥添加到请求标头中:
-H "Ocp-Apim-Subscription-Key: YOUR_KEY_HERE"
问题2:空响应/无内容
解决方案:
- 检查MCP服务器URL是否正确
- 验证订阅密钥是否有效
- 检查APIM后端是否正常:
curl https://ca-vw5lt6yc7noze.eastus.azurecontainerapps.io/health
问题3:区域显示“未知”
解决方案: 确保 AZURE_REGION 在容器应用程序配置中设置环境变量:
azd deploy # Redeploy to update environment variables
多区域测试
测试多区域部署时,请遵守 region 用于验证负载平衡的字段:
# Run multiple tests to see region rotation
for i in {1..10}; do
echo "Test $i:"
curl -s -X POST "https://apim-xxx.azure-api.net/bing-grounding-mcp/mcp" \
-H "Ocp-Apim-Subscription-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"bing_grounding","arguments":{"query":"test"}},"id":'$i'}' \
| jq -r '.result.metadata.region'
done
预期产出(2个地区):
Test 1: eastus ← First request to East US
Test 2: westus ← Load balanced to West US
Test 3: eastus ← Round-robin back to East US
Test 4: westus
Test 5: eastus
Test 6: westus
Test 7: eastus
Test 8: westus
Test 9: eastus
Test 10: westus
提取完整元数据进行分析:
# Get complete metadata from multiple requests
for i in {1..5}; do
echo "=== Request $i ==="
curl -s -X POST "https://apim-xxx.azure-api.net/bing-grounding-mcp/mcp" \
-H "Ocp-Apim-Subscription-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"bing_grounding","arguments":{"query":"test query"}},"id":'$i'}' \
| jq '.result.metadata'
echo ""
done
预期产量:
=== Request 1 ===
{
"agent_route": "gpt4o_1", ← Agent pool #1
"model": "gpt-4o",
"agent_id": "asst_ElHsNtK1PSFxwha7tLWIFM7T",
"region": "eastus" ← East US region
}
=== Request 2 ===
{
"agent_route": "gpt4o_3", ← Different agent (load balanced)
"model": "gpt-4o",
"agent_id": "asst_Abc123Xyz789Def456Ghi",
"region": "westus" ← West US region
}
=== Request 3 ===
{
"agent_route": "gpt4o_2", ← Third agent
"model": "gpt-4o",
"agent_id": "asst_Qrs789Tuv012Wxy345Zab",
"region": "eastus" ← Back to East US
}
=== Request 4 ===
{
"agent_route": "gpt4o_5", ← Fifth agent
"model": "gpt-4o",
"agent_id": "asst_Mno456Pqr789Stu012Vwx",
"region": "westus" ← Back to West US
}
=== Request 5 ===
{
"agent_route": "gpt4o_4", ← Fourth agent
"model": "gpt-4o",
"agent_id": "asst_Cde345Fgh678Ijk901Lmn",
"region": "eastus" ← East US again
}
这显示了什么:
- ✅ 区域分布 -东部和西部的请求正在平衡
- ✅ 代理商分布 -不同的代理路径(gpt4o_1至gpt40_5)
- ✅ 独特的代理商 -每个agent_id都不同
- ✅ 一致的模型 -全部使用gpt-4o
随时间变化的轨迹分布:
# Run 50 requests and count region distribution
echo "Testing 50 requests across regions..."
for i in {1..50}; do
curl -s -X POST "https://apim-xxx.azure-api.net/bing-grounding-mcp/mcp" \
-H "Ocp-Apim-Subscription-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"bing_grounding","arguments":{"query":"test"}},"id":'$i'}' \
| jq -r '.result.metadata.region'
done | sort | uniq -c
预期产量:
25 eastus ← 50% of requests (good distribution)
25 westus ← 50% of requests (good distribution)
如果分布不均匀:
45 eastus ← 90% to one region
5 westus ← Only 10% to other region
可能的原因:
- APIM后端健康检查标记一个区域不健康
- 断路器在一个区域跳闸
- 后端池权重配置不均
- DNS缓存或粘滞会话
性能测试
具有多个并发请求的负载测试:
# Install dependencies
pip install aiohttp asyncio
# Run load test (included in test_mcp.py)
python test_mcp.py --concurrent 10 --iterations 100
监视器:
- 响应时间
- 成功率
- 区域分布
- 引文质量
Azure AI代理配置
此服务包装了一个必须配置Bing基础功能的Azure AI代理。
设置Azure AI代理
- 创建Azure AI项目
- 创建启用Bing基础的AI代理
- 复制项目终结点和代理ID
- 将它们设置为环境变量
环境变量
| 变量 | 描述 | 必填 | 示例 |
|---|---|---|---|
AZURE_AI_PROJECT_ENDPOINT |
Azure AI项目端点 | 始终 | https://your-project.services.ai.azure.com/api/projects/yourProject |
AZURE_AI_AGENT_ID |
Azure AI代理ID | 始终 | asst_xxxxxxxxxxxxx |
AZURE_CLIENT_ID |
服务主体应用程序ID | 仅限本地测试 | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
AZURE_CLIENT_SECRET |
服务负责人机密 | 仅限本地测试 | your-secret-value |
AZURE_TENANT_ID |
Azure AD租户ID | 仅限本地测试 | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
身份验证设置
用于本地测试(服务负责人)
-
创建服务主体:
az ad sp create-for-rbac --name "bing-grounding-api-sp" --role Contributor这将返回:
{ "appId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", # AZURE_CLIENT_ID "password": "your-secret-here", # AZURE_CLIENT_SECRET "tenant": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # AZURE_TENANT_ID } -
授予人工智能项目访问权限:
# Get your subscription ID and resource group from Azure Portal az role assignment create \ --assignee <appId-from-above> \ --role "Cognitive Services User" \ --scope "/subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.CognitiveServices/accounts/<ai-project-name>" -
更新你的
.env文件:AZURE_AI_PROJECT_ENDPOINT=https://your-region.services.ai.azure.com/api/projects/your-project AZURE_AI_AGENT_ID=asst_xxxxxxxxxxxxx AZURE_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx AZURE_CLIENT_SECRET=your-secret-here AZURE_TENANT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
用于生产(管理身份)
部署到Azure容器应用程序时,请改用托管身份:
-
启用托管身份 在您的容器应用程序上:
az containerapp identity assign \ --name bing-grounding-api \ --resource-group your-rg \ --system-assigned -
授予托管身份访问权限 您的AI项目:
# Get the principal ID from the output above or: PRINCIPAL_ID=$(az containerapp identity show \ --name bing-grounding-api \ --resource-group your-rg \ --query principalId -o tsv) # Grant access az role assignment create \ --assignee $PRINCIPAL_ID \ --role "Cognitive Services User" \ --scope "/subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.CognitiveServices/accounts/<ai-project-name>" -
仅使用所需变量进行部署 (无客户机密):
az containerapp create \ --name bing-grounding-api \ --resource-group your-rg \ --environment your-env \ --image your-registry.azurecr.io/bing-grounding-api:latest \ --target-port 8989 \ --ingress external \ --system-assigned \ --env-vars \ AZURE_AI_PROJECT_ENDPOINT="your-endpoint" \ AZURE_AI_AGENT_ID="your-agent-id"
重要:不设置 AZURE_CLIENT_ID, AZURE_CLIENT_SECRET,或 AZURE_TENANT_ID 在生产中。这 DefaultAzureCredential 将自动使用托管身份。
项目结构
ai-bing-grounding-mcp/
├── agents/ # AI Agent implementations
│ ├── __init__.py
│ ├── base_agent.py # Abstract base class
│ └── bing_grounding.py # Bing grounding agent
├── ai/ # (Legacy - not used)
│ ├── __init__.py
│ └── azure_openai_client.py
├── app/ # FastAPI application
│ ├── __init__.py
│ └── main.py # API endpoints
├── apim-policy.xml # Main APIM policy (load balancing + circuit breaker)
├── apim-policy-with-healthcheck.xml # Enhanced APIM policy with active health checks
├── apim-healthcheck-monitor.xml # Optional active health monitoring policy
├── docker-compose.yaml # Local Docker development
├── dockerfile # Container image definition
├── env.sample # Environment variable template
├── main.py # Application entry point
├── requirements.txt # Python dependencies
├── _env_activate.bat # Activate virtual environment
├── _env_create.bat # Create virtual environment
├── _install.bat # Install dependencies
├── _run_server.bat # Run FastAPI server
├── _up.bat # Start Docker Compose
├── _down.bat # Stop Docker Compose
└── README.md # This file
部署到Azure
选项1:使用Azure Developer CLI自动部署(⭐ 推荐)
Azure开发者命令行界面(azd)自动化了从创建基础设施到部署应用程序的整个部署过程。 这是推荐的方法 用于开发和生产部署。
自动部署的内容:
- 🏗️ Azure容器应用环境+3个容器应用实例
- 🤖 Azure人工智能铸造中心和项目
- 🤖 12个基于Bing的GPT-4o AI代理(通过编程创建!)
- 🔐 Azure容器注册表
- 🔐 具有受管理身份的密钥库
- 📊 日志分析和应用洞察
- 🌐 Azure API管理(带负载平衡和断路器)
- 🔒 所有资源的RBAC角色分配
总部署时间:~8-15分钟 ⏱️
先决条件
在开始之前,请确保您已经:
必修的:
可选(用于当地发展):
- Python 3.11+- 下载
快速安装命令:
# Windows (PowerShell)
powershell -ex AllSigned -c "Invoke-RestMethod 'https://aka.ms/install-azd.ps1' | Invoke-Expression"
# macOS/Linux
curl -fsSL https://aka.ms/install-azd.sh | bash
第一步:登录Azure
azd auth login
这将打开一个浏览器进行身份验证。一旦通过身份验证,您就可以部署了。
步骤2:部署所有内容(一个命令)
最简单的方法是使用 azd up,它一步创建环境、配置基础设施并部署应用程序:
azd up
系统将提示您:
- 环境名称例如。,
dev,staging,prod- 创建资源组:
rg-bing-grounding-mcp-{env-name}
- 创建资源组:
- Azure订阅:从您的订阅中选择
- Azure位置例如。,
eastus2,westus2 - 资源组确认:如果已存在,请确认继续
期间会发生什么 azd up:
-
预浸挂钩 (约30秒)
- ✅ 检查资源组状态
- ✅ 注册Microsoft。Bing资源提供者
-
基础设施供应 (约5-10分钟)
- 🏗️ 创建容器注册表
- 🏗️ 创建容器应用程序环境
- 🏗️ 创建AI铸造中心和项目
- 🏗️ 部署GPT-4o模型
- 🏗️ 创建密钥库、存储、日志分析
- 🏗️ 创建API管理
- 🏗️ 配置托管身份和RBAC
-
供应后挂钩 (约2-3分钟)
- 🤖 使用Bing基础创建12个GPT-4o AI代理
- 📝 将代理ID保存到环境
-
应用程序部署 (约3-5分钟)
- 🐳 构建Docker镜像
- 📤 推送到Azure容器注册表
- 🚀 部署到所有3个容器应用程序实例
-
部署后挂钩 (约1分钟)
- 🔄 更新其他容器实例
完成后,您将看到:
SUCCESS: Your application was provisioned and deployed to Azure in X minutes.
You can view the application at https://ca-xxxxxx.eastus2.azurecontainerapps.io
就是这样!您的API有12个人工智能代理,随时准备为请求提供服务。
步骤2(备选方案):单独提供和部署
如果您更喜欢控制,可以将步骤分开:
A.创造环境:
azd env new <environment-name>
示例:
azd env new dev→ 创建rg-bing-grounding-mcp-devazd env new prod→ 创建rg-bing-grounding-mcp-prod
B.提供基础设施:
azd provision
这将创建所有Azure资源,并运行后视觉挂钩以创建AI代理。
C.部署应用程序:
azd deploy
这将构建Docker容器并将其部署到所有实例。
步骤3:测试部署
获取您的端点:
azd env get-values | grep AZURE_CONTAINER_APP_ENDPOINT
# or
azd env get-values | findstr AZURE_CONTAINER_APP_ENDPOINT # Windows
测试API:
# Health check
curl https://ca-xxxxxx.eastus2.azurecontainerapps.io/health
# List agents
curl https://ca-xxxxxx.eastus2.azurecontainerapps.io/agents
# Query with Bing grounding
curl -X POST "https://ca-xxxxxx.eastus2.azurecontainerapps.io/bing-grounding/gpt4o_1?query=What+is+Azure+AI+Foundry?"
高级配置
预配置环境(可选)
对于CI/CD管道或脚本部署,您可以预先配置值以避免交互式提示:
# Create environment
azd env new <env-name>
# Set subscription (find with: az account list -o table)
azd env set AZURE_SUBSCRIPTION_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# Set location
azd env set AZURE_LOCATION "eastus2"
# Now provision and deploy without prompts
azd up
何时进行预配置:
- ✅ CI/CD管道(GitHub操作、Azure DevOps)
- ✅ 自动化/脚本化部署
- ✅ 执行团队标准
- ✅ 多环境部署(开发/测试/生产)
查看环境配置
# Show all environment variables and outputs
azd env get-values
# Show deployment status and endpoints
azd show
常见工作流
更新应用程序代码
当你修改Python代码时:
azd deploy
这将重建Docker镜像,并在零停机时间(约3-5分钟)内更新所有容器应用程序实例。
更新基础架构
在中修改二头肌模板时 infra/:
azd provision
这将应用基础设施更改,而无需重新部署应用程序(约2-5分钟)。
查看日志
# Get resource group from environment
RG=$(azd env get-values | grep AZURE_RESOURCE_GROUP | cut -d'=' -f2 | tr -d '"')
# Get Container App name
CA_NAME=$(azd env get-values | grep AZURE_CONTAINER_APP_NAME | cut -d'=' -f2 | tr -d '"')
# Stream logs
az containerapp logs show --name $CA_NAME --resource-group $RG --follow
多种环境(开发/暂存/生产)
# Create and deploy dev environment
azd env new dev
azd env set AZURE_LOCATION "eastus2"
azd up
# Create and deploy prod environment
azd env new prod
azd env set AZURE_LOCATION "eastus"
azd up
# Switch between environments
azd env select dev
azd env select prod
# List all environments
azd env list
每个环境都会得到:
- 单独的资源组:
rg-bing-grounding-mcp-{env} - 隔离的Azure资源
- 本地配置
.azure/{env}/
拆除资源
# Delete all Azure resources (with confirmation)
azd down
# Delete without prompts
azd down --force --purge
⚠️ 警告:这将删除整个资源组和所有资源。
什么是自动创建的
当你奔跑时 azd up,提供以下资源:
| 资源 | 目的 | 详细信息 |
|---|---|---|
| 资源组 | 逻辑容器 | rg-bing-grounding-mcp-{env} |
| 集装箱登记处 | Docker镜像 | 应用镜像的私有注册表 |
| 容器应用程序(×3) | 应用程序托管 | 3个负载平衡实例 |
| AI铸造中心 | 人工智能基础设施 | 人工智能项目中心 |
| AI铸造项目 | AI代理管理 | 包含GPT-4o部署 |
| 12个AI代理 | 必应基础代理 | 通过API以编程方式创建 |
| API管理 | API网关 | 负载平衡+断路器 |
| 密钥库 | 机密管理 | 存储敏感配置 |
| 存储帐户 | 数据存储 | 用于AI Hub和日志 |
| 日志分析 | 监控 | 集中记录 |
| 应用洞察 | APM | 性能监控 |
| 管理身份 | 身份验证 | 安全的服务到服务身份验证 |
总成本估算:根据使用情况和SKU,每月约200-400美元。
自动挂钩解释
该解决方案使用 azd 钩子用于自动化设置任务:
预浸挂钩 (基础设施之前):
- 检查资源组 -提示RG是否已存在
- 注册供应商 -登记簿
Microsoft.Bing提供者
供应后挂钩 (基础设施之后):
- 创建AI代理 -以Bing为基础,通过编程创建12个GPT-4o代理
- 保存代理ID -将ID存储为环境变量
部署后挂钩 (部署后):
- 更新容器实例 -使用最新映像更新其他实例
这些钩子在 azure.yaml 并自动运行- 无需人工干预.
部署故障排除
问题: azd provision 订阅失败
- 修复:明确设置订阅:
azd env set AZURE_SUBSCRIPTION_ID "your-sub-id" - 修复:确保您在订阅中具有参与者/所有者角色
问题:容器部署失败,显示“找不到映像”
- 修复:确保Docker在本地运行
- 修复:检查ACR凭据:
az acr login --name <registry-name>
问题:未创建AI代理
- 修复:检查日志:
cat .azure/{env}/.env | grep AZURE_AI_AGENT - 修复:手动运行:
python scripts/postprovision_create_agents.py
问题:访问AI项目时出现身份验证错误
- 修复:验证托管身份是否具有“认知服务用户”角色
- 修复:检查Azure门户中的RBAC分配
最佳实践
✅ 使用 azd up 用于首次部署和组合基础架构+代码更改
✅ 使用 azd deploy 仅用于代码更改(更快)
✅ 使用单独的环境 用于dev/ststage/prod隔离
✅ 永不承诺 .azure/ 文件夹 -它包含特定于环境的配置
✅ 审查产出 每次部署后 azd env get-values
✅ 测试在dev 部署到生产环境之前
✅ 使用托管身份 (默认)而不是服务主体
✅ 监控成本 使用Azure成本管理
📚 了解更多:
选项2:使用Azure CLI手动部署
如果您喜欢手动控制或无法使用 azd:
第一步:创建基础设施
-
创建资源组:
az group create --name rg-bing-grounding --location eastus -
创建Azure容器注册表:
az acr create \ --resource-group rg-bing-grounding \ --name acrbing123 \ --sku Basic \ --admin-enabled true -
创建AI铸造中心和项目 (通过Azure门户):
- 首选https://ai.azure.com
- 创建新中心
- 在Hub中创建新项目
- 注意项目端点
-
创建容器应用程序环境:
az containerapp env create \ --name cae-bing-grounding \ --resource-group rg-bing-grounding \ --location eastus
步骤2:构建并推送容器映像
-
登录ACR:
az acr login --name acrbing123 -
构建和推送图像:
docker build -t acrbing123.azurecr.io/bing-grounding-api:latest . docker push acrbing123.azurecr.io/bing-grounding-api:latest
步骤3:部署容器应用程序(多个实例)
# Get ACR credentials
ACR_USERNAME=$(az acr credential show --name acrbing123 --query username -o tsv)
ACR_PASSWORD=$(az acr credential show --name acrbing123 --query passwords[0].value -o tsv)
# Deploy instance 1
az containerapp create \
--name bing-grounding-api-0 \
--resource-group rg-bing-grounding \
--environment cae-bing-grounding \
--image acrbing123.azurecr.io/bing-grounding-api:latest \
--target-port 8989 \
--ingress external \
--registry-server acrbing123.azurecr.io \
--registry-username $ACR_USERNAME \
--registry-password $ACR_PASSWORD \
--system-assigned \
--env-vars \
AZURE_AI_PROJECT_ENDPOINT="https://eastus.services.ai.azure.com/api/projects/yourProject" \
AZURE_AI_AGENT_ID="asst_xxxxxxxxxxxxx"
# Repeat for instances 1 and 2
az containerapp create --name bing-grounding-api-1 ... (same parameters)
az containerapp create --name bing-grounding-api-2 ... (same parameters)
步骤4:授予托管身份访问权限
# Get managed identity principal IDs
PRINCIPAL_ID_0=$(az containerapp identity show \
--name bing-grounding-api-0 \
--resource-group rg-bing-grounding \
--query principalId -o tsv)
# Grant access to AI Project (repeat for each instance)
az role assignment create \
--assignee $PRINCIPAL_ID_0 \
--role "Cognitive Services User" \
--scope "/subscriptions/<sub-id>/resourceGroups/rg-bing-grounding/providers/Microsoft.CognitiveServices/accounts/<ai-project-name>"
步骤5:更新容器应用程序(用于代码更改)
# Build and push new image
docker build -t acrbing123.azurecr.io/bing-grounding-api:v2 .
docker push acrbing123.azurecr.io/bing-grounding-api:v2
# Update container apps
az containerapp update \
--name bing-grounding-api-0 \
--resource-group rg-bing-grounding \
--image acrbing123.azurecr.io/bing-grounding-api:v2
# Repeat for other instances
使用Docker Compose进行本地开发
对于没有Azure资源的本地测试:
# Start services
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down
备注:您仍然需要有效的Azure AI项目凭据 .env 文件。
Azure API管理设置
断路器负载平衡
该服务包括用于具有多个后端实例的生产部署的APIM策略。
架构特征
┌──────────────────────────────────────────┐
│ [AZURE API MANAGEMENT] │
│ │
│ ┌────────────────────────────────────┐ │
│ │ Load Balancer + Circuit Breaker │ │
│ │ • Session Affinity (Cookies) │ │
│ │ • Health-Based Routing │ │
│ │ • Auto Failover & Recovery │ │
│ └─────────────────┬──────────────────┘ │
└────────────────────┼────────────────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ... (N instances)
│ ✅ HEALTHY │ │ ❌ UNHEALTHY│
│ Container │ │ Container │
│ App #1 │ │ App #2 │
│ [ACTIVE] │ │ [REMOVED] │
└─────────────┘ └─────────────┘
特性
- 会话亲和性(粘性会话) -客户端通过Cookie坚持使用相同的后端
- 断路器 -不健康的后端已自动从池中删除
- 自动恢复 -健康恢复后,后端重新加入
- 健康感知路由 -仅通往健康实例的路径
APIM策略文件
包括三个策略文件:
| 文件 | 描述 | 用例 |
|---|---|---|
apim-policy.xml |
具有会话关联性和断路器的主要负载平衡策略 | 推荐 -具有多个后端的生产部署 |
apim-policy-with-healthcheck.xml |
通过主动健康监测增强策略 | 需要主动健康检查的高可用性场景 |
apim-healthcheck-monitor.xml |
独立健康检查监测器 | 单独的监测管道 |
设置步骤
-
更新后端URL
在
apim-policy.xml,将占位符URL替换为容器应用程序URL:var backends = new System.Collections.Generic.Dictionary<string, string> { { "0", "https://bing-grounding-api-1.azurecontainerapps.io" }, { "1", "https://bing-grounding-api-2.azurecontainerapps.io" }, { "2", "https://bing-grounding-api-3.azurecontainerapps.io" }, { "3", "https://bing-grounding-api-4.azurecontainerapps.io" }, { "4", "https://bing-grounding-api-5.azurecontainerapps.io" } }; -
在Azure门户中应用策略
- 导航到您的APIM服务
- 转到您的API→ 设计表
- 点击“所有操作”(或特定操作)
- 在“入站处理”中,单击代码编辑器(
</>) - 从粘贴策略XML
apim-policy.xml - 点击保存
-
启用内部缓存 (断路器要求)
- 导航到APIM→ 缓存
- 启用内置缓存
断路器行为
❌ 不健康-标记背部不健康
后端已标记 [不健康] (从池中删除30秒):
- 退货
500,502,503,504(服务器错误) - 退货
429(超出费率限制) - 退货
401(身份验证失败) - 连接超时或失败
✅ 健康-自动恢复
后端已标记 [健康] (重新加入池)当:
- 退货
200 OK - 健康状态缓存过期(30秒后)
用于监视的响应标头
APIM策略添加了用于监视的标头:
| 标题 | 描述 | 示例 |
|---|---|---|
X-APIM-Correlation-Id |
用于跟踪的唯一请求ID | a1b2c3d4-... |
X-Backend-Instance |
处理请求的后端 | 0, 1, 2, 3, 4 |
X-Served-By-Instance |
为响应提供服务的后端 | 0, 1, 2, 3, 4 |
X-Error-Backend-Instance |
导致错误的后端(在错误时) | 2 |
饼干:
APIM-Backend-Instance-会话关联cookie(24小时TTL)
测试断路器
-
测试会话相关性
# First request - receives backend assignment curl -i https://your-apim.azure-api.net/bing-grounding # Check Set-Cookie header for: APIM-Backend-Instance=X # Subsequent requests with cookie go to same backend curl -i https://your-apim.azure-api.net/health \ -H "Cookie: APIM-Backend-Instance=0" -
测试故障转移
# Stop one Container App instance # Requests automatically route to healthy instances for i in {1..10}; do curl -s https://your-apim.azure-api.net/health | jq '.status' done -
测试恢复
# Restart the instance # Wait 30 seconds for cache expiration # It automatically rejoins on first 200 response
生产检查表
- []APIM中启用了内部缓存
- []部署并运行多个容器应用程序
- []健康端点返回200 OK
- []APIM策略中更新了后端URL
- []已应用和测试的政策
- []使用Cookie测试会话相关性
- []断路器经过模拟故障测试
- []已配置监控/警报(应用程序洞察)
- []安全性:已配置APIM订阅密钥
代理架构
包装器使用抽象基类(ABC)模式进行扩展:
agents/
├── base_agent.py # Abstract base class for all agents
└── bing_grounding.py # Bing grounding implementation
BaseAgent(ABC)
class BaseAgent(ABC):
"""Abstract base class for all agents"""
def __init__(self, endpoint: str = None, agent_id: str = None):
self.endpoint = endpoint
self.agent_id = agent_id
@abstractmethod
def chat(self, message: str) -> str:
"""Process a message and return response"""
pass
BingGrounding代理
具体实施:
- 连接到Azure AI代理服务
- 创建对话线程
- 从基于Bing的回复中提取引文并格式化引文
- 返回包含内容和引用的结构化JSON
- 处理后自动清理线程
使用新代理进行扩展
要添加新的代理类型,请执行以下操作:
- 创建一个新的代理类,该类继承自
BaseAgent - 实施
chat()方法 - 将配置添加到
.env - 在中添加新端点
app/main.py
例子:
class CustomAgent(BaseAgent):
def __init__(self):
endpoint = os.getenv("CUSTOM_AGENT_ENDPOINT")
agent_id = os.getenv("CUSTOM_AGENT_ID")
super().__init__(endpoint=endpoint, agent_id=agent_id)
def chat(self, message: str) -> str:
# Your custom implementation
pass
故障排除
问题:“AZURE_AI_PROJECT_ENDPOINT未设置”错误
- 修复:复制
env.sample到.env并填写您的凭据
问题:Azure AI代理的身份验证失败
- 修复:确保您已通过Azure CLI的身份验证:
az login - 修复:验证DefaultAzureCredentials是否有权访问AI项目
问题:没有引用回应
- 修复:确保您的Azure AI代理启用了Bing基础
- 修复:检查Azure AI Studio中是否正确配置了代理
问题:线程清理失败
- 修复:这些已记录,但不影响响应
- 修复:检查Azure AI代理服务限制和配额
生产安全最佳实践
为了简单起见,默认部署使用公共端点。对于生产工作负载,您应该通过专用网络和其他控制来增强安全性。
当前安全配置
✅ 托管身份 -容器应用程序向AI项目进行身份验证,没有秘密
✅ 基于角色的访问控制 -对所有资源进行基于角色的访问控制
✅ 仅限HTTPS -所有在传输过程中加密的流量
✅ ACR身份验证 -安全的容器注册表访问
✅ 密钥库RBAC -基于角色的密钥库授权
⚠️ 公共端点 -可从互联网访问的资源(适用于开发/测试)
推荐的生产增强功能
1.具有虚拟网络集成的专用网络
添加ExpressRoute集成以将资源与公共互联网隔离:
// Add to resources.bicep
// Virtual Network
resource vnet 'Microsoft.Network/virtualNetworks@2023-05-01' = {
name: 'vnet-${uniqueString(resourceGroup().id)}'
location: location
tags: tags
properties: {
addressSpace: {
addressPrefixes: ['10.0.0.0/16']
}
subnets: [
{
name: 'subnet-containerapp'
properties: {
addressPrefix: '10.0.0.0/23'
delegations: [
{
name: 'Microsoft.App/environments'
properties: {
serviceName: 'Microsoft.App/environments'
}
}
]
}
}
{
name: 'subnet-privateendpoints'
properties: {
addressPrefix: '10.0.2.0/24'
privateEndpointNetworkPolicies: 'Disabled'
}
}
]
}
}
// Update Container App Environment with VNet
resource containerAppEnv 'Microsoft.App/managedEnvironments@2023-05-01' = {
name: containerAppEnvName
location: location
tags: tags
properties: {
vnetConfiguration: {
infrastructureSubnetId: vnet.properties.subnets[0].id
internal: true // Make it internal for production
}
appLogsConfiguration: {
destination: 'log-analytics'
logAnalyticsConfiguration: {
customerId: logAnalytics.properties.customerId
sharedKey: logAnalytics.listKeys().primarySharedKey
}
}
}
}
2.Azure服务的专用端点
使用专用端点保护后端服务:
// Private DNS Zones (add to resources.bicep)
resource privateDnsZoneStorage 'Microsoft.Network/privateDnsZones@2020-06-01' = {
name: 'privatelink.blob.core.windows.net'
location: 'global'
tags: tags
}
resource privateDnsZoneKeyVault 'Microsoft.Network/privateDnsZones@2020-06-01' = {
name: 'privatelink.vaultcore.azure.net'
location: 'global'
tags: tags
}
resource privateDnsZoneACR 'Microsoft.Network/privateDnsZones@2020-06-01' = {
name: 'privatelink.azurecr.io'
location: 'global'
tags: tags
}
// Link DNS Zones to VNet
resource privateDnsZoneLinkStorage 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
parent: privateDnsZoneStorage
name: 'link-storage'
location: 'global'
properties: {
registrationEnabled: false
virtualNetwork: {
id: vnet.id
}
}
}
// Private Endpoint for Storage Account
resource privateEndpointStorage 'Microsoft.Network/privateEndpoints@2023-05-01' = {
name: 'pe-storage-${uniqueString(resourceGroup().id)}'
location: location
tags: tags
properties: {
subnet: {
id: vnet.properties.subnets[1].id // Private endpoints subnet
}
privateLinkServiceConnections: [
{
name: 'storage-connection'
properties: {
privateLinkServiceId: storage.id
groupIds: ['blob']
}
}
]
}
}
// Private DNS Zone Group for Storage
resource privateDnsZoneGroupStorage 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2023-05-01' = {
parent: privateEndpointStorage
name: 'default'
properties: {
privateDnsZoneConfigs: [
{
name: 'config-storage'
properties: {
privateDnsZoneId: privateDnsZoneStorage.id
}
}
]
}
}
// Update Storage Account to disable public access
resource storage 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: 'st${uniqueString(resourceGroup().id)}'
location: location
tags: tags
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
properties: {
accessTier: 'Hot'
supportsHttpsTrafficOnly: true
minimumTlsVersion: 'TLS1_2'
publicNetworkAccess: 'Disabled' // Changed from default
networkAcls: {
defaultAction: 'Deny'
bypass: 'AzureServices'
}
}
}
// Repeat similar patterns for:
// - Key Vault private endpoint
// - Container Registry private endpoint
// - AI Hub/Project (if supported in your region)
3.网络安全组(NSG)
添加NSG规则以控制流量:
// Network Security Group (add to resources.bicep)
resource nsg 'Microsoft.Network/networkSecurityGroups@2023-05-01' = {
name: 'nsg-containerapp'
location: location
tags: tags
properties: {
securityRules: [
{
name: 'AllowHTTPSInbound'
properties: {
priority: 100
direction: 'Inbound'
access: 'Allow'
protocol: 'Tcp'
sourcePortRange: '*'
destinationPortRange: '443'
sourceAddressPrefix: 'Internet'
destinationAddressPrefix: '*'
}
}
{
name: 'DenyAllInbound'
properties: {
priority: 1000
direction: 'Inbound'
access: 'Deny'
protocol: '*'
sourcePortRange: '*'
destinationPortRange: '*'
sourceAddressPrefix: '*'
destinationAddressPrefix: '*'
}
}
]
}
}
// Associate NSG with Container App subnet
resource vnet 'Microsoft.Network/virtualNetworks@2023-05-01' = {
// ... existing properties
properties: {
// ... existing properties
subnets: [
{
name: 'subnet-containerapp'
properties: {
addressPrefix: '10.0.0.0/23'
networkSecurityGroup: {
id: nsg.id
}
delegations: [
{
name: 'Microsoft.App/environments'
properties: {
serviceName: 'Microsoft.App/environments'
}
}
]
}
}
]
}
}
4.Azure前门或应用程序网关
对于具有WAF保护的生产级入口:
// Azure Front Door with WAF (add to resources.bicep)
resource frontDoor 'Microsoft.Cdn/profiles@2023-05-01' = {
name: 'fd-${uniqueString(resourceGroup().id)}'
location: 'global'
tags: tags
sku: {
name: 'Premium_AzureFrontDoor' // Premium includes WAF
}
properties: {
originResponseTimeoutSeconds: 60
}
}
// WAF Policy
resource wafPolicy 'Microsoft.Network/FrontDoorWebApplicationFirewallPolicies@2022-05-01' = {
name: 'waf${uniqueString(resourceGroup().id)}'
location: 'global'
tags: tags
sku: {
name: 'Premium_AzureFrontDoor'
}
properties: {
policySettings: {
enabledState: 'Enabled'
mode: 'Prevention'
requestBodyCheck: 'Enabled'
}
managedRules: {
managedRuleSets: [
{
ruleSetType: 'Microsoft_DefaultRuleSet'
ruleSetVersion: '2.1'
}
{
ruleSetType: 'Microsoft_BotManagerRuleSet'
ruleSetVersion: '1.0'
}
]
}
}
}
// Front Door Endpoint
resource fdEndpoint 'Microsoft.Cdn/profiles/afdEndpoints@2023-05-01' = {
parent: frontDoor
name: 'endpoint-${uniqueString(resourceGroup().id)}'
location: 'global'
properties: {
enabledState: 'Enabled'
}
}
// Origin Group (Container Apps)
resource originGroup 'Microsoft.Cdn/profiles/originGroups@2023-05-01' = {
parent: frontDoor
name: 'containerapp-origins'
properties: {
loadBalancingSettings: {
sampleSize: 4
successfulSamplesRequired: 3
additionalLatencyInMilliseconds: 50
}
healthProbeSettings: {
probePath: '/health'
probeRequestType: 'GET'
probeProtocol: 'Https'
probeIntervalInSeconds: 30
}
sessionAffinityState: 'Enabled' // Sticky sessions
}
}
// Origins (one for each Container App instance)
resource origin0 'Microsoft.Cdn/profiles/originGroups/origins@2023-05-01' = {
parent: originGroup
name: 'origin-0'
properties: {
hostName: containerApp[0].properties.configuration.ingress.fqdn
httpPort: 80
httpsPort: 443
originHostHeader: containerApp[0].properties.configuration.ingress.fqdn
priority: 1
weight: 1000
enabledState: 'Enabled'
}
}
// Repeat for other instances...
// Route
resource route 'Microsoft.Cdn/profiles/afdEndpoints/routes@2023-05-01' = {
parent: fdEndpoint
name: 'api-route'
properties: {
originGroup: {
id: originGroup.id
}
supportedProtocols: ['Https']
patternsToMatch: ['/*']
forwardingProtocol: 'HttpsOnly'
linkToDefaultDomain: 'Enabled'
httpsRedirect: 'Enabled'
}
dependsOn: [
origin0
]
}
// Associate WAF with Endpoint
resource wafAssociation 'Microsoft.Cdn/profiles/securityPolicies@2023-05-01' = {
parent: frontDoor
name: 'waf-policy'
properties: {
parameters: {
type: 'WebApplicationFirewall'
wafPolicy: {
id: wafPolicy.id
}
associations: [
{
domains: [
{
id: fdEndpoint.id
}
]
patternsToMatch: ['/*']
}
]
}
}
}
// Output the Front Door URL
output frontDoorUrl string = 'https://${fdEndpoint.properties.hostName}'
5.诊断设置和监测
启用全面日志记录:
// Diagnostic Settings for Container Apps (add to resources.bicep)
resource diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for i in range(0, containerAppInstances): {
name: 'diag-containerapp-${i}'
scope: containerApp[i]
properties: {
workspaceId: logAnalytics.id
logs: [
{
category: 'ContainerAppConsoleLogs'
enabled: true
retentionPolicy: {
enabled: true
days: 30
}
}
{
category: 'ContainerAppSystemLogs'
enabled: true
retentionPolicy: {
enabled: true
days: 30
}
}
]
metrics: [
{
category: 'AllMetrics'
enabled: true
retentionPolicy: {
enabled: true
days: 30
}
}
]
}
}]
// Alert Rules
resource cpuAlert 'Microsoft.Insights/metricAlerts@2018-03-01' = {
name: 'alert-high-cpu'
location: 'global'
tags: tags
properties: {
description: 'Alert when CPU usage exceeds 80%'
severity: 2
enabled: true
scopes: [
containerApp[0].id
containerApp[1].id
containerApp[2].id
]
evaluationFrequency: 'PT5M'
windowSize: 'PT15M'
criteria: {
'odata.type': 'Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria'
allOf: [
{
name: 'HighCPU'
metricName: 'UsageNanoCores'
operator: 'GreaterThan'
threshold: 80
timeAggregation: 'Average'
}
]
}
actions: [] // Add action groups here
}
}
生产部署检查表
安全:
- []启用了ExpressRoute集成
- []为存储、密钥库、ACR配置了专用端点
- []后端服务上的公共网络访问已禁用
- []已配置并测试NSG规则
- []已部署Azure前门或应用程序网关
- []在预防模式下启用WAF
- []使用管理身份(无客户端机密)
- []审查并最小化RBAC权限
- []强制执行TLS 1.2最低版本
监控:
- []所有资源上都启用了诊断设置
- []已配置日志分析工作区
- []已连接应用程序洞察
- []为关键指标配置了警报规则
- []为通知创建的操作组
- []为仪表板创建的工作簿
高可用性:
- []多个容器应用程序实例(至少3个)
- []已配置健康探测器
- []会话关联已启用(如果有状态)
- []已配置自动缩放规则
- []跨区域部署(可选)
顺从:
- []已启用静态数据加密
- []强制执行传输中的数据加密
- []已启用审核日志记录
- []备份和灾难恢复计划
- []已安排访问审查
- []已应用合规标签
成本优化技巧
默认部署适用于生产环境,但可以进行优化:
-
容器应用程序扩展
scale: { minReplicas: 1 // Lower for dev, 2-3 for prod maxReplicas: 10 rules: [ { name: 'http-rule' http: { metadata: { concurrentRequests: '100' } } } ] } -
API管理SKU
- 开发者:每月50美元-仅限非生产
- 基础:150美元/月-轻生产工作量
- 标准:700美元/月-生产工作量
- 高级:3000美元/月-企业,多地区
-
集装箱登记处
- 基础:$5/月-小型项目
- 标准:20美元/月-团队项目
- 高级:每月50美元-地理复制,高吞吐量
-
存储帐户
- 使用生命周期策略存档旧日志
- 启用软删除,缩短保留时间
许可证
麻省理工学院
