Apache Batik Transcoder inside Docker Container Bl

2019-05-10 03:56发布

We're running a Spring application within a docker container. Our application can take SVG files and transform them into PDF format to be embedded within a PDF.

The application works correctly on osx and transcodes as expected. However when run from inside a docker container, which has a different file system, the transcoder gets stuck and thrashes the cpu in some bizarre recursive file searching loop.

java.lang.Thread.State: RUNNABLE
    at java.io.UnixFileSystem.getBooleanAttributes0(Native Method)
    at java.io.UnixFileSystem.getBooleanAttributes(UnixFileSystem.java:242)
    at java.io.File.isFile(File.java:882)
    at org.apache.commons.io.filefilter.FileFileFilter.accept(FileFileFilter.java:59)
    at org.apache.commons.io.filefilter.AndFileFilter.accept(AndFileFilter.java:122)
    at org.apache.commons.io.filefilter.AndFileFilter.accept(AndFileFilter.java:122)
    at org.apache.commons.io.filefilter.OrFileFilter.accept(OrFileFilter.java:118)
    at java.io.File.listFiles(File.java:1291)
    at org.apache.commons.io.DirectoryWalker.walk(DirectoryWalker.java:357)
    at org.apache.commons.io.DirectoryWalker.walk(DirectoryWalker.java:364)
    at org.apache.commons.io.DirectoryWalker.walk(DirectoryWalker.java:364)
    at org.apache.commons.io.DirectoryWalker.walk(DirectoryWalker.java:364)
    at org.apache.commons.io.DirectoryWalker.walk(DirectoryWalker.java:364)
    at org.apache.commons.io.DirectoryWalker.walk(DirectoryWalker.java:364)
    at org.apache.commons.io.DirectoryWalker.walk(DirectoryWalker.java:364)
    at org.apache.commons.io.DirectoryWalker.walk(DirectoryWalker.java:364)
    at org.apache.commons.io.DirectoryWalker.walk(DirectoryWalker.java:364)
    at org.apache.commons.io.DirectoryWalker.walk(DirectoryWalker.java:364)
    at org.apache.commons.io.DirectoryWalker.walk(DirectoryWalker.java:364)
    at org.apache.commons.io.DirectoryWalker.walk(DirectoryWalker.java:364

Here's a look at the stack trace of a thread that ran the PDFTranscoder. Walk is called recursively for a while and then eventually getBooleanAttributes0 is called and everything blocks.

After some further research we found out we could take a closer look at what is happening with the strace command and saw that the system is essentially spamming the following in an endless loop.

stat("/./sys/devices/pci0000:00/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/PNP0103:00/subsystem/devices/pcspkr/input/input1/subsystem/input0/subsystem/input0/uniq", {st_mode=S_IFREG|0444, st_size=4096, ...}) = 0 <0.000224>

We seem to be getting blocked or hanging in the stat call. But we've delved so deep into system calls now that it's proving hard to debug. Does anyone have any ideas?

4条回答
地球回转人心会变
2楼-- · 2019-05-10 03:58

I was getting the same error. After trying many things to fix it, I came to the conclusion that it's an issue with your having fonts available to you on Mac OS X, while your (headless) Docker container OS has no fonts. The transcoder is not failing gracefully while searching for fonts all over the place. I solved it by forcing the transcoder to use the default fonts (and to not automatically look for other fonts) like this:

...
PDFTranscoder transcoder = new PDFTranscoder();
transcoder.addTranscodingHint(PDFTranscoder.KEY_AUTO_FONTS, false);
...
transcoder.transcode(transcoderInput, transcoderOutput);
...

Note this has the downside, of course, of falling back to its known fonts when it encounters one outside of the 14 fonts. I tried things to fix that but so far no luck.

I hope this helps someone.

查看更多
来,给爷笑一个
3楼-- · 2019-05-10 04:02

Try adding the parameter '-Duser.dir=/%CATALINA_HOME/' to your CATALINA_OPTS. I encountered the same issue on my centos server.

查看更多
爷的心禁止访问
4楼-- · 2019-05-10 04:13

I had the same problem on my project. I solve it with the downgrade of batik to 1.7 version.

I hope this will work for you.

查看更多
▲ chillily
5楼-- · 2019-05-10 04:15

Had the same issue. Solved it by setting the WORKDIR variable in the DockerFile. I set it to my deployment dir where I copy the spring jar file. ie

WORKDIR ${DEPLOYMENT_DIR}

using latest batik libraries in pom

    <dependency>
        <groupId>org.apache.xmlgraphics</groupId>
        <artifactId>batik-all</artifactId>
        <version>1.9.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.xmlgraphics</groupId>
        <artifactId>fop</artifactId>
        <version>2.2</version>
    </dependency>
查看更多
登录 后发表回答