Springboot集成GraphicsMagick

以什么方式集成?

JNI / 命令行(im4java)

在im4java官网中提到:

翻译过来就是: 从Java内部使用JNI运行本机代码始终会带来其他风险,对于长时间运行的进程(通常是Web应用程序服务器)尤其危险。内存损坏或分段错误(可能由故意操纵的图像触发)可能会使整个服务器瘫痪。

所以我们选择使用命令行的方式进行调用。

项目集成

1、将gm命令行工具引入到项目中

在SpringBoot集成Linux可执行命令的时候,我们将可执行文件放在了项目的resource目录下:

这里需要有一步操作就是将文件复制到宿主机:

    private void initGM() throws Exception {
        String osName = System.getProperty("os.name").toLowerCase();
        log.info("os name: {}", osName);
        String gmPath;
        if (osName.contains("mac")) {
            gmPath = "gm/mac/gm";
        } else if (osName.contains("linux")) {
            // 初始化容器的环境
            initPodEnv();
            gmPath = "gm/linux/gm";
        } else {
            throw new RuntimeException("非法操作系统:"+osName);
        }
        InputStream fisInJar = new ClassPathResource(gmPath).getInputStream();
        File file = File.createTempFile("GraphicsMagick", "_gm");
        file.setExecutable(true);
        GM_PATH = file.getAbsolutePath();
        //将jar包里的gm复制到操作系统的目录里
        OutputStream fosInOs = new FileOutputStream(file);
        byte[] buffer = new byte[1024];
        int readLength = fisInJar.read(buffer);
        while (readLength != -1) {
            fosInOs.write(buffer, 0, readLength);
            readLength = fisInJar.read(buffer);
        }
        IOUtils.closeQuietly(fosInOs);
        IOUtils.closeQuietly(fisInJar);
        log.info("gm初始化完毕");
    }

2、在项目启动的时候自动初始化环境

下面只对Linux进行了自动化环境安装,mac环境主要是本地开发,自己安装环境即可:

    /**
     * 初始化容器的环境
     *
     * 安装gm所依赖的库
     */
    private void initPodEnv() throws Exception {
        log.info("============ start init pod env ============");
        Process exec1 = Runtime.getRuntime().exec("yum install -y gcc make");
        this.printLog(exec1);
        log.info("cmd 1 exec success");

        Process exec2 = Runtime.getRuntime().exec("yum install -y libpng-devel libjpeg-devel libtiff-devel jasper-devel freetype-devel libtool-ltdl-devel*");
        this.printLog(exec2);
        log.info("cmd 2 exec success");
        // 打水印时缺少依赖
        Process exec3 = Runtime.getRuntime().exec("yum -y install ghostscript");
        this.printLog(exec3);
        log.info("cmd 3 exec success");
        log.info("============ init pod env success ============");
    }

3、gm进程池化

想象下,如果在每次进行图片处理都去 fork gm子进程,不仅代价大,而且在高并发情况下,容易造成子进程过多,导致系统负载飙高,上下文切换频繁。

所以将 gm进程 池化是很有必要的。

前提: gm提供batch批量模式,运行在此模式下的gm进程,会一直读取标准输入,逐行接收命令实时进行处理。

池化思路: 预先 fork 一批 gm 子进程,每次要运行命令时,从子进程池中挑选一个子进程,进行图片处理,处理完毕后归还连接。

具体架构:

/**
 * GM 进程池参数
 */
@ConfigurationProperties(prefix = "gm.pool")
@Data
public class GMPoolProperties {

    /**
     * 连接池最大活跃数
     */
    private int maxActive = 4;

    /**
     * 连接池最大空闲连接数
     */
    private int maxIdle = 4;

    /**
     * 连接池最小空闲连接数
     */
    private int minIdle = 2;

    /**
     * 资源池中资源最小空闲时间(单位为毫秒),达到此值后空闲资源将被移
     */
    private long minEvictableIdleTimeMillis = 300000L;

    /**
     * 连接池连接用尽后执行的动作
     */
    private WhenExhaustedAction whenExhaustedAction = WhenExhaustedAction.BLOCK;

    /**
     * 连接池没有对象返回时,最大等待时间(毫秒)
     */
    private long maxWait = 5000;

    /**
     * 定时对线程池中空闲的链接进行校验
     */
    private boolean testWhileIdle = false;

    /**
     * 空闲资源的检测周期(单位为毫秒)
     */
    private long timeBetweenEvictionRunsMillis = 10000L;

}

性能初测

1、单线程测试: 单线程循环100次

技术 耗时 平均耗时
GraphicsMagick + im4java 2110 ms 21 ms
GraphicsMagick + im4java + 池化技术 1478 ms 15 ms

总结:性能提升约29%  
2、多线程并发测试: 并发100个线程请求

技术 耗时 平均耗时
GraphicsMagick + im4java 37901 ms 379 ms
GraphicsMagick + im4java + 池化技术 22456 ms 224 ms

总结:性能提升约41%

写在最后

目前主流的是使用openresty(nginx + lua)来搭建图片处理服务,使用Java的话性能可能会比较差。因为对Java技术栈比较熟悉,前期会先使用Java实现。

本文的demo版本已经上传到github上,感兴趣的小伙伴可以去看下: github.com/Shanbw/Grap…

以上就是Springboot集成GraphicsMagick的详细内容,更多关于Springboot集成GraphicsMagick的资料请关注我们其它相关文章!

(0)

相关推荐

  • SpringBoot入坑笔记之spring-boot-starter-web 配置文件的使用

    经过上一篇的介绍,相信小伙伴们已经按奈不住内心对springboot的向往,本篇我将继续向小伙伴介绍springboot配置文件的配置,已经全局配置参数如何使用,好了下面开始我们今天的内容介绍. 我们知道Spring Boot支持容器的自动配置,默认是Tomcat,当然我们也是可以进行修改的: 1.首先我们排除spring-boot-starter-web依赖中的Tomcat:在pom文件中排除tomcat的starter <dependency> <groupId>org.spr

  • springboot如何读取配置文件(application.yml)中的属性值

    在spring boot中,简单几步,读取配置文件(application.yml)中各种不同类型的属性值: 1.引入依赖: <!-- 支持 @ConfigurationProperties 注解 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId>

  • 详解SpringBoot文件上传下载和多文件上传(图文)

    最近在学习SpringBoot,以下是最近学习整理的实现文件上传下载的Java代码: 1.开发环境: IDEA15+ Maven+JDK1.8 2.新建一个maven工程: 3.工程框架 4.pom.xml文件依赖项 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation

  • 详解SpringBoot配置连接池

    内置的连接池 目前spring Boot中默认支持的连接池有dbcp,dbcp2, tomcat, hikari三种连接池. 数据库连接可以使用DataSource池进行自动配置. 由于Tomcat数据源连接池的性能和并发,在tomcat可用时,我们总是优先使用它. 如果HikariCP可用,我们将使用它. 如果Commons DBCP可用,我们将使用它,但在生产环境不推荐使用它. 最后,如果Commons DBCP2可用,我们将使用它. 以上的几种连接池,可以通过在配置application文

  • 详解springboot-修改内置tomcat版本

    详解springboot-修改内置tomcat版本 1.解析Spring Boot父级依赖 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.6.RELEASE</version> </parent> 这块配置就是Spring

  • SpringBoot定时任务两种(Spring Schedule 与 Quartz 整合 )实现方法

    前言 最近在项目中使用到定时任务,之前一直都是使用Quartz 来实现,最近看Spring 基础发现其实Spring 提供 Spring Schedule 可以帮助我们实现简单的定时任务功能. 下面说一下两种方式在Spring Boot 项目中的使用. Spring Schedule 实现定时任务 Spring Schedule 实现定时任务有两种方式 1. 使用XML配置定时任务, 2. 使用 @Scheduled 注解. 因为是Spring Boot 项目 可能尽量避免使用XML配置的形式,

  • SpringBoot+Maven 多模块项目的构建、运行、打包实战

    本篇文章主要介绍了SpringBoot+Maven 多模块项目的构建.运行.打包,分享给大家,具体如下: 项目使用的工具: IntelliJ IDEA JDK 1.8 apache-maven-3.3.9 项目的目录: 主项目 springboot-multi 子模块 entity.dao.service.web 一.使用IDEA创建一个SpringBoot项目 : File -> new -> Project 项目名称为springboot-multi 二.删除项目中的src目录,把pom.

  • php下尝试使用GraphicsMagick的缩略图功能

    常用的图片处理工具有GD,ImageMagick,GraphicsMagick等等.GD就是个阿斗,略过不提:ImageMagick是目前最流行的图片处理工具,它的功能非常丰富:GraphicsMagick的功能略逊于ImageMagick,但是它的效率更强悍,就好比Apache和Nginx一样,一个功能更强,一个效率更胜. 现在更看重效率,所以本文就以GraphicsMagick为例来说说: 对于PHPer来说,有两种使用GraphicsMagick的方式: 1:使用PECL Gmagick扩

  • Springboot集成GraphicsMagick

    以什么方式集成? JNI / 命令行(im4java) 在im4java官网中提到: 翻译过来就是: 从Java内部使用JNI运行本机代码始终会带来其他风险,对于长时间运行的进程(通常是Web应用程序服务器)尤其危险.内存损坏或分段错误(可能由故意操纵的图像触发)可能会使整个服务器瘫痪. 所以我们选择使用命令行的方式进行调用. 项目集成 1.将gm命令行工具引入到项目中 在SpringBoot集成Linux可执行命令的时候,我们将可执行文件放在了项目的resource目录下: 这里需要有一步操作

  • 详解Spring-Boot集成Spring session并存入redis

    spring Session 提供了一套用于管理用户 session 信息的API和实现. Spring Session为企业级Java应用的session管理带来了革新,使得以下的功能更加容易实现: 编写可水平扩展的原生云应用. 将session所保存的状态卸载到特定的外部session存储中,如Redis或Apache Geode中,它们能够以独立于应用服务器的方式提供高质量的集群. 当用户使用WebSocket发送请求的时候,能够保持HttpSession处于活跃状态. 在非Web请求的处

  • SpringBoot集成Spring Data JPA及读写分离

    相关代码: github OSCchina JPA是什么 JPA(Java Persistence API)是Sun官方提出的Java持久化规范,它为Java开发人员提供了一种对象/关联映射工具 来管理Java应用中的关系数据.它包括以下几方面的内容: 1.ORM映射 支持xml和注解方式建立实体与表之间的映射. 2.Java持久化API 定义了一些常用的CRUD接口,我们只需直接调用,而不需要考虑底层JDBC和SQL的细节. 3.JPQL查询语言 这是持久化操作中很重要的一个方面,通过面向对象

  • 详解SpringBoot集成jsp(附源码)+遇到的坑

    本文介绍了SpringBoot集成jsp(附源码)+遇到的坑 ,分享给大家 1.大体步骤 (1)创建Maven web project: (2)在pom.xml文件添加依赖: (3)配置application.properties支持jsp (4)编写测试Controller (5)编写JSP页面 (6)编写启动类App.java 2.新建SpringInitialzr 3.pom文件 <dependencies> <dependency> <groupId>org.s

  • SpringBoot集成Swagger2实现Restful(类型转换错误解决办法)

    pom.xml增加依赖包 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <

  • springboot集成activemq的实例代码

    ActiveMQ ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位. 特性 多种语言和协议编写客户端.语言: Java,C,C++,C#,Ruby,Perl,Python,PHP.应用协议: OpenWire,Stomp REST,WS Notification,XMPP,AMQP

  • SpringBoot 集成Kaptcha实现验证码功能实例详解

    在一个web应用中验证码是一个常见的元素.不管是防止机器人还是爬虫都有一定的作用,我们是自己编写生产验证码的工具类,也可以使用一些比较方便的验证码工具.在网上收集一些资料之后,今天给大家介绍一下kaptcha的和springboot一起使用的简单例子. 准备工作: 1.你要有一个springboot的hello world的工程,并能正常运行. 2.导入kaptcha的maven: <!-- https://mvnrepository.com/artifact/com.github.penggl

  • SpringBoot集成MyBatis的分页插件PageHelper实例代码

    昨天给各位总结了本人学习springboot整合mybatis第一阶段的一些学习心得和源码,主要就算是敲了一下SpringBoot的门儿,希望能给各位的入门带给一点儿捷径,今天给各位温习一下MyBatis的分页插件PageHelper和SpringBoot的集成,它的使用也非常简单,开发更为高效.因为PageHelper插件是属于MyBatis框架的,所以相信很多哥们儿都已经用烂了,下面带着各位吃一下回头草. 首先说说MyBatis框架的PageHelper插件吧,它是一个非常好用的分页插件,通

  • SpringBoot集成多数据源解析

    一,前面我们介绍了springboot的快速启动,大家肯定对springboot也有所了解,下面我们来介绍一下springboot怎么集成多数据源. 在有的项目开发中需要在一个项目中访问多个数据源或者两个项目之间通信(实质上是互相访问对方的数据库),在这里,我们介绍一下在一个项目中如何集成多个数据源(即访问多个不同的数据库),因为在项目中有时会有这种需求,比如在一个大型项目开发中,一个数据库中保存数据的索引,各种使用频繁的数据,另一个数据库中保存其他的数据. 1.下面我们来讨论一个问题,怎么集成

  • SpringBoot集成swagger的实例代码

    Swagger 是一款RESTFUL接口的文档在线自动生成+功能测试功能软件.本文简单介绍了在项目中集成swagger的方法和一些常见问题.如果想深入分析项目源码,了解更多内容,见参考资料. Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步.Swagger 让部署管理和使用功能强大的API从未如此简单. 对于

随机推荐