使用kafka-streams创建一个包含多个聚合的新KStream

时间:2017-09-01 03:24:11

标签: apache-kafka-streams

我发送的JSON消息包含有关Web服务请求和Kafka主题响应的详细信息。我希望在使用Kafka流到达Kafka时处理每条消息,并将结果作为持续更新的摘要(JSON消息)发送到客户端所连接的websocket。

然后,客户端将解析JSON并在网页上显示各种计数/摘要。

示例输入消息如下

{
  "reqrespid":"048df165-71c2-429c-9466-365ad057eacd",
  "reqDate":"30-Aug-2017",
  "dId":"B198693",
  "resp_UID":"N",
  "resp_errorcode":"T0001",
  "resp_errormsg":"Unable to retrieve id details. DB Procedure error",
  "timeTaken":11,
  "timeTakenStr":"[0 minutes], [0 seconds], [11 milli-seconds]",
  "invocation_result":"T"
}

{
  "reqrespid":"f449af2d-1f8e-46bd-bfda-1fe0feea7140",
  "reqDate":"30-Aug-2017",
  "dId":"G335887",
  "resp_UID":"Y",
  "resp_errorcode":"N/A",
  "resp_errormsg":"N/A",
  "timeTaken":23,
  "timeTakenStr":"[0 minutes], [0 seconds], [23 milli-seconds]",
  "invocation_result":"S"
}

{
  "reqrespid":"e71b802d-e78b-4dcd-b100-fb5f542ea2e2",
  "reqDate":"30-Aug-2017",
  "dId":"X205014",
  "resp_UID":"Y",
  "resp_errorcode":"N/A",
  "resp_errormsg":"N/A",
  "timeTaken":18,
  "timeTakenStr":"[0 minutes], [0 seconds], [18 milli-seconds]",
  "invocation_result":"S"
}

随着消息流进入Kafka,我希望能够即时计算

**

  • 请求总数,即所有
  • 的计数
  • invocation_result等于'S'
  • 的请求总数
  • invocation_result不等于'S'的请求总数
  • invocation_result等于'S'和UID的请求总数 等于'Y'
  • invocation_result等于'S'和UID的请求总数 等于'Y'
  • 最短时间,即min(timeTaken)
  • 最长时间,即max(timeTaken)
  • 平均所用时间,即平均(timeTaken)

**

并将它们写入KStream,新密钥设置为reqdate值,新值为包含计算值的JSON消息,如下所示,使用前面显示的3条消息

{
  "total_cnt":3, "num_succ":2, "num_fail":1, "num_succ_data":2, 
  "num_succ_nodata":0, "num_fail_biz":0, "num_fail_tech":1,
  "min_timeTaken":11, "max_timeTaken":23, "avg_timeTaken":17.3
}

Kafka溪流新手。我如何进行多次计数并将不同的列全部集中在一个或不同的步骤链中? Apache flink或calcite 会更合适吗,因为我对KTable的理解表明你只能拥有一个密钥,例如: 2017年8月30日然后是单个列值,例如计数 3 。我需要一个带有一个键和多个计数值的结果表结构。

非常感谢所有帮助。

1 个答案:

答案 0 :(得分:0)

您可以执行复杂的聚合步骤,一次计算所有这些步骤。我只想草写这个想法:

class AggResult {
    long total_cnt = 0;
    long num_succ = 0;
    // and many more
}

stream.groupBy(...).aggregate(
    new Initializer<AggResult>() {
        public AggResult apply() {
            return new AggResult();
        }
    },
    new Aggregator<KeyType, JSON, AggResult> {
        AggResult apply(KeyType key, JSON value, AggResult aggregate) {
            ++aggregate.total_cnt;
            if (value.get("success").equals("true")) {
                ++aggregate.num_succ;
            }
            // add more conditions to get all the other aggregate results
            return aggregate;
        }
    },
    // other parameters omitted for brevity
)
.to("result-topic");