Azure Event Hubs TypeScript SDK
Azure Event Hubs TypeScript SDK
高吞吐量事件流和实时数据摄取。
安装
npm install @azure/event-hubs @azure/identity如需使用消费者组进行检查点(checkpointing)管理:
npm install @azure/eventhubs-checkpointstore-blob @azure/storage-blob环境变量
EVENTHUB_NAMESPACE=<namespace>.servicebus.windows.net
EVENTHUB_NAME=my-eventhub
STORAGE_ACCOUNT_NAME=<storage-account>
STORAGE_CONTAINER_NAME=checkpoints身份验证
import { EventHubProducerClient, EventHubConsumerClient } from "@azure/event-hubs";
import { DefaultAzureCredential } from "@azure/identity";
const fullyQualifiedNamespace = process.env.EVENTHUB_NAMESPACE!;
const eventHubName = process.env.EVENTHUB_NAME!;
const credential = new DefaultAzureCredential();
// 生产者
const producer = new EventHubProducerClient(fullyQualifiedNamespace, eventHubName, credential);
// 消费者
const consumer = new EventHubConsumerClient(
"$Default", // 消费者组
fullyQualifiedNamespace,
eventHubName,
credential
);
核心工作流
发送事件
const producer = new EventHubProducerClient(namespace, eventHubName, credential);
// 创建批次并添加事件
const batch = await producer.createBatch();
batch.tryAdd({ body: { temperature: 72.5, deviceId: "sensor-1" } });
batch.tryAdd({ body: { temperature: 68.2, deviceId: "sensor-2" } });
await producer.sendBatch(batch);
await producer.close();
发送到指定分区
// 通过分区 ID
const batch = await producer.createBatch({ partitionId: "0" });
// 通过分区键(一致性哈希)
const batch = await producer.createBatch({ partitionKey: "device-123" });
接收事件(简单模式)
const consumer = new EventHubConsumerClient("$Default", namespace, eventHubName, credential);
const subscription = consumer.subscribe({
processEvents: async (events, context) => {
for (const event of events) {
console.log(Partition: ${context.partitionId}, Body: ${JSON.stringify(event.body)});
}
},
processError: async (err, context) => {
console.error(Error on partition ${context.partitionId}: ${err.message});
},
});
// 一段时间后停止
setTimeout(async () => {
await subscription.close();
await consumer.close();
}, 60000);
使用检查点接收(生产模式)
import { EventHubConsumerClient } from "@azure/event-hubs";
import { ContainerClient } from "@azure/storage-blob";
import { BlobCheckpointStore } from "@azure/eventhubs-checkpointstore-blob";
const containerClient = new ContainerClient(
https://${storageAccount}.blob.core.windows.net/${containerName},
credential
);
const checkpointStore = new BlobCheckpointStore(containerClient);
const consumer = new EventHubConsumerClient(
"$Default",
namespace,
eventHubName,
credential,
checkpointStore
);
const subscription = consumer.subscribe({
processEvents: async (events, context) => {
for (const event of events) {
console.log(Processing: ${JSON.stringify(event.body)});
}
// 处理完批次后更新检查点
if (events.length > 0) {
await context.updateCheckpoint(events[events.length - 1]);
}
},
processError: async (err, context) => {
co
nsole.error(
Error: ${err.message});},
});
### 从特定位置接收const subscription = consumer.subscribe({
processEvents: async (events, context) => { /* ... */ },
processError: async (err, context) => { /* ... */ },
}, {
startPosition: {
// 从开头开始
"0": { offset: "@earliest" },
// 从末尾开始(仅接收新事件)
"1": { offset: "@latest" },
// 从特定偏移量开始
"2": { offset: "12345" },
// 从特定时间开始
"3": { enqueuedOn: new Date("2024-01-01") },
},
});
## Event Hub 属性// 获取 Hub 信息
const hubProperties = await producer.getEventHubProperties();
console.log(
Partitions: ${hubProperties.partitionIds});
// 获取分区信息
const partitionProperties = await producer.getPartitionProperties("0");
console.log(Last sequence: ${partitionProperties.lastEnqueuedSequenceNumber});
## 批处理选项const subscription = consumer.subscribe(
{
processEvents: async (events, context) => { /* ... */ },
processError: async (err, context) => { /* ... */ },
},
{
maxBatchSize: 100, // 每批次最大事件数
maxWaitTimeInSeconds: 30, // 批次最大等待时间
}
);
## 关键类型import {
EventHubProducerClient,
EventHubConsumerClient,
EventData,
ReceivedEventData,
PartitionContext,
Subscription,
SubscriptionEventHandlers,
CreateBatchOptions,
EventPosition,
} from "@azure/event-hubs";
import { BlobCheckpointStore } from "@azure/eventhubs-checkpointstore-blob";
## 事件属性// 发送带属性的事件
const batch = await producer.createBatch();
batch.tryAdd({
body: { data: "payload" },
properties: {
eventType: "telemetry",
deviceId: "sensor-1",
},
contentType: "application/json",
correlationId: "request-123",
});
// 在接收端访问
consumer.subscribe({
processEvents: async (events, context) => {
for (const event of events) {
console.log(Type: ${event.properties?.eventType});
console.log(Sequence: ${event.sequenceNumber});
console.log(Enqueued: ${event.enqueuedTimeUtc});
console.log(Offset: ${event.offset});
}
},
});
## 错误处理consumer.subscribe({
processEvents: async (events, context) => {
try {
for (const event of events) {
await processEvent(event);
}
await context.updateCheckpoint(events[events.length - 1]);
} catch (error) {
// 出错时不更新检查点 - 事件将被重新处理
console.error("Processing failed:", error);
}
},
processError: async (err, context) => {
if (err.name === "MessagingError") {
// 瞬时错误 - SDK 将自动重试
console.warn("Transient error:", err.message);
} else {
// 致命错误
console.error("Fatal error:", err);
}
},
});
``
最佳实践
1. 使用检查点 (Checkpointing) - 在生产环境中务必使用检查点以实现精确一次处理
2. 批量发送 - 使用
createBatch() 以提高发送效率
3. 分区键 (Partition keys) - 使用分区键确保相关事件的顺序性
4. 消费者组 (Consumer groups) - 为不同的处理流水线使用独立的消费者组
5. 优雅地处理错误 - 处理失败时不要更新检查点
6. 关闭客户端 - 完成后务必关闭 producer/consumer
7. 监控积压 (Lag) - 跟踪 lastEnqueuedSequenceNumber` 与已处理序列号的差值
Whe
使用指南
本技能适用于执行概览中所描述的工作流或操作。局限性
- 仅在任务与上述范围明确匹配时使用本技能。
- 不要将输出结果视为针对特定环境的验证、测试或专家评审的替代方案。
- 如果缺少必要的输入、权限、安全边界或成功标准,请停止操作并寻求澄清。