如何设置风暴工作者的JVM最大堆大小?

时间:2016-03-08 09:53:54

标签: java jvm apache-kafka apache-storm

我是Storm编程的新手,我有一份工作要对自定义分组方法进行测试,看看它是否更好。

所以我必须在几种不同的条件下测量风暴的吞吐量,例如不同的工人数量,不同的工人记忆......等等

使用conf.setNumWorkers();设置工作人员编号很容易,但我发现很难设置每个工作人员的最大堆大小。

我尝试编辑storm.yaml并添加了

worker.childopts: "-Xmn128m-Xms128m-Xmx128m"

conf.put(Config.WORKER_CHILDOPTS, "-Xmn128m -Xms128m -Xmx128m");

添加到我的代码中。

但是当我在我的工作节点上使用jmap -heap [pid]时,我发现最大堆大小仍然是768m,这是默认的最大堆大小。

如何实现此目的以限制JVM的最大内存使用?

顺便说一句,我正在使用kafkaspout向暴风雨发送消息,欢迎对我的测试工作提出任何建议。

5 个答案:

答案 0 :(得分:2)

尝试编辑storm / default.yaml文件。查找工作器设置,您将在那里找到设置堆内存的条目。它默认应该是这样的!

worker.heap.memory.mb: 768

在同一个文件中,您还可以找到以下设置,您可以根据需要更改值。

topology.component.resources.onheap.memory.mb: 128.0
topology.component.resources.offheap.memory.mb: 0.0
topology.component.cpu.pcore.percent: 10.0
topology.worker.max.heap.size.mb: 768.0

希望有所帮助!

答案 1 :(得分:2)

如果你的Storm版本是<1.0.0,你必须在storm.yaml中设置worker.childopts,然后重新启动你的主管。此参数不会作为拓扑特定选项from what I've gleaned引入,因此您所做的拓扑配置更改不会影响结果。

对于Storm版本&gt; = 1.0.0,您可以参考ssadaqat's answer,但不是编辑defaults.yaml(这是源代码的一部分),您再次需要将此值插入到storm中。 YAML。

答案 2 :(得分:2)

虽然ssadaquat的答案是正确的,并且您可以在风暴的yaml文件中设置工作程序内存,但我已经能够以编程方式成功地执行此操作:

Config stormConfig = new Config();
int fourGB = 4 * 1024;
stormConfig.put(Config.TOPOLOGY_WORKER_MAX_HEAP_SIZE_MB, fourGB);  

如果您不想更改多台服务器中的yaml文件,或者您根本不想更改yaml文件,那么这样做会特别有用。

有很多答案说你必须设置childopts以增加记忆力,但这对我没有用。事实上,我注意到在设置topology_worker_max_heap_size_mb后,childopts值会自动增加。还要尽量确保服务器上有enough of swap memory,尤其是在处理大量数据时。

答案 3 :(得分:1)

您可以通过以下步骤更改工作人员的最大堆大小:

1:添加&#34; worker.heap.memory.mb:2048&#34;进入nimbus节点的conf / storm.yaml文件;

2:重启nimbus和主管

工人&#39;堆大小将更改为2GB

答案 4 :(得分:0)

我无法找出设置JVM最大堆大小的正确方法,但我使用了另一种方法作为解决方法。

注意:我目前没有手头的源代码,所以下面的代码只是为了演示这个想法并完全未经测试。

该方法是利用Storm中重新传输失败元组的机制。

如果您正在使用某种类型的现有鲸鱼喷水,例如KafkaSpout或其他任何事情,那么您不必担心重新传输失败的元组,默认情况下它都会被处理掉实现。

但是,如果您要实施自己的鲸鱼喷水,则必须自行完成。我相信,如果您尝试实施鲸鱼喷水,那么您必须知道void ack(Object msgId)void fail(Object msgId)等等,并且很容易实现重新传输机制。

我们的WorkerBolt看起来像这样,假设它是一个字数螺栓。

class WorkerBolt implements IRichBolt{
    ...
    private HashMap<String, int> counts = new HashMap<>();
    private int wordStoredCount = 0;
    private final int COUNT_LIMIT = 500000;  // Here's our limit
    ...
    void execute(Tuple tuple){
        if(wordStoreCount >= COUNT_LIMIT){
            tuple.fail();
        }

        // do our counting stuff

        wordStoredCount++;

        // send the tuple downstream to aggregate/process/etc. if needed
    }
    ...

它不是很准确,因为每个单词可能有不同的长度或大小,您可以使用MEMORY_COUNT memoryStoredCount并将每个单词的内存使用加到{{1}更准确。

采用这种方法可以使系统更具可控性,因为如果我们设置最大堆大小并且JVM达到约束,它将简单地抛出OutOfMemoryException并关闭系统,这可能不是我们想要的。