【问题标题】:How to I generate a thread dump for an Java process on heroku?如何在 heroku 上为 Java 进程生成线程转储?
【发布时间】:2014-03-07 19:15:00
【问题描述】:

我希望能够为运行在 heroku 上的 Java 应用程序生成 Java 线程转储?我看到 heroku 正在运行 jstack,但我不知道如何运行它以在我的进程上生成线程转储。我不知道如何让 PID 发送到 jstack。一旦我有了 PID,我只需从我的开发机器上运行“heroku jstack -l”(它安装了工具带)?

【问题讨论】:

    标签: java heroku


    【解决方案1】:

    好的,这是最好的方法。这将为您提供 JVM 使用的格式,而不必以编程方式重新创建它。同样,这是针对 heroku 的,其他环境需要调整此代码。这会将其公开为一个休息接口。

    @GET
    @Transactional
    @Path( "/threaddump" )
    public Response threadDump() throws Exception {
        dumpThreads();
        return Response.ok().build();
    }
    
    public static void dumpThreads() throws Exception {
        ProcessBuilder processBuilder = new ProcessBuilder( "/bin/sh", "-c", "kill -3 $PPID" );
        processBuilder.redirectErrorStream( true );
        Process process = processBuilder.start();
        InputStream inputStream = process.getInputStream();
        StreamUtils.copy( inputStream, System.out );
    }
    

    【讨论】:

    • 是 org.springframework.util.StreamUtils 吗?什么是响应类型?为什么不将输出写入文件?只是好奇。我理解 kill -3 部分,但想知道您为什么选择这种方法来获取响应。
    • 我希望它出现在我的 papertrail 日志中,我也希望它像 Ctrl-Break 一样响应。真的不希望它在文件中。不确定我是否理解您关于响应类型的问题。在 StreamUtils 上,您还可以使用 Guava CharStreams.toString(in) 并将其发送到 LOG 或 System.out。
    • 在你的函数中 public Response threadDump() throws Exception {,这个 Response 类的全名是什么——我不熟悉。所以这会将结果打印到应用系统?
    • 哦,我只是在使用 JAX-RS Jersey。这是他们拥有的 Response 类。
    【解决方案2】:

    您可以尝试以下操作 - 将此函数放在某个类中并有办法调用它,将输出保存到文件或在页面上显示...

    static StringBuilder allStack() {
        StringBuilder sb = new StringBuilder();
        Map<Thread, StackTraceElement[]> trace = Thread.getAllStackTraces();
        for(Thread t:trace.keySet()){
            StackTraceElement[]trc = trace.get(t);
            sb.append("\n");
            sb.append(t.getName());
            sb.append(" ");         
            sb.append(t.getId());
    
            sb.append(" |");            
            sb.append(t.getThreadGroup());
    
            sb.append("| ");            
            sb.append(t);
            sb.append(" :-\n");
            for(StackTraceElement e:trc){
                sb.append(e.toString());
                sb.append("\n");
            }
            sb.append(" -***-\n");
        }
        return sb;
    }
    

    【讨论】:

    • 谢谢,我知道该怎么做。但我不想以编程方式进行。我想从控制台做到这一点。因此,对于在 Heroku dyno 上运行的 Web 服务器,我想从我的本地机器生成一个线程转储。
    • 不知道。它更强大->如果进程挂起。为什么不通过您的主机中的票询问?
    【解决方案3】:

    您还可以考虑将 REST API 嵌入到 java JMX 以执行此线程转储。 Jolokia 似乎是一个不错的候选人。它还将支持内置身份验证并且更加灵活,因为您可以访问任何 JMX mbean 而无需实现新的 REST 端点

    http://www.jolokia.org,特别是使用POST Exec request调用ThreadMXBean.dumpAllThreads()方法的REST协议

    【讨论】:

      猜你喜欢
      • 2011-07-04
      • 1970-01-01
      • 2011-02-16
      • 1970-01-01
      • 2010-11-24
      • 2012-12-16
      • 2011-04-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多