Azure Event Hubs Java SDK

azure-eventhub-java
分类编程
作者Agentic Awesome Skills 社区
许可MIT
评分4.80/5
使用5.6K

Azure Event Hubs Java SDK

使用 Azure Event Hubs Java SDK 构建实时流应用程序。

安装

xml
<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-messaging-eventhubs</artifactId>
    <version>5.19.0</version>
</dependency>

<!-- 用于检查点存储 (生产环境) -->
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-messaging-eventhubs-checkpointstore-blob</artifactId>
<version>1.20.0</version>
</dependency>

客户端创建

EventHubProducerClient

java
import com.azure.messaging.eventhubs.EventHubProducerClient;
import com.azure.messaging.eventhubs.EventHubClientBuilder;

// 使用连接字符串
EventHubProducerClient producer = new EventHubClientBuilder()
.connectionString("<connection-string>", "<event-hub-name>")
.buildProducerClient();

// 使用包含 EntityPath 的完整连接字符串
EventHubProducerClient producer = new EventHubClientBuilder()
.connectionString("<connection-string-with-entity-path>")
.buildProducerClient();

使用 DefaultAzureCredential

java
import com.azure.identity.DefaultAzureCredentialBuilder;

EventHubProducerClient producer = new EventHubClientBuilder()
.fullyQualifiedNamespace("<namespace>.servicebus.windows.net")
.eventHubName("<event-hub-name>")
.credential(new DefaultAzureCredentialBuilder().build())
.buildProducerClient();

EventHubConsumerClient

java
import com.azure.messaging.eventhubs.EventHubConsumerClient;

EventHubConsumerClient consumer = new EventHubClientBuilder()
.connectionString("<connection-string>", "<event-hub-name>")
.consumerGroup(EventHubClientBuilder.DEFAULT_CONSUMER_GROUP_NAME)
.buildConsumerClient();

异步客户端

java
import com.azure.messaging.eventhubs.EventHubProducerAsyncClient;
import com.azure.messaging.eventhubs.EventHubConsumerAsyncClient;

EventHubProducerAsyncClient asyncProducer = new EventHubClientBuilder()
.connectionString("<connection-string>", "<event-hub-name>")
.buildAsyncProducerClient();

EventHubConsumerAsyncClient asyncConsumer = new EventHubClientBuilder()
.connectionString("<connection-string>", "<event-hub-name>")
.consumerGroup("$Default")
.buildAsyncConsumerClient();

核心模式

发送单个事件

java
import com.azure.messaging.eventhubs.EventData;

EventData eventData = new EventData("Hello, Event Hubs!");
producer.send(Collections.singletonList(eventData));

发送事件批次

java
import com.azure.messaging.eventhubs.EventDataBatch;
import com.azure.messaging.eventhubs.models.CreateBatchOptions;

// 创建批次
EventDataBatch batch = producer.createBatch();

// 添加事件 (如果批次已满则返回 false)
for (int i = 0; i < 100; i++) {
EventData event = new EventData("Event " + i);
if (!batch.tryAdd(event)) {
// 批次已满,发送并创建新批次
producer.send(batch);
batch = producer.createBatch();
batch.tryAdd(event);
}
}

// 发送剩余事件
if (batch.getCount() > 0) {
producer.send(batch);
}

发送到指定分区

java
CreateBatchOptions options = new CreateBatchOptio
ns() .setPartitionId("0");

EventDataBatch batch = producer.createBatch(options);
batch.tryAdd(new EventData("Partition 0 event"));
producer.send(batch);

code
### 使用分区键发送
java
CreateBatchOptions options = new CreateBatchOptions()
.setPartitionKey("customer-123");

EventDataBatch batch = producer.createBatch(options);
batch.tryAdd(new EventData("Customer event"));
producer.send(batch);

code
### 带有属性的事件
java
EventData event = new EventData("Order created");
event.getProperties().put("orderId", "ORD-123");
event.getProperties().put("customerId", "CUST-456");
event.getProperties().put("priority", 1);

producer.send(Collections.singletonList(event));

code
### 接收事件(简单模式)
java
import com.azure.messaging.eventhubs.models.EventPosition;
import com.azure.messaging.eventhubs.models.PartitionEvent;

// 从特定分区接收
Iterable<PartitionEvent> events = consumer.receiveFromPartition(
"0", // partitionId
10, // maxEvents
EventPosition.earliest(), // startingPosition
Duration.ofSeconds(30) // timeout
);

for (PartitionEvent partitionEvent : events) {
EventData event = partitionEvent.getData();
System.out.println("Body: " + event.getBodyAsString());
System.out.println("Sequence: " + event.getSequenceNumber());
System.out.println("Offset: " + event.getOffset());
}

code
### EventProcessorClient(生产环境)
java
import com.azure.messaging.eventhubs.EventProcessorClient;
import com.azure.messaging.eventhubs.EventProcessorClientBuilder;
import com.azure.messaging.eventhubs.checkpointstore.blob.BlobCheckpointStore;
import com.azure.storage.blob.BlobContainerAsyncClient;
import com.azure.storage.blob.BlobContainerClientBuilder;

// 创建检查点存储 (checkpoint store)
BlobContainerAsyncClient blobClient = new BlobContainerClientBuilder()
.connectionString("<storage-connection-string>")
.containerName("checkpoints")
.buildAsyncClient();

// 创建处理器
EventProcessorClient processor = new EventProcessorClientBuilder()
.connectionString("<eventhub-connection-string>", "<event-hub-name>")
.consumerGroup("$Default")
.checkpointStore(new BlobCheckpointStore(blobClient))
.processEvent(eventContext -> {
EventData event = eventContext.getEventData();
System.out.println("Processing: " + event.getBodyAsString());

// 处理后更新检查点
eventContext.updateCheckpoint();
})
.processError(errorContext -> {
System.err.println("Error: " + errorContext.getThrowable().getMessage());
System.err.println("Partition: " + errorContext.getPartitionContext().getPartitionId());
})
.buildEventProcessorClient();

// 开始处理
processor.start();

// 保持运行...
Thread.sleep(Duration.ofMinutes(5).toMillis());

// 优雅停止
processor.stop();

code
### 批量处理
java
EventProcessorClient processor = new EventProcessorClientBuilder()
.connectionString("<connection-string>", "<event-hub-name>")
.consumerGroup("$Default")
.checkpointStore(new BlobCheckpointStore(blobClient))
.processEventBatch(eventBatchContext -> {
List<EventData> events = eventBatchContext.getEvents();
System.out.printf("Received %d events%n", events.size());

for (EventData event : events) {
// 处理每个事件
System.out.println(event.getBodyAsStr
code
ing());
}

// 批处理后更新检查点
eventBatchContext.updateCheckpoint();
}, 50) // maxBatchSize
.processError(errorContext -> {
System.err.println("Error: " + errorContext.getThrowable());
})
.buildEventProcessorClient();

异步接收

java
asyncConsumer.receiveFromPartition("0", EventPosition.latest())
    .subscribe(
        partitionEvent -> {
            EventData event = partitionEvent.getData();
            System.out.println("Received: " + event.getBodyAsString());
        },
        error -> System.err.println("Error: " + error),
        () -> System.out.println("Complete")
    );

获取 Event Hub 属性

java
// 获取 Hub 信息
EventHubProperties hubProps = producer.getEventHubProperties();
System.out.println("Hub: " + hubProps.getName());
System.out.println("Partitions: " + hubProps.getPartitionIds());

// 获取分区信息
PartitionProperties partitionProps = producer.getPartitionProperties("0");
System.out.println("Begin sequence: " + partitionProps.getBeginningSequenceNumber());
System.out.println("Last sequence: " + partitionProps.getLastEnqueuedSequenceNumber());
System.out.println("Last offset: " + partitionProps.getLastEnqueuedOffset());

事件位置 (Event Positions)

java
// 从开头开始
EventPosition.earliest()

// 从末尾开始(仅接收新事件)
EventPosition.latest()

// 从特定偏移量开始
EventPosition.fromOffset(12345L)

// 从特定序列号开始
EventPosition.fromSequenceNumber(100L)

// 从特定时间开始
EventPosition.fromEnqueuedTime(Instant.now().minus(Duration.ofHours(1)))

错误处理

java
import com.azure.messaging.eventhubs.models.ErrorContext;

.processError(errorContext -> {
Throwable error = errorContext.getThrowable();
String partitionId = errorContext.getPartitionContext().getPartitionId();

if (error instanceof AmqpException) {
AmqpException amqpError = (AmqpException) error;
if (amqpError.isTransient()) {
System.out.println("Transient error, will retry");
}
}

System.err.printf("Error on partition %s: %s%n", partitionId, error.getMessage());
})

资源清理

java
// 务必关闭客户端
try {
    producer.send(batch);
} finally {
    producer.close();
}

// 或使用 try-with-resources
try (EventHubProducerClient producer = new EventHubClientBuilder()
.connectionString(connectionString, eventHubName)
.buildProducerClient()) {
producer.send(events);
}

环境变量

bash
EVENT_HUBS_CONNECTION_STRING=Endpoint=sb://<namespace>.servicebus.windows.net/;SharedAccessKeyName=...
EVENT_HUBS_NAME=<event-hub-name>
STORAGE_CONNECTION_STRING=<for-checkpointing>

最佳实践

1. 使用 EventProcessorClient:生产环境建议使用,可提供负载均衡和检查点管理。
2. 批量发送事件:使用 EventDataBatch 以提高发送效率。
3. 分区键 (Partition Keys):使用分区键以保证分区内的顺序性。
4. 设置检查点:处理完成后更新检查点,避免重复处理。
5. 错误处理:通过重试机制处理瞬时错误。
6. 关闭客户端:完成后务必关闭生产者/消费者。

触发词

  • "Event Hubs Java"
  • "event streaming Azure"
  • "real-time data ingestion"
  • "EventProcessorClient"
  • "event hub producer consumer"
  • "partition processing"

适用场景

本技能适用于执行概览中所描述的工作流或操作。

局限性

  • 仅在任务明确符合上述范围时使用此技能。
  • 不要将输出结果视为特定环境验证、测试或专家评审的替代方案。
  • 如果缺少必要的输入、权限、安全边界或验收标准,请停止操作并请求澄清。