首页 > 解决方案 > Kafka Streams 应用程序无法以 Cloud Foundry 中的“what():资源暂时不可用”开始

问题描述

亲爱的 Stackoverflow 人,

我在使用 Kafka Streams binder 的 Spring Cloud Stream 应用程序时遇到问题。只有在我们自己的 Pivotal Cloud Foundry (CF) 环境中才会出现此问题。在这一点上我有点碰壁了,所以我求助于你和你的智慧!

当应用程序启动时,我看到以下错误

<snip>
2019-08-07T15:17:58.36-0700 [APP/PROC/WEB/0]OUT     current active tasks: [0_3, 1_3, 2_3, 3_3, 4_3, 0_7, 1_7, 5_3, 2_7, 3_7, 4_7, 0_11, 1_11, 5_7, 2_11, 3_11, 4_11, 0_15, 1_15, 5_11, 2_15, 3_15, 4_15, 0_19, 1_19, 5_15, 2_19, 3_19, 4_19, 0_23, 1_23, 5_19, 2_23, 3_23, 4_23, 5_23]
2019-08-07T15:17:58.36-0700 [APP/PROC/WEB/0]OUT     current standby tasks: []
2019-08-07T15:17:58.36-0700 [APP/PROC/WEB/0]OUT     previous active tasks: []
2019-08-07T15:18:02.67-0700 [API/0]      OUT Updated app with guid 2db4a719-53ee-4d4a-9573-fe958fae1b4f ({"state"=>"STOPPED"})
2019-08-07T15:18:02.64-0700 [APP/PROC/WEB/0]ERR terminate called after throwing an instance of 'std::system_error'
2019-08-07T15:18:02.64-0700 [APP/PROC/WEB/0]ERR   what():  Resource temporarily unavailable
2019-08-07T15:18:02.67-0700 [CELL/0]     OUT Stopping instance 516eca4f-ea73-4684-7e48-e43c
2019-08-07T15:18:02.67-0700 [CELL/SSHD/0]OUT Exit status 0
2019-08-07T15:18:02.71-0700 [APP/PROC/WEB/0]OUT Exit status 134
2019-08-07T15:18:02.71-0700 [CELL/0]     OUT Destroying container
2019-08-07T15:18:03.62-0700 [CELL/0]     OUT Successfully destroyed container

这里的关键是与 what(): Resource temporarily unavailable

该错误与分区数有关。如果我将分区数设置为 12 或更少,则一切正常。如果我将其加倍,则该过程无法以此错误开始。

这不会发生在我的本地 Windows 开发机器上。当我将此应用程序包装在 docker 映像中并运行时,它也不会在我的本地 docker 环境中发生。我可以拍摄相同的图像并将其推送到 CF 或将应用程序作为 java 应用程序推送,我收到此错误。

以下是有关 kafka 流应用程序的一些信息。我们有一个带有多个分区的输入主题。主题是 debezium 连接器的输出,基本上它是一堆数据库表的更改日志。拓扑不是超级复杂,但也不是微不足道的。它的工作是将表更新信息聚合回我们的聚合中。我们最终在拓扑中有 17 个本地商店。我强烈怀疑这个问题与rocksdb和应用程序所在的CF容器可用的资源有关。但我一点也不知道“暂时不可用”的资源是什么。

正如我所提到的,我尝试将其部署为具有各种 jdk8 jvm、不同基础映像 centos、debian 的 docker 容器,我尝试了各种不同的 CF java buildbacks,我尝试限制与最大容器内存大小相关的 java 堆(认为它可能有与本机内存分配有关)无济于事。

我还要求我们的操作人员对容器设置一些限制,并将打开文件限制从最初的 16k 更改为现在的 500k+。我看到了一些与文件锁定相关的错误,如下所示,但在此更改后它们消失了。

2019-08-01T15:46:23.69-0700 [APP/PROC/WEB/0]ERR Caused by: org.rocksdb.RocksDBException: lock : /home/vcap/tmp/kafka-streams/cms-cdc/0_7/rocksdb/input/LOCK: No locks available
2019-08-01T15:46:23.69-0700 [APP/PROC/WEB/0]ERR   at org.rocksdb.RocksDB.open(Native Method)

但是what(): Resource temporarily unavailable,分区数较多的错误仍然存​​在。

容器上的 ulimit -a 看起来像这样

~$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 1007531
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 524288
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) unlimited
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

我真的需要了解这个错误的根源是什么。在这种情况下很难计划不知道我们在这里达到什么限制。

希望听到你的想法。谢谢!

编辑

是否有某种方法可以从 Rocksdb 库中获取更详细的错误消息,或者可以构建它以便输出更多信息?

编辑 2

我还尝试使用自定义rocksdb内存设置org.apache.kafka.streams.state.RocksDBConfigSetter

默认值在org.apache.kafka.streams.state.internals.RocksDBStore#openDB(org.apache.kafka.streams.processor.ProcessorContext)

首先,我确保 Java 堆设置远低于容器进程大小限制,并且通过设置没有给内存计算器留下任何内容 JAVA_OPTS: -XX:MaxDirectMemorySize=100m -XX:ReservedCodeCacheSize=240m -XX:MaxMetaspaceSize=145m -Xmx1000m

有了这个我试过:

1.降低写缓冲区大小 org.rocksdb.Options#setWriteBufferSize(long) org.rocksdb.Options#setMaxWriteBufferNumber(int)

2.将max_open_files设置为容器限制的一半(所有db实例的总数) org.rocksdb.Options#setMaxOpenFiles(int)

3.我尝试完全关闭块缓存 org.rocksdb.BlockBasedTableConfig#setNoBlockCache

4.我还尝试在重新启用块缓存后设置 cache_index_and_filter_blocks = true https://github.com/facebook/rocksdb/wiki/Block-Cache#caching-index-and-filter-blocks

一切都无济于事。当我在输入主题上设置更高数量的分区(24)时,上述问题仍然存在。现在我已经RocksDBConfigSetter登录了,我可以看到错误发生在配置rocksdb时。

编辑 3

我还没有深究这件事。我在https://www.facebook.com/groups/rocksdb.dev上提出了这个问题,并被建议使用 strace 或类似方法跟踪系统调用,但我无法在我们的环境中获得执行此操作所需的权限。

它已经消耗了太多时间,以至于我现在不得不接受一种解决方法。我最终做的是将拓扑重构为

1) 最小化具体化 ktable 的数量(以及生成的 RocksDB 实例的数量)和

2)分解多个进程之间的拓扑。

这使我可以使用弹簧配置文件在单独的部署中打开和关闭拓扑部分,并且目前给了我一些有限的前进方向。

标签: apache-kafka-streamsspring-cloud-streamcloud-foundryrocksdb

解决方案


推荐阅读