Apache storm Apache Storm spout停止从spout发送消息

Apache storm Apache Storm spout停止从spout发送消息,apache-storm,apache-storm-topology,Apache Storm,Apache Storm Topology,我们已经为这个问题奋斗了很长时间。简言之,我们的风暴拓扑在一段时间后以随机方式停止从喷口发出消息。我们有一个自动脚本,在主数据刷新活动完成后,该脚本每天在UTC 06:00重新部署拓扑 在过去两周内,我们的拓扑在UTC时间晚些时候(22:00到02:00之间)停止发送消息3次。只有在协调世界时06:00左右重新启动时,它才会联机 我已经搜索了很多答案和博客,但没有找到这里发生了什么。我们有一个未锚定的拓扑结构,这是我们3-4年前做出的选择。我们从0.9.2开始,现在是1.1.0 我已经检查了所有

我们已经为这个问题奋斗了很长时间。简言之,我们的风暴拓扑在一段时间后以随机方式停止从喷口发出消息。我们有一个自动脚本,在主数据刷新活动完成后,该脚本每天在UTC 06:00重新部署拓扑

在过去两周内,我们的拓扑在UTC时间晚些时候(22:00到02:00之间)停止发送消息3次。只有在协调世界时06:00左右重新启动时,它才会联机

我已经搜索了很多答案和博客,但没有找到这里发生了什么。我们有一个未锚定的拓扑结构,这是我们3-4年前做出的选择。我们从0.9.2开始,现在是1.1.0

我已经检查了所有类型的日志,我100%确定没有调用控制器的
nextTuple()
方法,并且系统中没有可能导致此问题的异常。我还检查了我们积累的所有日志,甚至没有一个错误或警告日志解释突然停止。信息日志也没有那么有用。在工人日志、主管日志或nimbus日志中,没有与此问题相关的内容

这就是我们的喷口课的样子: Controller.java

public class Controller implements IRichSpout {

    SpoutOutputCollector _collector;
    Calendar LAST_RUN = null;
    List<ControllerMessage> msgList;

    /**
     * It is to open the spout
     */
      public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
        _collector = collector;
        msgList= new ArrayList<ControllerMessage>();

        MongoIndexingHandler mongoIndexingHandler = new MongoIndexingHandler();
        mongoIndexingHandler.createMongoIndexes();

      }

      /**
       * It executes the next tuple
       */



    @Override
    public void nextTuple() {
           Map<String, Object> logMap = new HashMap<>();
            logMap.put("BEGIN", new Date());

        try {
            TriggerHandler thandler = new TriggerHandler();
            if (msgList.size() == 0) {
                List<ControllerMessage> mList = thandler.getControllerMessage(new Date());
                msgList = mList;
            }

            if (msgList.size() > 0) {
                ControllerMessage message = msgList.get(0);
                if(thandler.fire(message.getFireTime())) {
                    Util.log(message, "CONTROLLER_LOGS", message.getTime(), new Date());
                    msgList.remove(0);
                    _collector.emit(new Values(message));
                }

            }
            else{
                Utils.sleep(1000);
            }

        } catch (Exception e) {
            _collector.reportError(e);

            Util.exLog(e, "EXECUTOR_ERROR", new Date(), "nextTuple()",Controller.class);
        } 
    }

      /**
       * It acknowledges the messages
       */
      @Override
      public void ack(Object id) {

      }
      /**
       * It tells failed messages
       */
      @Override
      public void fail(Object id) {

      }
     /**
      * It declares the message name
      */
      @Override
      public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("SPOUT_MESSAGE"));
      }

    @Override
    public void activate() {

    }

    @Override
    public void close() {

    }

    @Override
    public void deactivate() {

    }

    @Override
    public Map<String, Object> getComponentConfiguration() {
        return null;
    }


}
public class DiagnosticTopology {

    public static void main(String[] args) throws Exception {
        int gSize = (null != args && args.length > 0) ? Integer.parseInt(args[0]) : 2;
        int sSize = (null != args && args.length > 1) ? Integer.parseInt(args[1]) : 128;
        int sMSize = (null != args && args.length > 2) ? Integer.parseInt(args[2]) : 16;
        int aGSize = (null != args && args.length > 3) ? Integer.parseInt(args[3]) : 16;
        int rSize = (null != args && args.length > 4) ? Integer.parseInt(args[4]) : 64;
        int rMSize = (null != args && args.length > 5) ? Integer.parseInt(args[5]) : 16;
        int dMSize = (null != args && args.length > 6) ? Integer.parseInt(args[6]) : 8;
        int wSize = (null != args && args.length > 7) ? Integer.parseInt(args[7]) : 16;
        String topologyName = (null != args && args.length > 8) ? args[8] : "DIAGNOSTIC";

        TopologyBuilder builder = new TopologyBuilder();

        builder.setSpout("controller", new Controller(), 1);
        builder.setBolt("generator", new GeneratorBolt(), gSize).shuffleGrouping("controller");
        builder.setBolt("scraping", new ScrapingBolt(), sSize).shuffleGrouping("generator");
        builder.setBolt("smongo", new MongoBolt(), sMSize).shuffleGrouping("scraping");
        builder.setBolt("aggregation", new AggregationBolt(), aGSize).shuffleGrouping("scraping");
        builder.setBolt("rule", new RuleBolt(), rSize).shuffleGrouping("smongo");
        builder.setBolt("rmongo", new RMongoBolt(), rMSize).shuffleGrouping("rule");
        builder.setBolt("dstatus", new DeviceStatusBolt(), dMSize).shuffleGrouping("rule");

        builder.setSpout("trigger", new TriggerSpout(), 1);
        builder.setBolt("job", new JobTriggerBolt(), 4).shuffleGrouping("trigger");

        Config conf = new Config();
        conf.setDebug(false);
        conf.setNumWorkers(wSize);

        StormSubmitter.submitTopologyWithProgressBar(topologyName, conf, builder.createTopology());
    }
}
我们为生产和测试环境准备了相当好的服务器(Xeon、8核、32 GB和闪存驱动器),并且没有外部因素会导致此问题,因为代码中到处都有异常处理

当这件事发生时,似乎一切都突然停止了,也没有发生原因的痕迹


非常感谢您的帮助

我不知道是什么原因导致了您的问题,但我建议您首先检查升级到最新的Storm版本是否解决了问题。我知道至少有两个与工作线程死亡和不再出现相关的问题。1750在1.1.0中固定,但2194直到1.1.1才固定

如果升级无法解决问题,您可以通过执行以下操作进行调试

下次拓扑挂起时,打开Storm UI并找到喷口。它将显示运行喷口的执行者列表,以及负责运行喷口的工人。选择一个喷口执行器没有排放任何东西的工人。在运行该worker的机器上打开一个shell,并找到worker JVM的进程id。使用
jps-m
可以很容易地做到这一点

示例输出显示本地计算机上端口为6701的工作JVM,其pid为7592:

7592工人测试-2-1520361882 d24dc55d-76c7-4cc6-93fa-2663fcdcb1ba-10.0.75.1 6701 f7b6f8e4-6c87-47ca-a7b7-655009b6c62a

通过执行
kill-3
触发线程转储,或者如果愿意,使用
jstack

在线程转储中,您应该能够找到挂起的执行器线程。例如,当我为一个带有一个名为“word”的喷口的拓扑进行线程转储时,其中一个喷口执行器的编号是13,我看到了

编辑:堆栈溢出不允许我发布堆栈跟踪,因为查找未格式化代码的启发式方法不好。我花在发布堆栈跟踪上的时间可能与写原始答案的时间一样长,所以我不必费心继续尝试。这是应该在这里的痕迹

这向我展示了执行者13目前正在做什么。在这种情况下,它在调用nextTuple时处于休眠状态


如果您能找到挂起的执行器在做什么,您应该能够更好地解决问题,或者向Storm报告错误。

我们在应用程序中观察到了这一点,我们的CPU非常繁忙,所有其他线程都在等待轮到它们。当我们试图使用JVisualVM检查资源使用情况以找到根本原因时,我们发现某些螺栓中的某些功能导致了大量开销和CPU时间。请通过电话查询。如果nextTuple()方法的CPU关键路径中有阻塞的线程,或者您从上游接收到相同的数据,请使用任何分析工具。

谢谢!这应该会有帮助。在升级之前,我想先分析一下问题,以便对其进行验证。只是等待它再次停止:P将用我的发现向您更新。再次感谢您的帮助:)