为什么我的Apache Storm 2.0拓扑在30秒后重新启动?

时间:2019-10-02 16:20:16

标签: java apache-storm

我尝试使用多个配置参数,甚至使用withLocalModeOverride也很顺利。我在这里想念什么?

这是一个示例应用程序,在30秒钟后,计数器被重置,一切重新开始。如果可以提供其他详细信息,请告诉我。

用法:

mvn package
java -jar target/Test-0.1.0.jar

src/main/java/Test.java

package storm.test;

import org.apache.storm.Config;
import org.apache.storm.LocalCluster;
import org.apache.storm.generated.StormTopology;
import org.apache.storm.spout.SpoutOutputCollector;
import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.TopologyBuilder;
import org.apache.storm.topology.base.BaseRichBolt;
import org.apache.storm.topology.base.BaseRichSpout;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Tuple;
import org.apache.storm.tuple.Values;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

class Test {
    private static class Spout extends BaseRichSpout {
        private SpoutOutputCollector spoutOutputCollector;
        private long n;

        @Override
        public void open(Map<String, Object> map, TopologyContext topologyContext, SpoutOutputCollector spoutOutputCollector) {
            this.spoutOutputCollector = spoutOutputCollector;
        }

        @Override
        public void nextTuple() {
            LOG.error("InfiniteSpout::nextTuple {}", n);
            spoutOutputCollector.emit(new Values(n++));
        }

        @Override
        public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
            outputFieldsDeclarer.declare(new Fields("x"));
        }
    }

    private static class Bolt extends BaseRichBolt {
        @Override
        public void prepare(Map<String, Object> map, TopologyContext topologyContext, OutputCollector outputCollector) {

        }

        @Override
        public void execute(Tuple tuple) {
            Long x = tuple.getLongByField("x");
            LOG.error("Bolt::execute {}", x);
        }

        @Override
        public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {

        }
    }

    private static final Logger LOG = LoggerFactory.getLogger(Test.class);

    public static void main(String[] args) {
        try {
            TopologyBuilder builder = new TopologyBuilder();
            builder.setSpout("spout", new Spout());
            builder.setBolt("bolt", new Bolt()).shuffleGrouping("spout");

            Config conf = new Config();
            LocalCluster cluster = new LocalCluster();
            StormTopology topology = builder.createTopology();
            cluster.submitTopology("test", conf, topology);
        } catch (Exception e) {
            LOG.error(e.getMessage());
        }
    }
}

pom.xml

<project>
    <modelVersion>4.0.0</modelVersion>

    <groupId>Test</groupId>
    <artifactId>Test</artifactId>
    <version>0.1.0</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.storm</groupId>
            <artifactId>storm-core</artifactId>
            <version>2.0.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.1.2</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>Test</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>3.1.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

1 个答案:

答案 0 :(得分:2)

这是实际的问题:

这是https://issues.apache.org/jira/browse/STORM-3501。此问题仅影响在LocalClusters中的运行,然后仅影响所生成的jar中没有资源目录。

您可以通过在jar中添加资源目录来解决此问题。使用pom,您想添加src / main / resources / resources目录。

关于运行单节点Storm的注意事项,我认为您应该认真考虑Storm是否是您的用例的正确选择。 Storm相当复杂,其中很大一部分复杂度是因为我们希望它能够在许多物理机之间分配计算。如果您要在一台计算机上运行所有计算,则可能无法真正通过使用Storm来获得太多收益,例如只是编写常规的Java应用程序,或使用Apache Camel之类的东西。

运行单节点时要考虑的其他事项:

  • 风暴是快速失败的,因此,如果您遇到任何错误,整个工作人员将崩溃。在单台计算机上运行时,您可能会占用很大一部分集群(默认为每台计算机4个工作线程,因此,一旦发生错误,您将损失四分之一的状态)。

  • 不要将LocalCluster用于生产工作负载,它不是为此设计的。设置真正的Storm安装,然后仅在一台计算机上运行它。

以下是一些让我惊讶的东西,也许其中一些会有所帮助:

  • 您需要在cluster.submitTopology之后添加一个睡眠,否则您的程序应该立即退出。该调用不会阻塞,它只是将拓扑提交到LocalCluster,然后返回。当您的主要方法退出时,LocalCluster也可能会关闭。在“实际”设置中,您将提交到作为单独进程运行的集群,因此这不是问题,但是在使用LocalCluster时,需要使主线程等待,直到您要关闭程序为止

  • 以防万一您最终在测试中使用了类似的代码,完成后应该记得关闭LocalCluster。它是自动关闭的,因此您可以尝试一下。

  • 在螺栓中确认元组是一个好习惯。如果您只是想在使用元组完成螺栓时确认,请考虑扩展BaseBasicBolt。