如何使用ksql在Kafka的时间窗口上的聚合之上执行聚合

时间:2020-11-01 17:36:35

标签: apache-kafka apache-kafka-streams ksqldb

我有一堆防火墙数据。 我想:

A)对每小时每个IP的字节求和,然后

B)计算该小时内所有IP的最小和最大总和

我已经能够在Kafka中做A,但是我不知道该怎么做B。我一直在仔细研究文档,觉得自己快要结束了,但是我似乎总是只发现其中一部分解决方案。

我的firewall_stream运行得很好。

client.create_stream(
    table_name='firewall_stream',
    columns_type=['src_ip VARCHAR',
                  'dst_ip VARCHAR',
                  'src_port INTEGER',
                  'dst_port INTEGER',
                  'protocol VARCHAR',
                  'action VARCHAR',
                  'timestamp VARCHAR',
                  'bytes BIGINT',
    ],
    topic='firewall',
    value_format='JSON'
)

我创建了具有1小时滚动窗口的物化视图bytes_sent,总和(字节),并按IP地址分组。这很棒!。

client.ksql('''
CREATE TABLE bytes_sent as
  SELECT src_ip, sum(bytes) as bytes_sum
  FROM firewall_stream
  GROUP BY src_ip
  EMIT CHANGES
''')

这就是我被困住的地方。首先,我尝试仅根据bytes_sent创建另一个实例化视图,该视图通过windowstart进行了max(bytes_sum)组,但出现一个错误,您无法在窗口化实例化视图上进行聚合。

因此,我删除了时间窗口(如图所示,将其重新显示在第二个实例化视图中),但随后我的“ group by”子句没有任何字段。在Postgres中,我可以在没有group by的情况下执行max操作,它将在整个表中进行计算,但Kafka始终要求使用group by。现在我不确定该使用什么。

似乎无法使用文档中的窗口表进行联接(尽管我还没有尝试过,可能会有误解)。

我唯一的猜测是从该物化视图bytes_sent创建另一个流,并查看changelog事件,然后以某种方式将它们转换为给定时间范围内所有IP的最大字节。

任何有关如何解决此问题的反馈将不胜感激!

1 个答案:

答案 0 :(得分:0)

简而言之,您目前无法做到这一点。

我的快速解决方案基本上是:

  • 创建一个主题作为第一次聚合的输出
  • 在该新主题上创建一个新流,但在 ksql 之外
  • 在第二个上运行新的 ksql 聚合

也就是说,在这种设置中可能会出错很多。在这一点上,我们只是针对这个特定用例排除了 ksql,并且可能会直接使用流。