[英]How do I use the requestShutdown and shutdown to do graceful shutdown in the case of KCL Java library for AWS Kinesis
我正在嘗試使用Java中的KCL庫的新功能來為AWS Kinesis通過注冊shutdown hook來優雅地關閉以停止所有記錄處理器,然后優雅地停止工作。 新庫提供了一個新的接口,需要實現記錄處理器。 但它如何被調用?
嘗試首先調用worker.requestShutdown()然后調用worker.shutdown()並且它可以正常工作。 但它是否有任何預期的使用方式。 那么使用它們有什么用處及其好處?
正如您可能知道的那樣,當您創建一個Worker
,它
1)在dynamodb中創建消費者偏移表
2)按照配置的時間間隔創建租約, 安排租賃接受者和租賃續訂者
如果您有兩個分區,則同一個dynamodb表中將有兩條記錄,這意味着分區需要租約。
例如。
{
"checkpoint": "TRIM_HORIZON",
"checkpointSubSequenceNumber": 0,
"leaseCounter": 38,
"leaseKey": "shardId-000000000000",
"leaseOwner": "ComponentTest_Consumer_With_Two_Partitions_Consumer_192.168.1.83",
"ownerSwitchesSinceCheckpoint": 0
}
{
"checkpoint": "49570828493343584144205257440727957974505808096533676050",
"checkpointSubSequenceNumber": 0,
"leaseCounter": 40,
"leaseKey": "shardId-000000000001",
"leaseOwner": "ComponentTest_Consumer_With_Two_Partitions_Consumer_192.168.1.83",
"ownerSwitchesSinceCheckpoint": 0
}
leaseCoordinatorThreadPool
)負責接收和續訂租約的時間表 3)然后,對於流中的每個分區, Worker
創建一個內部PartitionConsumer ,它實際上獲取事件 ,並調度到RecordProcessor#processRecords
。 請參閱ProcessTask #call
4)關於你的問題,你必須將IRecordProcessorFactory
impl注冊到worker
,這將為每個PartitionConsumer
提供一個ProcessorFactoryImpl
。
例如。 看這里的例子,這可能會有所幫助
KinesisClientLibConfiguration streamConfig = new KinesisClientLibConfiguration(
"consumerName", "streamName", getAuthProfileCredentials(), "consumerName-" + "consumerInstanceId")
.withKinesisClientConfig(getHttpConfiguration())
.withInitialPositionInStream(InitialPositionInStream.TRIM_HORIZON); // "TRIM_HORIZON" = from the tip of the stream
Worker consumerWorker = new Worker.Builder()
.recordProcessorFactory(new DavidsEventProcessorFactory())
.config(streamConfig)
.dynamoDBClient(new DynamoDB(new AmazonDynamoDBClient(getAuthProfileCredentials(), getHttpConfiguration())))
.build();
public class DavidsEventProcessorFactory implements IRecordProcessorFactory {
private Logger logger = LogManager.getLogger(DavidsEventProcessorFactory.class);
@Override
public IRecordProcessor createProcessor() {
logger.info("Creating an EventProcessor.");
return new DavidsEventPartitionProcessor();
}
}
class DavidsEventPartitionProcessor implements IRecordProcessor {
private Logger logger = LogManager.getLogger(DavidsEventPartitionProcessor.class);
//TODO add consumername ?
private String partitionId;
private ShutdownReason RE_PARTITIONING = ShutdownReason.TERMINATE;
public KinesisEventPartitionProcessor() {
}
@Override
public void initialize(InitializationInput initializationInput) {
this.partitionId = initializationInput.getShardId();
logger.info("Initialised partition {} for streaming.", partitionId);
}
@Override
public void processRecords(ProcessRecordsInput recordsInput) {
recordsInput.getRecords().forEach(nativeEvent -> {
String eventPayload = new String(nativeEvent.getData().array());
logger.info("Processing an event {} : {}" , nativeEvent.getSequenceNumber(), eventPayload);
//update offset after configured amount of retries
try {
recordsInput.getCheckpointer().checkpoint();
logger.debug("Persisted the consumer offset to {} for partition {}",
nativeEvent.getSequenceNumber(), partitionId);
} catch (InvalidStateException e) {
logger.error("Cannot update consumer offset to the DynamoDB table.", e);
e.printStackTrace();
} catch (ShutdownException e) {
logger.error("Consumer Shutting down", e);
e.printStackTrace();
}
});
}
@Override
public void shutdown(ShutdownInput shutdownReason) {
logger.debug("Shutting down event processor for {}", partitionId);
if(shutdownReason.getShutdownReason() == RE_PARTITIONING) {
try {
shutdownReason.getCheckpointer().checkpoint();
} catch (InvalidStateException e) {
logger.error("Cannot update consumer offset to the DynamoDB table.", e);
e.printStackTrace();
} catch (ShutdownException e) {
logger.error("Consumer Shutting down", e);
e.printStackTrace();
}
}
}
}
//然后開始消費者
consumerWorker.run();
現在,當你想要停止你的Consumer實例( Worker
)時,你不需要對每個PartitionConsumer
做太多的處理,一旦你要求它關閉,這將由Worker
。
在shutdown
,它要求 leaseCoordinatorThreadPool
停止,它負責續訂和租賃,並等待終止。
另一方面, requestShutdown
取消租賃者, 並通知PartitionConsumer
關閉。
requestShutdown
更重要的是,如果你想在RecordProcessor
上得到通知,那么你也可以實現IShutdownNotificationAware
。 這種情況如果在RecordProcessor
處理事件但工作人員即將關閉的競爭條件下,您仍應該能夠提交偏移然后關閉。
requestShutdown
返回ShutdownFuture
,然后調用worker.shutdown
您必須在RecordProcessor
上實現以下方法才能在requestShutdown
上收到通知,
class DavidsEventPartitionProcessor implements IRecordProcessor, IShutdownNotificationAware {
private String partitionId;
// few implementations
@Override
public void shutdownRequested(IRecordProcessorCheckpointer checkpointer) {
logger.debug("Shutdown requested for {}", partitionId);
}
}
但是如果你在通知之前松開租約那么它可能不會被調用。
新庫提供了一個新的接口,需要實現記錄處理器。 但它如何被調用?
IRecordProcessorFactory
和IRecordProcessor
。 RecordProcessorFactory
到您的Worker
。 嘗試首先調用worker.requestShutdown()然后調用worker.shutdown()並且它可以正常工作。 但它是否有任何預期的使用方式?
您應該使用requestShutdown()
進行正常關閉 ,這將處理競爭條件。 它是在kinesis-client-1.7.1中引入的
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.