发送到任务之前,请在KafkaConnect中修改连接器配置

时间:2019-01-25 09:17:42

标签: apache-kafka apache-kafka-connect

我正在Kafka Connect中编写一个SinkConnector并遇到问题。该连接器具有这样的配置:

{
    "connector.class" : "a.b.ExampleFileSinkConnector",
    "tasks.max" : '1',
    "topics" : "mytopic",
    "maxFileSize" : "50"
}

我这样定义连接器的配置:

@Override public ConfigDef config()
  {
    ConfigDef result = new ConfigDef();
    result.define("maxFileSize", Type.STRING, "10", Importance.HIGH, "size of file");
    return result;
  }

在连接器中,我这样启动任务:

@Override public List<Map<String, String>> taskConfigs(int maxTasks) {
  List<Map<String, String>> result = new ArrayList<Map<String,String>>();
  for (int i = 0; i < maxTasks; i++) {
    Map<String, String> taskConfig = new HashMap<>();
    taskConfig.put("connectorName",   connectorName);
    taskConfig.put("taskNumber",      Integer.toString(i));
    taskConfig.put("maxFileSize",     maxFileSize);
    result.add(taskConfig);
  }
  return result;
}

一切顺利。

但是,在启动Task时(在taskConfigs()中),如果我添加了它:

taskConfig.put("epoch", "123");

这破坏了整个基础架构:所有连接器都以无休止的循环停止和重新启动。

连接日志文件中没有任何异常或错误可以帮助您。

使其生效的唯一方法是在连接器配置中添加“ epoch”,我不想这样做,因为它是连接器必须发送给任务的内部参数。不应将其暴露给连接器的用户。

我注意到的另一点是,除了将其设置为默认值之外,无法更新任何连接器配置参数的值。更改参数并将其发送到任务会产生相同的行为。

在此问题上的任何帮助,我将非常感谢。

编辑:这是SinkTask :: start()

的代码
@Override public void start(Map<String, String> taskConfig) {
  try {
    connectorName   = taskConfig.get("connectorName");
    log.info("{} -- Task.start()", connectorName);
    fileNamePattern = taskConfig.get("fileNamePattern");
    rootDir         = taskConfig.get("rootDir");
    fileExtension   = taskConfig.get("fileExtension");
    maxFileSize     = SimpleFileSinkConnector.parseIntegerConfig(taskConfig.get("maxFileSize"));
    maxTimeMinutes  = SimpleFileSinkConnector.parseIntegerConfig(taskConfig.get("maxTimeMinutes"));
    maxNumRecords   = SimpleFileSinkConnector.parseIntegerConfig(taskConfig.get("maxNumRecords"));
    taskNumber      = SimpleFileSinkConnector.parseIntegerConfig(taskConfig.get("taskNumber"));
    epochStart      = SimpleFileSinkConnector.parseLongConfig(taskConfig.get("epochStart"));
    log.info("{} -- fileNamePattern: {}, rootDir: {}, fileExtension: {}, maxFileSize: {}, maxTimeMinutes: {}, maxNumRecords: {}, taskNumber: {}, epochStart : {}",
            connectorName, fileNamePattern, rootDir, fileExtension, maxFileSize, maxTimeMinutes, maxNumRecords, taskNumber, epochStart);
    if (taskNumber == 0) {
      checkTempFilesForPromotion();
    }
    computeInitialFilename();
    log.info("{} -- Task.start() END", connectorName);
  } catch (Exception e) {
    log.info("{} -- Task.start() EXCEPTION : {}", connectorName, e.getLocalizedMessage());
  }
}

1 个答案:

答案 0 :(得分:0)

我们找到了问题的根本原因。 Kafka Connect Framework实际上是按设计方式运行的-问题与我们尝试使用taskConfigs配置框架的方式有关。

问题

在我们的设计中,FileSinkConnector在其start()生命周期方法中设置了一个纪元,并且通过taskConfigs()生命周期方法将该纪元传递给其任务。因此,每次连接器的start()生命周期方法运行时,都会为任务生成不同的配置-这就是问题所在。

每次都必须生成不同的配置。事实证明,Connect Framework将检测配置差异,并在检测到时重新启动/重新平衡-停止并重新启动连接器/任务。重新启动将调用连接器的stop()和start()方法……这(当然)将产生另一个配置更改(由于新时期),并且恶性循环已经开始!

这是一个有趣且出乎意料的问题……由于Connect中的行为,我们对此并不感激。这是我们第一次尝试生成任务配置,这不是连接器配置的简单功能。

请注意,Connect中的这种行为是有意的,它解决了动态更改配置的实际问题-例如JDBC Sink Connector,当它检测到要接收的新数据库表时自发更新其配置。

感谢那些帮助了我们的人!