簡體   English   中英

如何找出memory(OOM)容器出問題的根本原因

[英]How to find out the root cause of container going out of memory (OOM)

我在我的 Micronaut 應用程序中運行一個批處理,它從數據庫中獲取 500 000 條記錄,挑選 100 個項目的批次,並在進行處理后(包括對該批次的 api 調用)再次將數據插入另一個 sqlite 表中。

     try (Connection connection = dataSource.getConnection();
            PreparedStatement statement = connection.prepareStatement("SELECT id,item_id,type,operation FROM table WHERE serial_id = ? AND type = ? AND fail_reason IS NULL"  )) {
            statement.setString(1, serialId);
            statement.setString(2, type.name());
            ResultSet resultSet = statement.executeQuery();
            List<ItemEntity> itemEntities = new ArrayList<>(batchSize);
            int i = 0;
            while (resultSet.next()) {
                itemEntities.add(ItemEntity.builder()
                        .id(resultSet.getString("id"))
                        .itemId(resultSet.getString("item_id"))
                        .type(ItemType.valueOf(resultSet.getString("type")))
                        .operation(Operation.valueOf(resultSet.getString("operation")))
                        .build());

                i++;

                if(i == batchSize) {
                    i = 0;
                    consumer.accept(itemEntities);
                    itemEntities.clear();
                }
            }

            if(!itemEntities.isEmpty())
                consumer.accept(itemEntities);
        } catch (Exception ex) {
            log.error("error", ex);
            throw new RuntimeException("error", ex);
        }
    }

每當此批次運行時,容器都會以退出代碼 137 重新啟動。我已經檢查了以下 jvm arguments

-XX:+HeapDumpOnOutOfMemoryError -XX:+ExitOnOutOfMemoryError -XX:HeapDumpPath=/var/data/heapdump.hprof

因為在容器重啟后我沒有得到任何堆轉儲文件所以我假設不是 Micronaut 應用程序導致容器出現 go OOM。

容器 memory 限制為 512m。

我可以嘗試調試此問題的所有內容是什么?

我發現一種可以有效調試問題的技術,我可以稱之為“隔離和剝離”。 這背后的想法是將這個問題的所有因素隔離到單獨的關注點中,並不斷迭代以找出哪個因素對導致問題的影響最大。 這是一個問題識別練習。 列出一些候選問題后,您就可以將注意力轉移到解決方案的思維方式上。

對於您的特定問題,我可以總結一下發生的事情(如果我錯了請糾正我)

  • 使用數據庫連接准備一條語句,然后為其分配一些變量,然后執行。
  • 得到結果集。 使用結果集,填充項目實體並將它們批量發送給消費者(大約 100 個)。 然后重復

從這里我可以提取一個問題列表。

    1. sql 查詢數據庫,期望結果為50k
    1. 將一個 resultSet 行處理成一個項目實體
    1. 將一個項目實體傳遞給消費者。

所以隔離這些問題來調試它。 同時注釋掉或刪除代碼的其他部分。

對於第 1 項,查看結果集 50k 是否導致 OOM 錯誤。 將查詢調整為最大 10k、20k、30k。 或者從1k開始; 查看 100 個結果是否有效。 稍微更改一下查詢,看看是否可以一點一點地添加它,看看它何時中斷。

對於第 2 項,是在 100 個問題的循環中構建項目。 你能把它一直建到 500k 嗎? 嘗試不同的量。

對於第 3 項,您能否在沒有任何問題的情況下向消費者處理一項。 您能否將剛剛手工創建的模擬項目發送給它並處理一批 100 個。然后將其提高到一批 1000 或 5000 個。如果成功輪換,看看它在什么時候失敗了。

另一個角度是搞亂 memory 的限制。 一旦您完成上述工作的某些子集,我會在之后執行此操作,並保持遞增直到您看到它中斷。

另一種方法是查看您是否可以使用 Micronaut 存儲庫和實體來解決相同的問題。 兩者都在較小的上下文中,如 100 個實體,然后嘗試增加到 50k。 我不認為我在上面看到的是 micronaut 問題,但試驗將有助於通過證據排除它

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM