Azure SDK 教程
1. 什么是 Azure SDK?
Azure SDK (Software Development Kit) 是 Microsoft Azure 提供的开发工具包,它允许开发者在自己的应用中轻松集成 Azure 服务。Azure SDK for JavaScript 是专门为 JavaScript 和 Node.js 开发者设计的 SDK,支持浏览器和 Node.js 环境。
2. Azure SDK 的核心概念
2.1 客户端 (Client)
客户端是与 Azure 服务交互的主要接口,每个 Azure 服务都有对应的客户端类。
2.2 认证 (Authentication)
认证用于验证对 Azure 服务的访问权限,Azure SDK 支持多种认证方式,包括服务 principal、Managed Identity、Azure CLI 等。
2.3 配置 (Configuration)
配置包含认证信息、区域、端点等信息,用于初始化客户端。
2.4 响应 (Response)
响应是 Azure 服务返回的数据,通常包含状态码、 headers 和 body。
2.5 错误处理 (Error Handling)
Azure SDK 提供了统一的错误处理机制,包括重试策略和错误分类。
2.6 Promise 和异步操作
Azure SDK for JavaScript 使用 Promise 和 async/await 语法处理异步操作。
3. Azure SDK 的安装和配置
3.1 安装 Azure SDK
使用 npm 或 yarn 安装 Azure SDK for JavaScript:
# 安装核心包
npm install @azure/identity
# 安装特定服务的客户端
npm install @azure/storage-blob @azure/cosmos @azure/keyvault-secrets3.2 配置认证
Azure SDK 支持多种认证方式:
- Azure CLI:使用本地安装的 Azure CLI 进行认证
- Managed Identity:在 Azure 资源(如 VM、App Service)中使用托管身份
- 服务 Principal:使用客户端 ID、客户端密钥和租户 ID 进行认证
- 环境变量:使用环境变量设置认证信息
3.3 初始化客户端
// 使用 DefaultAzureCredential 进行认证
const { DefaultAzureCredential } = require('@azure/identity');
const { BlobServiceClient } = require('@azure/storage-blob');
const credential = new DefaultAzureCredential();
const blobServiceClient = new BlobServiceClient(
'https://your-storage-account.blob.core.windows.net',
credential
);
// 使用服务 Principal 进行认证
const { ClientSecretCredential } = require('@azure/identity');
const { SecretClient } = require('@azure/keyvault-secrets');
const credential = new ClientSecretCredential(
'your-tenant-id',
'your-client-id',
'your-client-secret'
);
const secretClient = new SecretClient(
'https://your-key-vault.vault.azure.net',
credential
);4. Azure SDK 的基本使用
4.1 使用 Blob Storage 服务
上传文件到 Blob Storage:
const { DefaultAzureCredential } = require('@azure/identity');
const { BlobServiceClient } = require('@azure/storage-blob');
const fs = require('fs');
const credential = new DefaultAzureCredential();
const blobServiceClient = new BlobServiceClient(
'https://your-storage-account.blob.core.windows.net',
credential
);
async function uploadFile(containerName, blobName, filePath) {
// 获取容器客户端
const containerClient = blobServiceClient.getContainerClient(containerName);
// 确保容器存在
await containerClient.createIfNotExists();
// 获取 blob 客户端
const blobClient = containerClient.getBlockBlobClient(blobName);
// 上传文件
const fileContent = fs.readFileSync(filePath);
const uploadResult = await blobClient.upload(fileContent, fileContent.length);
console.log('File uploaded successfully:', uploadResult);
return uploadResult;
}
// 使用示例
uploadFile('my-container', 'example.txt', './example.txt');下载 Blob Storage 中的文件:
const { DefaultAzureCredential } = require('@azure/identity');
const { BlobServiceClient } = require('@azure/storage-blob');
const fs = require('fs');
const credential = new DefaultAzureCredential();
const blobServiceClient = new BlobServiceClient(
'https://your-storage-account.blob.core.windows.net',
credential
);
async function downloadFile(containerName, blobName, filePath) {
// 获取容器客户端
const containerClient = blobServiceClient.getContainerClient(containerName);
// 获取 blob 客户端
const blobClient = containerClient.getBlockBlobClient(blobName);
// 下载文件
const downloadResponse = await blobClient.download();
const downloadContent = await streamToBuffer(downloadResponse.readableStreamBody);
// 写入文件
fs.writeFileSync(filePath, downloadContent);
console.log('File downloaded successfully');
return downloadContent;
}
// 辅助函数:将流转换为缓冲区
function streamToBuffer(readableStream) {
return new Promise((resolve, reject) => {
const chunks = [];
readableStream.on('data', (data) => {
chunks.push(data instanceof Buffer ? data : Buffer.from(data));
});
readableStream.on('end', () => {
resolve(Buffer.concat(chunks));
});
readableStream.on('error', reject);
});
}
// 使用示例
downloadFile('my-container', 'example.txt', './downloaded-example.txt');4.2 使用 Cosmos DB 服务
创建数据库和容器:
const { DefaultAzureCredential } = require('@azure/identity');
const { CosmosClient } = require('@azure/cosmos');
const credential = new DefaultAzureCredential();
const cosmosClient = new CosmosClient({
endpoint: 'https://your-cosmos-account.documents.azure.com:443/',
aadCredentials: credential
});
async function createDatabaseAndContainer() {
// 创建数据库
const { database } = await cosmosClient.databases.createIfNotExists({
id: 'my-database'
});
console.log('Database created:', database.id);
// 创建容器
const { container } = await database.containers.createIfNotExists({
id: 'my-container',
partitionKey: { paths: ['/partitionKey'] }
});
console.log('Container created:', container.id);
return { database, container };
}
// 使用示例
createDatabaseAndContainer();写入数据:
const { DefaultAzureCredential } = require('@azure/identity');
const { CosmosClient } = require('@azure/cosmos');
const credential = new DefaultAzureCredential();
const cosmosClient = new CosmosClient({
endpoint: 'https://your-cosmos-account.documents.azure.com:443/',
aadCredentials: credential
});
async function createItem() {
// 获取数据库和容器
const database = cosmosClient.database('my-database');
const container = database.container('my-container');
// 创建项
const item = {
id: '1',
partitionKey: 'partition1',
name: 'John Doe',
email: 'john@example.com'
};
const { resource } = await container.items.create(item);
console.log('Item created:', resource);
return resource;
}
// 使用示例
createItem();读取数据:
const { DefaultAzureCredential } = require('@azure/identity');
const { CosmosClient } = require('@azure/cosmos');
const credential = new DefaultAzureCredential();
const cosmosClient = new CosmosClient({
endpoint: 'https://your-cosmos-account.documents.azure.com:443/',
aadCredentials: credential
});
async function readItem() {
// 获取数据库和容器
const database = cosmosClient.database('my-database');
const container = database.container('my-container');
// 读取项
const { resource } = await container.item('1', 'partition1').read();
console.log('Item read:', resource);
return resource;
}
// 使用示例
readItem();4.3 使用 Key Vault 服务
存储密钥:
const { DefaultAzureCredential } = require('@azure/identity');
const { SecretClient } = require('@azure/keyvault-secrets');
const credential = new DefaultAzureCredential();
const secretClient = new SecretClient(
'https://your-key-vault.vault.azure.net',
credential
);
async function setSecret() {
// 存储密钥
const secretName = 'my-secret';
const secretValue = 'my-secret-value';
const result = await secretClient.setSecret(secretName, secretValue);
console.log('Secret set:', result.name);
return result;
}
// 使用示例
setSecret();读取密钥:
const { DefaultAzureCredential } = require('@azure/identity');
const { SecretClient } = require('@azure/keyvault-secrets');
const credential = new DefaultAzureCredential();
const secretClient = new SecretClient(
'https://your-key-vault.vault.azure.net',
credential
);
async function getSecret() {
// 读取密钥
const secretName = 'my-secret';
const result = await secretClient.getSecret(secretName);
console.log('Secret retrieved:', result.value);
return result;
}
// 使用示例
getSecret();4. Azure SDK 的高级功能
4.1 使用重试策略
Azure SDK 提供了内置的重试策略,可以配置重试次数、延迟和错误分类:
const { DefaultAzureCredential } = require('@azure/identity');
const { BlobServiceClient, RetryPolicyType } = require('@azure/storage-blob');
const credential = new DefaultAzureCredential();
const blobServiceClient = new BlobServiceClient(
'https://your-storage-account.blob.core.windows.net',
credential,
{
retryOptions: {
maxTries: 4,
retryDelayInMs: 1000,
maxRetryDelayInMs: 10000,
retryPolicyType: RetryPolicyType.EXPONENTIAL
}
}
);4.2 使用分页器
分页器用于处理返回大量数据的 API 操作,例如列出 Blob 存储中的所有容器:
const { DefaultAzureCredential } = require('@azure/identity');
const { BlobServiceClient } = require('@azure/storage-blob');
const credential = new DefaultAzureCredential();
const blobServiceClient = new BlobServiceClient(
'https://your-storage-account.blob.core.windows.net',
credential
);
async function listAllContainers() {
const containers = [];
let marker;
do {
const listContainersResponse = await blobServiceClient.listContainers({ marker });
containers.push(...listContainersResponse.containerItems);
marker = listContainersResponse.continuationToken;
} while (marker);
console.log('All containers retrieved:', containers.length);
return containers;
}
// 使用示例
listAllContainers();4.3 使用批量操作
批量操作允许在单个请求中执行多个操作,例如批量上传多个 Blob:
const { DefaultAzureCredential } = require('@azure/identity');
const { BlobServiceClient } = require('@azure/storage-blob');
const credential = new DefaultAzureCredential();
const blobServiceClient = new BlobServiceClient(
'https://your-storage-account.blob.core.windows.net',
credential
);
async function batchUpload() {
const containerClient = blobServiceClient.getContainerClient('my-container');
await containerClient.createIfNotExists();
// 创建批量操作客户端
const batchClient = containerClient.getBlobBatchClient();
// 准备批量操作
const operations = [];
// 添加上传操作
operations.push(
batchClient.getUploadBlobBatchOperation('blob1.txt', Buffer.from('Content 1')),
batchClient.getUploadBlobBatchOperation('blob2.txt', Buffer.from('Content 2')),
batchClient.getUploadBlobBatchOperation('blob3.txt', Buffer.from('Content 3'))
);
// 执行批量操作
const results = await batchClient.submitBatch(operations);
console.log('Batch upload completed:', results.length);
return results;
}
// 使用示例
batchUpload();4.4 使用流式处理
Azure SDK 支持流式处理,例如流式上传和下载大文件:
const { DefaultAzureCredential } = require('@azure/identity');
const { BlobServiceClient } = require('@azure/storage-blob');
const fs = require('fs');
const credential = new DefaultAzureCredential();
const blobServiceClient = new BlobServiceClient(
'https://your-storage-account.blob.core.windows.net',
credential
);
async function streamUpload() {
const containerClient = blobServiceClient.getContainerClient('my-container');
await containerClient.createIfNotExists();
const blobClient = containerClient.getBlockBlobClient('large-file.txt');
const fileStream = fs.createReadStream('./large-file.txt');
const fileSize = fs.statSync('./large-file.txt').size;
// 流式上传
await blobClient.uploadStream(fileStream, fileSize);
console.log('File uploaded as stream');
}
// 使用示例
streamUpload();5. Azure SDK 的最佳实践
5.1 安全最佳实践
- 使用托管身份:在 Azure 资源中优先使用托管身份,避免存储凭证
- 最小权限原则:为应用授予必要的最小权限
- 使用 Key Vault:将敏感信息存储在 Key Vault 中,而不是硬编码在应用中
- 加密传输:始终使用 HTTPS 与 Azure 服务通信
5.2 性能最佳实践
- 重用客户端实例:避免频繁创建客户端实例
- 使用批量操作:对于多个相似操作,使用批量 API 减少网络往返
- 使用流式处理:对于大文件,使用流式上传和下载
- 选择合适的区域:选择离用户最近的区域,减少延迟
5.3 错误处理最佳实践
- 实现重试策略:对于临时错误,使用指数退避重试
- 捕获和处理特定错误:根据错误类型采取不同的处理策略
- 记录错误信息:详细记录错误信息,便于调试
- 设置合理的超时:避免请求无限期等待
5.4 代码组织最佳实践
- 模块化:将 Azure 服务相关代码组织成模块
- 使用异步/await:使用现代 JavaScript 语法处理异步操作
- 编写单元测试:为 Azure SDK 代码编写单元测试
- 使用 TypeScript:使用 TypeScript 提高代码可靠性
6. 实际应用示例
6.1 构建一个文件上传服务
const express = require('express');
const multer = require('multer');
const { DefaultAzureCredential } = require('@azure/identity');
const { BlobServiceClient } = require('@azure/storage-blob');
const { v4: uuidv4 } = require('uuid');
const app = express();
const upload = multer({ storage: multer.memoryStorage() });
const credential = new DefaultAzureCredential();
const blobServiceClient = new BlobServiceClient(
'https://your-storage-account.blob.core.windows.net',
credential
);
const containerName = 'my-file-upload-container';
app.post('/upload', upload.single('file'), async (req, res) => {
try {
const file = req.file;
const blobName = `${uuidv4()}-${file.originalname}`;
const containerClient = blobServiceClient.getContainerClient(containerName);
await containerClient.createIfNotExists();
const blobClient = containerClient.getBlockBlobClient(blobName);
await blobClient.upload(file.buffer, file.buffer.length, {
blobHTTPHeaders: { blobContentType: file.mimetype }
});
const fileUrl = blobClient.url;
res.json({ success: true, fileUrl });
} catch (error) {
console.error('Error uploading file:', error);
res.status(500).json({ success: false, error: 'Failed to upload file' });
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});6.2 构建一个用户数据存储服务
const express = require('express');
const { DefaultAzureCredential } = require('@azure/identity');
const { CosmosClient } = require('@azure/cosmos');
const { v4: uuidv4 } = require('uuid');
const app = express();
app.use(express.json());
const credential = new DefaultAzureCredential();
const cosmosClient = new CosmosClient({
endpoint: 'https://your-cosmos-account.documents.azure.com:443/',
aadCredentials: credential
});
const databaseId = 'my-database';
const containerId = 'users';
async function initializeCosmos() {
const { database } = await cosmosClient.databases.createIfNotExists({ id: databaseId });
await database.containers.createIfNotExists({
id: containerId,
partitionKey: { paths: ['/id'] }
});
console.log('Cosmos DB initialized');
}
initializeCosmos();
app.post('/users', async (req, res) => {
try {
const user = {
id: uuidv4(),
...req.body
};
const database = cosmosClient.database(databaseId);
const container = database.container(containerId);
const { resource } = await container.items.create(user);
res.json({ success: true, user: resource });
} catch (error) {
console.error('Error creating user:', error);
res.status(500).json({ success: false, error: 'Failed to create user' });
}
});
app.get('/users/:id', async (req, res) => {
try {
const { id } = req.params;
const database = cosmosClient.database(databaseId);
const container = database.container(containerId);
const { resource } = await container.item(id, id).read();
if (!resource) {
return res.status(404).json({ success: false, error: 'User not found' });
}
res.json({ success: true, user: resource });
} catch (error) {
console.error('Error getting user:', error);
res.status(500).json({ success: false, error: 'Failed to get user' });
}
});
app.get('/users', async (req, res) => {
try {
const database = cosmosClient.database(databaseId);
const container = database.container(containerId);
const { resources } = await container.items.readAll().fetchAll();
res.json({ success: true, users: resources });
} catch (error) {
console.error('Error getting users:', error);
res.status(500).json({ success: false, error: 'Failed to get users' });
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});6.3 构建一个密钥管理服务
const express = require('express');
const { DefaultAzureCredential } = require('@azure/identity');
const { SecretClient } = require('@azure/keyvault-secrets');
const app = express();
app.use(express.json());
const credential = new DefaultAzureCredential();
const secretClient = new SecretClient(
'https://your-key-vault.vault.azure.net',
credential
);
app.post('/secrets', async (req, res) => {
try {
const { name, value } = req.body;
const result = await secretClient.setSecret(name, value);
res.json({ success: true, secret: { name: result.name, value: result.value } });
} catch (error) {
console.error('Error setting secret:', error);
res.status(500).json({ success: false, error: 'Failed to set secret' });
}
});
app.get('/secrets/:name', async (req, res) => {
try {
const { name } = req.params;
const result = await secretClient.getSecret(name);
res.json({ success: true, secret: { name: result.name, value: result.value } });
} catch (error) {
console.error('Error getting secret:', error);
res.status(500).json({ success: false, error: 'Failed to get secret' });
}
});
app.get('/secrets', async (req, res) => {
try {
const secrets = [];
for await (const secretProperties of secretClient.listPropertiesOfSecrets()) {
const secret = await secretClient.getSecret(secretProperties.name);
secrets.push({ name: secret.name, value: secret.value });
}
res.json({ success: true, secrets });
} catch (error) {
console.error('Error listing secrets:', error);
res.status(500).json({ success: false, error: 'Failed to list secrets' });
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});7. Azure SDK 与其他云 SDK 的比较
7.1 Azure SDK vs AWS SDK
- 认证方式:Azure SDK 使用 AAD (Azure Active Directory) 进行认证,而 AWS SDK 使用访问密钥和秘密访问密钥
- 客户端初始化:Azure SDK 通常需要 endpoint 和认证信息,而 AWS SDK 需要区域和认证信息
- 错误处理:两者都提供了统一的错误处理机制,但错误类型和结构不同
- API 设计:两者都使用 Promise 和 async/await,但 API 设计风格不同
7.2 Azure SDK vs Google Cloud SDK
- 认证方式:Azure SDK 使用 AAD,而 Google Cloud SDK 使用服务账号密钥
- 客户端初始化:Azure SDK 需要 endpoint,而 Google Cloud SDK 需要项目 ID
- 服务覆盖:两者都覆盖了各自云平台的主要服务,但具体服务和 API 不同
- 性能:两者都针对各自平台进行了优化,性能相近
8. 总结
Azure SDK for JavaScript 是一个强大的工具包,它允许开发者在 JavaScript 和 Node.js 应用中轻松集成 Azure 服务。通过本教程的学习,你应该已经掌握了 Azure SDK 的核心概念、安装配置、基本使用和高级功能。
Azure SDK 的主要优势包括:
- 全面的服务支持:支持所有 Azure 服务
- 现代 JavaScript 语法:使用 Promise 和 async/await
- 统一的认证机制:支持多种认证方式
- 内置的重试策略:提高应用的可靠性
- 丰富的功能:包括批量操作、流式处理和分页器等
通过遵循最佳实践,你可以构建安全、高性能、可靠的 Azure 集成应用。无论是构建 Web 应用、移动应用后端还是云原生应用,Azure SDK 都能为你提供强大的支持。