简体   繁体   English

Tomcat冻结了SpringBoot App的部署

[英]Tomcat Freezes deploying SpringBoot App

I'm trying to deply some Apps (4 spring boot web apps) in Tomcat 9 , I noticed 2 of them make Tomcat log to display: 我正在尝试在Tomcat 9中使用某些应用程序(4个春季启动Web应用程序),我注意到其中2个使Tomcat日志显示:

17-Nov-2016 00:15:07.110 INFO [localhost-startStop-2] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive /Users/viruskimera/apache-tomcat-9.0.0.M11/webapps/ftpoutbound990-0.0.1-SNAPSHOT.war

And it stays that way just deploying it doesn't display DEPLOYMENT FINISHED. 而且它保持这种状态,只是部署它不会显示DEPLOYMENT FINISHED。 the thing is that the App WORKS even when it doens't appear DEPLOYED completely. 事实是,即使应用程序并未完全部署,它也能正常工作。 (I see my log4j entries and files are processed in the monitored folder) (我看到我的log4j条目和文件在受监视的文件夹中处理)

These apps monitor 2 different folders using Java watchService with the following code: 这些应用程序使用Java watchService通过以下代码监视2个不同的文件夹:

package com.ftpoutbound990.monitor; 包com.ftpoutbound990.monitor;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.ClosedWatchServiceException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.ftpoutbound990.client.FtpoutboundApp;

@Component
public class MonitorDirectory {

    final static Logger logger = Logger.getLogger(MonitorDirectory.class);

    @Autowired
    private FtpoutboundApp ftpoutboundapp;

    @Value("${folder990}")
    private String folder990;

    public void startMonitoring() throws IOException, InterruptedException {
        logger.info("INICIO DE MONITOREO DE ARCHIVOS 990");
        try (WatchService watchService = FileSystems.getDefault().newWatchService()) {

            Path faxFolder = Paths.get(folder990);

            WatchService watchmyservice = FileSystems.getDefault().newWatchService();
            faxFolder.register(watchmyservice, StandardWatchEventKinds.ENTRY_CREATE);

            boolean valid = true;
            do {
                try {
                    WatchKey watchKey = watchmyservice.take();

                    for (WatchEvent event : watchKey.pollEvents()) {
                        WatchEvent.Kind kind = event.kind();
                        if (StandardWatchEventKinds.ENTRY_CREATE.equals(event.kind())) {
                            String fileName = event.context().toString();
                            logger.info("ARCHIVO NUEVO:" + fileName);
                            boolean isGrowing = false;
                            Long initialWeight = new Long(0);
                            Long finalWeight = new Long(0);
                            Path child = faxFolder.resolve(folder990 + fileName);
                            do {
                                initialWeight = child.toFile().length();
                                Thread.sleep(1000);
                                finalWeight = child.toFile().length();
                                isGrowing = initialWeight < finalWeight;
                                logger.info("AUN COPIANDO ARCHIVO:" + fileName);
                            } while (isGrowing);
                            logger.info("LISTO ARCHIVO:" + fileName);
                            getFile(fileName);
                        }
                    }
                    valid = watchKey.reset();
                    // Thread.sleep(1000 * 10);
                } catch (InterruptedException | ClosedWatchServiceException e) {
                    //watchmyservice.close();
                    Thread.currentThread().interrupt();
                }

            } while (valid);
        }
    }

    public void getFile(String fileName) throws IOException {

        File file = new File(folder990 + fileName);
        ftpoutboundapp.createGateway(file);
    }

}

If I remove the Do-While the Apps do finished deployed! 如果我删除Do-While,则应用程序会完成部署! But why? 但为什么? It's a standard Java watchservice code, could anybody help me to realize what I'm missing/what's the issue? 这是标准的Java监视服务代码,有人可以帮助我认识到我所缺少的内容吗? the thing is that Tomcat doesn't deploy my 4th App cause it keeps deploying the 3rd one. 事实是,Tomcat没有部署我的第4个应用程序,因为它一直在部署第3个应用程序。 Thanks in advance for your help 在此先感谢您的帮助


EDIT 1: ADDING THREAD 编辑1:添加线程

28-Dec-2016 17:57:27.558 INFO [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
28-Dec-2016 17:57:27.559 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-8080"]
28-Dec-2016 17:57:27.613 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-8009"]
28-Dec-2016 17:57:27.664 INFO [main] org.apache.catalina.core.StandardService.stopInternal Stopping service Catalina
28-Dec-2016 17:57:27.664 SEVERE [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.startup.HostConfig.deployWARs Error waiting for multi-thread deployment of WAR files to complete
 java.lang.InterruptedException
    at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:404)
    at java.util.concurrent.FutureTask.get(FutureTask.java:191)
    at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:744)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:407)
    at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1595)
    at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:280)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:92)
    at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1136)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1372)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1376)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1344)
    at java.lang.Thread.run(Thread.java:745)

28-Dec-2016 18:00:21.904 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version:        Apache Tomcat/9.0.0.M11
28-Dec-2016 18:00:21.907 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built:          Oct 6 2016 18:54:10 UTC
28-Dec-2016 18:00:21.908 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server number:         9.0.0.0
28-Dec-2016 18:00:21.908 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name:               Mac OS X
28-Dec-2016 18:00:21.908 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version:            10.9.5
28-Dec-2016 18:00:21.908 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture:          x86_64
28-Dec-2016 18:00:21.908 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home:             /Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre
28-Dec-2016 18:00:21.908 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version:           1.8.0_73-b02
28-Dec-2016 18:00:21.908 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor:            Oracle Corporation
28-Dec-2016 18:00:21.909 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE:         /Users/viruskimera/apache-tomcat-9.0.0.M11
28-Dec-2016 18:00:21.909 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME:         /Users/viruskimera/apache-tomcat-9.0.0.M11
28-Dec-2016 18:00:21.909 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=/Users/viruskimera/apache-tomcat-9.0.0.M11/conf/logging.properties
28-Dec-2016 18:00:21.909 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
28-Dec-2016 18:00:21.909 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
28-Dec-2016 18:00:21.910 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
28-Dec-2016 18:00:21.910 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=/Users/viruskimera/apache-tomcat-9.0.0.M11
28-Dec-2016 18:00:21.910 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=/Users/viruskimera/apache-tomcat-9.0.0.M11
28-Dec-2016 18:00:21.910 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=/Users/viruskimera/apache-tomcat-9.0.0.M11/temp
28-Dec-2016 18:00:21.910 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /Users/viruskimera/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.
28-Dec-2016 18:00:22.063 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"]
28-Dec-2016 18:00:22.093 INFO [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector Using a shared selector for servlet write/read
28-Dec-2016 18:00:22.096 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["ajp-nio-8009"]
28-Dec-2016 18:00:22.098 INFO [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector Using a shared selector for servlet write/read
28-Dec-2016 18:00:22.100 INFO [main] org.apache.catalina.startup.Catalina.load Initialization processed in 604 ms
28-Dec-2016 18:00:22.145 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service Catalina
28-Dec-2016 18:00:22.145 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/9.0.0.M11
28-Dec-2016 18:00:22.224 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive /Users/viruskimera/apache-tomcat-9.0.0.M11/webapps/ftpoutbound990-0.0.1-SNAPSHOT.war
28-Dec-2016 18:00:26.346 INFO [localhost-startStop-1] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.3.6.RELEASE)

Taking a shot in the blind.. 在盲人手中射击。

A simple review of your code suggests that if an exception is thrown inside the try catch, the boolean flag valid remains true causing an infinite loop. 对代码的简单回顾表明,如果在try catch中引发异常,则布尔标志valid仍然为true从而导致无限循环。

Hence set the flag to false in the body of the catch block! 因此,在catch块的主体中​​将标志设置为false!

The tomcat deployer thread seems invoking the startMonitoring method. tomcat部署程序线程似乎正在调用startMonitoring方法。 As intended, this method never returning back and hence deployment is not getting complete. 按照预期,此方法永不返回,因此部署未完成。

To fix this, need to run the monitoring method in separate (or background) thread. 要解决此问题,需要在单独的(或后台)线程中运行监视方法。

Below refactored example may be helpful. 下面的重构示例可能会有所帮助。

Aside note, a single instance of WatcherService instances can be used for watching the multiple directories. 另外请注意,可以使用WatcherService实例的单个实例来监视多个目录。

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class MonitorDirectory {

    final static Logger logger = Logger.getLogger(MonitorDirectory.class);

    @Autowired
    private FtpoutboundApp ftpoutboundapp;

    @Value("${folder990}")
    private String folder990;

    private WatchService watchService;

    private ExecutorService eventLoop = Executors.newFixedThreadPool(1);

    @PostConstruct
    public void init() throws IOException, InterruptedException {
        watchService = FileSystems.getDefault().newWatchService();
        eventLoop.submit((Runnable) () -> {
            try {
                startMonitoring();
            } catch (Exception e) {
                logger.error("ERROR...", e);
            }
        });
    }

    @PreDestroy
    public void destroy() throws IOException {
        eventLoop.shutdownNow();
        if (watchService != null) {
            watchService.close();
        }
    }

    public void startMonitoring() throws IOException, InterruptedException {
        logger.info("INICIO DE MONITOREO DE ARCHIVOS 990");
        Path faxFolder = Paths.get(folder990);
        WatchKey watchKey = faxFolder.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
        boolean valid = true;
        do {
            for (WatchEvent<?> event : watchKey.pollEvents()) {
                WatchEvent.Kind<?> kind = event.kind();
                if (StandardWatchEventKinds.ENTRY_CREATE.equals(kind)) {
                    String fileName = event.context().toString();
                    logger.info("ARCHIVO NUEVO:" + fileName);
                    boolean isGrowing = false;
                    Long initialWeight = new Long(0);
                    Long finalWeight = new Long(0);
                    Path child = faxFolder.resolve(folder990 + fileName);
                    do {
                        initialWeight = child.toFile().length();
                        Thread.sleep(1000);
                        finalWeight = child.toFile().length();
                        isGrowing = initialWeight < finalWeight;
                        logger.info("AUN COPIANDO ARCHIVO:" + fileName);
                    } while (isGrowing);
                    logger.info("LISTO ARCHIVO:" + fileName);

                    getFile(fileName);
                }
                valid = watchKey.reset();
            }
        } while (valid);
    }

    public void getFile(String fileName) throws IOException {
        File file = new File(folder990 + fileName);
        ftpoutboundapp.createGateway(file);
    }

}

Can you check the few things below. 您能检查以下几件事吗?

Is the Component MonitorDirectory is called only once in your applications. 是组件MonitorDirectory在您的应用程序中仅被调用一次。 If not, you may need to declare 'eventLoop' as static and check the initialization in PostConstruct to avoid multiple initialization and invocation. 如果不是,则可能需要将“ eventLoop”声明为静态,并检查PostConstruct中的初始化,以避免多次初始化和调用。

Also, executorservice is initialized with the threadpool of 1 and if Multiple MonitorDirectory object is initialized in your application, this might lead to the deployment freeze 另外,executorservice的线程池为1初始化,并且如果您的应用程序中初始化了多个MonitorDirectory对象,则可能导致部署冻结

Is there any chance, the filesize could be shrinking in the server environment. 有没有机会,文件大小可能会在服务器环境中缩小。 This might lead to infinite looping on 'isGrowing' check.. 这可能会导致“ isGrowing”检查无限循环。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM