微服务架构 - 容器应用示例 ⏱️ 预计时间:25-35 分钟 | 预计成本:约 $50-100/月 | ⭐ 复杂度:高级 一个简化但功能齐全的微服务架构,使用 AZD CLI 部署到 Azure 容器应用。本示例展示了服务间通信、容器编排和监控,采用了实用的两服务设置。 学习方法:本示例从一个最小的两服务架构(API 网关 + 后端服务)开始,您可以实际部署并学习。在掌握这一基础后,我们提供扩展到完整微服务生态系统的指导。
⏱️ 预计时间:25-35 分钟 | 预计成本:约 $50-100/月 | ⭐ 复杂度:高级
一个简化但功能齐全的微服务架构,使用 AZD CLI 部署到 Azure 容器应用。本示例展示了服务间通信、容器编排和监控,采用了实用的两服务设置。
** 学习方法**:本示例从一个最小的两服务架构(API 网关 + 后端服务)开始,您可以实际部署并学习。在掌握这一基础后,我们提供扩展到完整微服务生态系统的指导。
完成本示例后,您将能够:
┌─────────────────────────────┐ │ Internet │ └──────────────┬──────────────┘ │ │ HTTPS │ ┌──────────────▼──────────────┐ │ API Gateway │ │ (Node.js Container) │ │ - Routes requests │ │ - Health checks │ │ - Request logging │ └──────────────┬──────────────┘ │ │ HTTP (internal) │ ┌──────────────▼──────────────┐ │ Product Service │ │ (Python Container) │ │ - Product CRUD │ │ - In-memory data store │ │ - REST API │ └──────────────┬──────────────┘ │ ┌──────────────▼──────────────┐ │ Application Insights │ │ (Monitoring & Logs) │ └─────────────────────────────┘
为什么从简单开始?
类比:这就像学习驾驶。您从空停车场(2 个服务)开始,掌握基础知识,然后逐步进入城市交通(5+ 服务,带数据库)。
在掌握两服务架构后,您可以扩展到:
Full Architecture (Not Included - For Reference) ├── API Gateway (✅ Included) ├── Product Service (✅ Included) ├── Order Service ( Add next) ├── User Service ( Add next) ├── Notification Service ( Add last) ├── Azure Service Bus ( For async communication) ├── Cosmos DB ( For product persistence) ├── Azure SQL ( For order management) └── Azure Storage ( For file storage)
请参阅文末的“扩展指南”部分,获取分步说明。
✅ 服务发现:基于 DNS 的容器间自动发现
✅ 负载均衡:内置跨副本的负载均衡
✅ 自动扩展:基于 HTTP 请求的独立服务扩展
✅ 健康监控:两服务的存活性和就绪性探针
✅ 分布式日志记录:使用 Application Insights 的集中式日志记录
✅ 内部网络:安全的服务间通信
✅ 容器编排:自动部署和扩展
✅ 零停机更新:带版本管理的滚动更新
开始之前,请确认您已安装以下工具:
Azure Developer CLI (azd)(版本 1.0.0 或更高)
azd version # 预期输出:azd版本1.0.0或更高
Azure CLI(版本 2.50.0 或更高)
az --version # 预期输出:azure-cli 2.50.0或更高版本
Docker(用于本地开发/测试 - 可选)
docker --version # 预期输出:Docker版本20.10或更高
这是一个高级示例。您应具备:
刚接触容器应用? 请先从 Simple Flask API 示例 开始学习基础知识。
git clone https://github.com/microsoft/AZD-for-beginners.git cd AZD-for-beginners/examples/container-app/microservices
✓ 成功检查:确认您能看到 azure.yaml:
ls # 预期:README.md, azure.yaml, infra/, src/
azd auth login
这将打开您的浏览器进行 Azure 身份验证。使用您的 Azure 凭据登录。
✓ 成功检查:您应看到:
Logged in to Azure.
azd init
您将看到的提示:
microservices-dev)eastus,westeurope)✓ 成功检查:您应看到:
SUCCESS: New project initialized!
azd up
发生了什么(需要 8-12 分钟):
✓ 成功检查:您应看到:
SUCCESS: Your application was deployed to Azure in X minutes Y seconds. Endpoint: https://api-gateway-<unique-id>.azurecontainerapps.io
⏱️ 时间:8-12 分钟
# 获取网关端点 GATEWAY_URL=$(azd env get-values | grep API_GATEWAY_URL | cut -d '=' -f2 | tr -d '"') # 测试 API 网关健康状况 curl $GATEWAY_URL/health # 预期输出: # {"status":"healthy","service":"api-gateway","timestamp":"2025-11-19T10:30:00Z"}
通过网关测试产品服务:
# 列出产品 curl $GATEWAY_URL/api/products # 预期输出: # [ # {"id":1,"name":"笔记本电脑","price":999.99,"stock":50}, # {"id":2,"name":"鼠标","price":29.99,"stock":200}, # {"id":3,"name":"键盘","price":79.99,"stock":150} # ]
✓ 成功检查:两个端点均返回 JSON 数据且无错误。
** 恭喜!** 您已将微服务架构部署到 Azure!
所有实现文件均已包含——这是一个完整的、可运行的示例:
microservices/ │ ├── README.md # This file ├── azure.yaml # AZD configuration ├── .gitignore # Git ignore patterns │ ├── infra/ # Infrastructure as Code (Bicep) │ ├── main.bicep # Main orchestration │ ├── abbreviations.json # Naming conventions │ ├── core/ # Shared infrastructure │ │ ├── container-apps-environment.bicep # Container environment + registry │ │ └── monitor.bicep # Application Insights + Log Analytics │ └── app/ # Service definitions │ ├── api-gateway.bicep # API Gateway container app │ └── product-service.bicep # Product Service container app │ └── src/ # Application source code ├── api-gateway/ # Node.js API Gateway │ ├── app.js # Express server with routing │ ├── package.json # Node dependencies │ └── Dockerfile # Container definition └── product-service/ # Python Product Service ├── main.py # Flask API with product data ├── requirements.txt # Python dependencies └── Dockerfile # Container definition
每个组件的作用:
基础设施(infra/):
main.bicep:编排所有 Azure 资源及其依赖项core/container-apps-environment.bicep:创建容器应用环境和 Azure 容器注册表core/monitor.bicep:设置用于分布式日志记录的 Application Insightsapp/*.bicep:包含扩展和健康检查的单个容器应用定义API 网关(src/api-gateway/):
产品服务(src/product-service/):
端口:8080
访问:公共(外部入口)
目的:将传入请求路由到相应的后端服务
端点:
GET / - 服务信息GET /health - 健康检查端点GET /api/products - 转发到产品服务(列出所有)GET /api/products/:id - 转发到产品服务(按 ID 获取)关键功能:
代码亮点(src/api-gateway/app.js):
// 内部服务通信 app.get('/api/products', async (req, res) => { const response = await axios.get(`${PRODUCT_SERVICE_URL}/products`); res.json(response.data); });
端口:8000
访问:仅限内部(无外部入口)
目的:管理带内存数据的产品目录
端点:
GET / - 服务信息GET /health - 健康检查端点GET /products - 列出所有产品GET /products/<id> - 按 ID 获取产品关键功能:
数据模型:
{ "id": 1, "name": "Laptop", "description": "High-performance laptop", "price": 999.99, "stock": 50 }
为什么仅限内部?
产品服务不对外公开。所有请求必须通过 API 网关,这提供了:
在本示例中,API 网关通过内部 HTTP 调用与产品服务通信:
// API网关 (src/api-gateway/app.js) const PRODUCT_SERVICE_URL = process.env.PRODUCT_SERVICE_URL; // 发起内部HTTP请求 const response = await axios.get(`${PRODUCT_SERVICE_URL}/products`);
关键点:
基于 DNS 的发现:容器应用自动为内部服务提供 DNS
product-service.internal.<environment>.azurecontainerapps.iohttp://product-service(容器应用会解析)无公共暴露:产品服务在 Bicep 中设置为 external: false
环境变量:服务 URL 在部署时注入
类比:这就像办公室房间。API 网关是接待处(面向公众),而产品服务是办公室房间(仅限内部)。访客必须通过接待处才能进入任何办公室。
# 部署基础设施和两个服务 azd up
这将部署:
时间:8-12 分钟
# 仅部署一个服务(在初始 azd up 之后) azd deploy api-gateway # 或部署产品服务 azd deploy product-service
使用场景:当您更新了某个服务的代码并希望仅重新部署该服务时。
# 更改缩放参数 azd env set GATEWAY_MAX_REPLICAS 30 # 使用新配置重新部署 azd up
两服务在其 Bicep 文件中配置了基于 HTTP 的自动扩展:
API 网关:
产品服务:
自定义扩展(在 infra/app/*.bicep 中):
scale: { minReplicas: 1 maxReplicas: 10 rules: [ { name: 'http-scale-rule' http: { metadata: { concurrentRequests: '100' // Adjust this } } } ] }
API 网关:
产品服务:
两服务均包含存活性和就绪性探针:
probes: [ { type: 'Liveness' httpGet: { path: '/health' port: 8080 } initialDelaySeconds: 10 periodSeconds: 30 } { type: 'Readiness' httpGet: { path: '/health' port: 8080 } initialDelaySeconds: 5 periodSeconds: 10 } ]
这意味着:
# 从 API Gateway 流式传输日志 azd logs api-gateway --follow # 查看最近的产品服务日志 azd logs product-service --tail 100 # 查看两个服务的所有日志 azd logs --follow
预期输出:
[api-gateway] API Gateway listening on port 8080 [api-gateway] Product Service URL: http://product-service [api-gateway] GET /api/products 200 - 45ms [product-service] Retrieved 5 products
在 Azure 门户中访问 Application Insights,然后运行以下查询:
查找慢请求:
requests | where timestamp > ago(1h) | where duration > 1000 // Requests taking >1 second | summarize count() by name, cloud_RoleName | order by count_ desc
跟踪服务间调用:
dependencies | where timestamp > ago(1h) | where type == "Http" | project timestamp, name, target, duration, success | order by timestamp desc
按服务的错误率:
exceptions | where timestamp > ago(24h) | summarize errorCount = count() by cloud_RoleName, type | order by errorCount desc
随时间的请求量:
requests | where timestamp > ago(1h) | summarize requestCount = count() by bin(timestamp, 5m), cloud_RoleName | render timechart
# 获取应用程序洞察详细信息 azd env get-values | grep APPLICATIONINSIGHTS # 打开 Azure 门户监控 az monitor app-insights component show \ --app $(azd env get-values | grep APPLICATIONINSIGHTS_CONNECTION_STRING | cut -d '=' -f2) \ --resource-group $(azd env get-values | grep AZURE_RESOURCE_GROUP | cut -d '=' -f2) \ --query "appId" -o tsv
curl $(azd env get-values | grep API_GATEWAY_URL | cut -d '=' -f2 | tr -d '"')/api/products[注意:请参阅上文“实践练习”部分,获取包括部署验证、数据修改、自动扩展测试、错误处理以及添加第三个服务的详细分步练习。]
| 资源 | 配置 | 预计成本 |
|---|---|---|
| API 网关 | 2-20 副本,1 vCPU,2GB RAM | $30-150 |
| 产品服务 | 1-10 副本,0.5 vCPU,1GB RAM | $15-75 |
| 容器注册表 | 基本层 | $5 |
| Application Insights | 1-2 GB/月 | $5-10 |
| 日志分析 | 1 GB/月 | $3 |
| 总计 | $58-243/月 |
按使用情况的成本分解:
开发时缩减到零:
scale: { minReplicas: 0 // Save $30-40/month when not in use maxReplicas: 10 }
为 Cosmos DB 使用消费计划(当您添加它时):
设置 Application Insights 采样:
appInsights.defaultClient.config.samplingPercentage = 50; // 抽取50%的请求
不需要时清理:
azd down
用于学习/测试,请考虑:
为避免持续费用,请删除所有资源:
azd down --force --purge
确认提示:
? Total resources to delete: 6, are you sure you want to continue? (y/N)
输入 y 以确认。
删除内容:
✓ 验证清理:
az group list --query "[?starts_with(name,'rg-microservices')]" --output table
应返回空结果。
掌握了这个两服务架构后,可以按以下步骤扩展:
为产品服务添加 Cosmos DB:
创建 infra/core/cosmos.bicep:
resource cosmosAccount 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' = { name: name location: location kind: 'GlobalDocumentDB' properties: { databaseAccountOfferType: 'Standard' locations: [{ locationName: location, failoverPriority: 0 }] } }
更新产品服务以使用 Cosmos DB 替代内存数据
预计额外成本:~$25/月(无服务器模式)
创建订单服务:
src/order-service/(Python/Node.js/C#)infra/app/order-service.bicep/api/orders架构变为:
API Gateway → Product Service (Cosmos DB) → Order Service (Azure SQL)
实现事件驱动架构:
infra/core/servicebus.bicep模式:请求/响应(HTTP)+ 事件驱动(服务总线)
实现用户服务:
src/user-service/(Go/Node.js)添加以下组件:
完整生产架构成本:~$300-1,400/月
单容器应用(简单 Flask API 示例):
微服务(本示例):
Kubernetes (AKS):
推荐:从容器应用(本示例)开始,仅在需要 Kubernetes 特定功能时迁移到 AKS。
问:为什么只有 2 个服务而不是 5 个以上?
答:学习进阶。通过简单示例掌握基础知识(服务通信、监控、扩展)后再增加复杂性。这里学到的模式适用于 100 个服务的架构。
问:我可以自己添加更多服务吗?
答:当然可以!按照上面的扩展指南操作。每个新服务遵循相同的模式:创建 src 文件夹,创建 Bicep 文件,更新 azure.yaml,部署。
问:这是生产就绪的吗?
答:这是一个坚实的基础。对于生产环境,请添加:托管身份、Key Vault、持久化数据库、CI/CD 流水线、监控警报和备份策略。
问:为什么不使用 Dapr 或其他服务网格?
答:为了学习保持简单。一旦理解了原生容器应用的网络功能,可以在高级场景中叠加使用 Dapr。
问:如何在本地调试?
答:使用 Docker 在本地运行服务:
cd src/api-gateway docker build -t local-gateway . docker run -p 8080:8080 -e PRODUCT_SERVICE_URL=http://localhost:8000 local-gateway
问:可以使用不同的编程语言吗?
答:可以!本示例展示了 Node.js(网关)+ Python(产品服务)。您可以混合使用任何可以运行在容器中的语言。
问:如果我没有 Azure 额度怎么办?
答:使用 Azure 免费层(新账户前 30 天)或短期测试后立即删除部署。
** 学习路径总结**:您已经学会了部署一个具有自动扩展、内部网络、集中监控和生产就绪模式的多服务架构。这一基础为复杂的分布式系统和企业级微服务架构做好了准备。
** 课程导航:**
免责声明:
本文档使用AI翻译服务Co-op Translator进行翻译。尽管我们努力确保翻译的准确性,但请注意,自动翻译可能包含错误或不准确之处。原始语言的文档应被视为权威来源。对于关键信息,建议使用专业人工翻译。我们对因使用此翻译而产生的任何误解或误读不承担责任。