Flink - 在丰富事件

时间:2018-02-17 12:58:42

标签: apache-flink

我目前正在编写流媒体应用程序,其中:

  • 作为输入,我从kafka主题收到一些警报(1个警报链接到1个资源,例如1个警报将链接到my-router-1或my-switch-1或my-VM -1或my-VM-2或......)
  • 然后,我需要对外部系统进行查询,以便通过链接到与警报相关联的资源的一些其他信息来丰富警报

查询外部系统时:

  • 我不想每个警报执行1次查询,每个资源甚至不需要1次查询
  • 我更愿意进行群组查询(针对多个资源链接的多个警报进行1次查询)
  • 我的想法是有一个像n缓冲区(n是一个小数字代表我将并行执行的查询的nb),然后在给定的时间段内(让我们说100毫秒),把所有在其中一个缓冲区内的警报和100毫秒结束时,并行执行我的n个查询(1个查询负责丰富属于多个资源的多个警报)。

在Spark中,我会通过mapPartitions做一些事情(如果我有n分区,那么我将只对我的外部系统进行n次查询,并且每个查询将针对微观期间收到的所有警报批处理一个分区)。

现在,我正在寻找Flink,我还没有真正找到在请求外部系统时进行此类分组的最佳方式。

在查看此类用例时,特别是在asyncio(https://ci.apache.org/projects/flink/flink-docs-release-1.4/dev/stream/operators/asyncio.html)时,似乎每个键处理1个查询。

例如,我可以很容易地:

  • 将资源ID定义为密钥
  • 定义100毫秒的处理时间窗口
  • 然后对外部系统进行查询(通过asyncio功能同步或更好地异步)

但是通过这样做,我将为每个资源执行1次查询(可能是针对多个警报但链接到相同的密钥,即相同的资源)。 这不是我想要做的,因为它会导致对外部系统的过多查询。

然后,我研究了为我的请求定义一种技术密钥的选项(类似于我想要执行的查询的资源ID%nb的hashCode)。

所以,如果我想并行执行最多4个查询,那么我的密钥将类似于" resourceId.hashCode%4"。

我当时认为没关系,但是当我在运行我的工作时更深入地查看某些指标时,我发现我的查询并没有很好地分发给我的4个操作符实例(其中只有2个正在执行某些操作)。 它用于将键分配给给定运算符实例的机制:

    public static int assignKeyToParallelOperator(Object key, int maxParallelism, int parallelism) {
    return computeOperatorIndexForKeyGroup(maxParallelism, parallelism, assignToKeyGroup(key, maxParallelism));
}

(在我的例子中,并行度为4,maxParallelism 128和我的键值在[0,4 []范围内(在这样的上下文中,我的2个键转到运算符实例3,2转到运算符实例4)(运算符实例1和2将无关)。 我以为key = 0将转到运算符0,键1转到运算符1,键2转到运算符2,键3转到运算符3,但事实并非如此。

那么你知道在查询外部系统时进行这种分组的最佳方法是什么?

即每个运营商实例对所有警报进行1次查询"已收到"在过去的100ms内通过此运算符实例。

1 个答案:

答案 0 :(得分:0)

您可以将聚合器函数放在异步函数的上游,其中该函数(使用定时窗口)输出<resource id><list of alerts to query>的记录。您可以在聚合器之前通过<resource id>键入流,然后应该将其流水线化为异步功能。