Java调用shell脚本执行imagemagick压缩图片


文章目录

  • 前言
  • 安装
    • 方式一:Dockerfile
    • 方式二:进入已有容器内部安装
    • 测试
  • Linux上压缩
  • Java执行shell实现压缩


前言

自己做个小项目,有个需求得存储图片,为了页面渲染速度。
这里存储的是压缩图片,然后外链指向原图。本地不存储。美滋滋。
但是想法很美好,结果缺不尽人意…

业务逻辑上一点问题没有,结果出在服务器上,内存不足,导致宕机。
一通排查之后发现是压缩图片这里导致的内存溢出。
尝试解决办法:

  • 所有IO流操作完立马close,无效
  • 数量降低为每分钟处理3张图片,无效
  • 采用谷歌的开源工具thumbnailator,无效

最后无奈在linux上安装imagemagick,然后java执行shell语句去压缩图片。
然后就一路顺畅了,不得不说java的IO真的吃内存。


安装

介绍一下本文的环境,java项目运行在docker容器中,基于java:8-alpine镜像。
注意是alpine,超苗条的linux。所以很多基本指令在容器内都没有。

方式一:Dockerfile

全写注释了,就不做过多额外的解释了

FROM java:8-alpine
ADD target/xxx.jar xxx.jar
# 修改alpine的源地址改为阿里的,否则下载速度极慢
RUN echo -e "https://mirrors.aliyun.com/alpine/v3.7/main" > /etc/apk/repositories
# 更新本地apk的镜像索引数据 并且 安装imagemagick
RUN apk update && apk add imagemagick
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/xxx.jar"]

方式二:进入已有容器内部安装

# 进入容器,因为是基于alpine,所以这里用sh,而不是bash
docker exec -it xxx sh
# 修改alpine的源地址改为阿里的,否则下载速度极慢
echo -e "https://mirrors.aliyun.com/alpine/v3.7/main" > /etc/apk/repositories
# 更新本地apk的镜像索引数据 并且 安装imagemagick
apk update && apk add imagemagick

测试

convert -version

/ # convert -version
Version: ImageMagick 7.0.7-11 Q16 x86_64 2017-11-15 http://www.imagemagick.org
Copyright: © 1999-2017 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC HDRI Modules OpenMP
Delegates (built-in): bzlib cairo fontconfig freetype gslib jng jpeg lcms ltdl pangocairo png ps rsvg tiff webp xml zlib
/ #


Linux上压缩

官方示例:https://www.imagemagick.org/Usage/

# 压缩质量为70% 1.png:源文件 to1.jpng:压缩后的文件 
convert -quality 70% 1.png to1.jpg && rm -f 1.png
# 如何用这个还是提示内存不足的话,再加上两个参数即可。设置最大内存2mb
convert -limit memory 2mb -limit map 2mb -quality 70% 1.png to1.jpg && rm -f 1.png


Java执行shell实现压缩

String cmd = "convert -limit memory 2mb -limit map 2mb -quality 70% 1.png to1.jpg && rm -f 1.png";
// "sh", "-c"不可省略,waitFor:阻塞线程等待shell执行结束
Runtime.getRuntime().exec(new String[]{"sh", "-c", cmd}).waitFor();

你可能感兴趣的:(Linux,java)