java 轻量级文件数据库

基于云的Java数据库应用程序的数量每分钟都在增加。 许多组织部署了数百甚至数千个微服务实例。 但是,相对于运行时环境,大多数应用程序会带来惊人的不必要开销。 反过来,这会使应用程序运行更慢,运行成本更高。

在本文中,我将演示如何编写比normal(*)小10倍的数据库应用程序。 考虑到应用程序,第三方库和Java运行时,存储要求约为32 MB,而不是通常的(*)〜300 MB。 另外,运行该应用程序所需的RAM也将减少25%。

(*)这些是以下完整JDK(不包括应用程序和第三方库)的存储要求:

jdk.8.0_191        360 MB
jdk-9.0.4          504 MB
adoptopenjdk-11    298 MB

使用支持微服务的ORM

大多数传统的ORM不支持Java模块封装。 通常,这需要交付大量不必要的代码。

在本文中,我将使用开源的基于Stream的Java ORM Speedment ,它的最新版本支持Java Platform Module System(JPMS)。 这使我们能够仅使用我们的应用程序显式使用的模块来生成优化的自定义Java运行时环境(JRE,来自JDK的部分,用于运行应用程序)。

阅读关于Speedment 3.2中的新功能, 这篇文章 。

应用程序

我们希望在本文中部署的整个应用程序位于
GitHub上的开源项目,位于子目录“ microservice-jlink ”下。 它连接到托管在云中MySQL“ Sakila”数据库(包含有关电影的数据)的公共实例,并在控制台上列出了十个最长的被评为“ PG-13”的电影。 数据模型已预先配置为适合此数据库的数据结构。 如果要使用另一个数据库创建自己的应用程序,请访问Speedment初始化程序以专门为该数据库配置项目。

该应用程序的main方法如下所示:

public final class Main {public static void main(String[] args) {final Speedment app = new SakilaApplicationBuilder().withPassword("sakila").build();final FilmManager films = app.getOrThrow(FilmManager.class);System.out.println("These are the ten longest films rated as PG-13:");films.stream()                          // 1.filter(Film.RATING.equal("PG-13")) // 2.sorted(Film.LENGTH.reversed())     // 3.limit(10)                          // 4.map(film -> String.format(         // 5"%-18s %d min",film.getTitle(),film.getLength().orElse(0))).forEach(System.out::println);      // 6}
}

首先,我们将数据库密码传递给Speedment构建器(Speedment从不在内部存储密码)。 使用配置文件中的数据库IP地址,端口等对构建器进行了预配置。

然后,我们获得FilmManager ,该FilmManager器随后可用于创建直接与数据库中“ film”表相对应的Java流。

最后,我们:

  1. 创建Film实体Stream
  2. 筛选出评级等于“ PG-13”的Film实体
  3. 以相反的长度顺序对剩余的影片进行排序(最长的优先)
  4. 将视频流限制为前10部电影
  5. 将每个电影实体映射到具有电影标题和电影长度的String
  6. 将每个String打印到控制台

该应用程序本身非常易于理解。 还应注意,Speedment将在后台显示Java Stream到SQL:

SELECT `film_id`,`title`,`description`,`release_year`,`language_id`,`original_language_id`,`rental_duration`,`rental_rate`,`length`,`replacement_cost`,`rating`,`special_features`,`last_update`
FROM `sakila`.`film`
WHERE (`rating` = ? COLLATE utf8_bin)
ORDER BY `length`IS NOT NULL, `length` DESC LIMIT ?,
values:[PG-13, 10]

这意味着仅从数据库中提取了所需的电影实体。

直接在IDE下运行时,将产生以下输出:

These are the ten longest films rated as PG-13:
GANGS PRIDE        185 min
CHICAGO NORTH      185 min
POND SEATTLE       185 min
THEORY MERMAID     184 min
CONSPIRACY SPIRIT  184 min
FRONTIER CABIN     183 min
REDS POCUS         182 min
HOTEL HAPPINESS    181 min
JACKET FRISCO      181 min
MIXED DOORS        180 min

这看起来很完美。

模块化项目

要使用模块,我们需要在Java 9或更高版本下运行,并且在我们的项目中必须有一个module-info.java文件:

module microservice.jlink {requires com.speedment.runtime.application;requires com.speedment.runtime.connector.mysql; // (*)
}

com.speedment.runtime.application模块是任何Speedment应用程序始终需要的基本模块。

(*)根据数据库类型,您必须将MySQL模块替换为数据库的相应模块。 在此处阅读有关各种数据库连接器模块的所有信息。

建设项目

如前所述,完整项目可在GitHub上获得 。 这是您如何获得的:

git clone https://github.com/speedment/user-guide-code-samples.git

将目录更改为相关的子项目:

cd user-guide-code-samples
cd microservice-jlink

生成项目(由于模块系统,您必须使用Java 9或更高版本):

mvn clean install

自定义JRE构建脚本

该项目还包含一个名为build_jre.sh的自定义JRE构建脚本, build_jre.sh包含以下命令:

#!/bin/bash
SPEEDMENT_VERSION=3.2.1
JDBC_VERSION=8.0.18
OUTPUT=customjre
echo "Building $OUTPUT..."
MODULEPATH=$(find ~/.m2/repository/com/speedment/runtime -name "*.jar" \| grep $SPEEDMENT_VERSION.jar | xargs echo | tr ' ' ':')
MODULEPATH=$MODULEPATH:$(find ~/.m2/repository/com/speedment/common -name "*.jar" \| grep $SPEEDMENT_VERSION.jar | xargs echo | tr ' ' ':')
MODULEPATH=$MODULEPATH:$(find . -name "*.jar" | xargs echo | tr ' ' ':')$JAVA_HOME/bin/jlink \
--no-header-files \
--no-man-pages \
--compress=2 \
--strip-debug \
--module-path "$JAVA_HOME\jmods:$MODULEPATH" \
--add-modules microservice.jlink,java.management,java.naming,java.rmi,java.transaction.xa \
--output $OUTPUT

该脚本是这样工作的:

在设置了各种参数之后,该脚本通过添加speedment/runtimespeedment/common目录的jar来构建模块路径。 即使我们添加了所有这些模块,模块系统也会在以后找出实际使用的模块,并丢弃其他模块。 MODULEPATH的最后一行将添加应用程序本身的JAR文件。

设置完所有参数后,我们将调用jlink命令,该命令将构建自定义JRE。 我使用了许多(可选)标志来减小目标JRE的大小。 因为JDBC驱动程序不支持JPMS,所以我在--add-modules参数下手动添加了驱动程序所需的一些模块。

构建超紧凑型JRE

有了以上脚本,我们可以使用一个命令为我们的云数据库应用程序创建超紧凑的自定义JRE:

./build_jre.sh

在我较旧的MacBook Pro上,构建仅需大约5秒钟。 我们可以使用以下命令查看JRE / app的总大小:

du -sh customjre/

这将产生以下输出:

32M customjre/

惊人的结果! 我们有一个功能齐全的JVM,其中包含垃圾回收,JIT编译器,所有库(JDBC驱动程序除外)以及应用程序本身仅包装在32 MB的存储空间中!

我们可以将它与JDK本身的未缩减大小进行比较,后者通常被用作云实例的基准。

du -sh $JAVA_HOME

这将在我的笔记本电脑上产生以下输出:

298M /Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home/

而且该数字甚至不包括应用程序或任何第三方库。 因此,我们将存储需求降低了大约10倍!

实际使用的模块

要查看通过简化过程实现了哪些模块,我们可以发出以下命令:

cat customjre/release

这将在我的机器上产生以下输出(为了清晰起见,经过重新格式化和排序):

JAVA_VERSION="11.0.5"
MODULES="
com.speedment.common.annotation
com.speedment.common.function
com.speedment.common.injector
com.speedment.common.invariant
com.speedment.common.json
com.speedment.common.jvm_version
com.speedment.common.logger
com.speedment.common.mapstream
com.speedment.common.tuple
com.speedment.runtime.application
com.speedment.runtime.compute
com.speedment.runtime.config
com.speedment.runtime.connector.mysql
com.speedment.runtime.core
com.speedment.runtime.field
com.speedment.runtime.typemapper
com.speedment.runtime.welcome
java.base
java.logging
java.management
java.naming
java.prefs
java.rmi
java.security.sasl
java.sql
java.transaction.xa
java.xml
microservice.jlink
"

因此,自定义运行时未包括所有未使用的Java模块(例如javax.crypto )。

运行应用程序

可以使用自定义JRE运行该应用程序,如下所示:

customjre/bin/java --class-path ~/.m2/repository/mysql/mysql-connector-java/8.0.18/mysql-connector-java-8.0.18.jar -m microservice.jlink/com.speedment.example.microservices.jlink.Main

首次构建项目时(即mvn clean install ),Maven自动将文件mysql-connector-java-8.0.18.jar下载到其本地存储库中。 由于MySQL JDBC驱动程序尚不兼容Java平台模块系统,因此我们不得不手动将其粘上。

运行时,该程序会产生与上面相同的输出,但是运行时会小10倍:

These are the ten longest films rated as PG-13:
GANGS PRIDE        185 min
CHICAGO NORTH      185 min
POND SEATTLE       185 min
THEORY MERMAID     184 min
CONSPIRACY SPIRIT  184 min
FRONTIER CABIN     183 min
REDS POCUS         182 min
HOTEL HAPPINESS    181 min
JACKET FRISCO      181 min
MIXED DOORS        180 min

内存使用情况

一个可能更重要的问题是云应用程序总共使用了多少应用程序内存(RSS)。 快速浏览一下,发现堆内存使用量也减少了:

标准JDK

Pers-MBP:speedment pemi$  jmap -histo 38715num     #instances         #bytes  class name (module)
-------------------------------------------------------1:         25836        3036560  [B (java.base@11.0.5)2:          2055        1639408  [I (java.base@11.0.5)3:          4234         511568  java.lang.Class (java.base@11.0.5)4:         21233         509592  java.lang.String (java.base@11.0.5)5:           196         270552  [C (java.base@11.0.5)6:          4181         245400  [Ljava.lang.Object; (java.base@11.0.5)7:          4801         153632  java.util.concurrent.ConcurrentHashMap$Node (java.base@11.0.5)8:          3395         135800  java.util.LinkedHashMap$Entry (java.base@11.0.5)
…
1804:             1             16  sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo (jdk.localedata@11.0.5)
Total        137524        7800144

自定义JRE

Pers-MBP:speedment pemi$  jmap -histo 38783 | headnum     #instances         #bytes  class name (module)
-------------------------------------------------------1:         22323        1714608  [B (java.base@11.0.5)2:          4229         511000  java.lang.Class (java.base@11.0.5)3:         19447         466728  java.lang.String (java.base@11.0.5)4:          1776         424408  [I (java.base@11.0.5)5:            69         264656  [C (java.base@11.0.5)6:          4044         240128  [Ljava.lang.Object; (java.base@11.0.5)7:          4665         149280  java.util.concurrent.ConcurrentHashMap$Node (java.base@11.0.5)8:          3395         135800  java.util.LinkedHashMap$Entry (java.base@11.0.5)
…
1726:             1             16  sun.util.resources.LocaleData$LocaleDataStrategy (java.base@11.0.5)
Total        102904        5727960

堆改善

堆使用量从7,800,144字节减少到5,727,960字节(减少了25%以上)!

注意:在运行jmap命令之前,我让应用程序建议一个显式的垃圾收集器,并等待几秒钟,以消除由可能早期调用垃圾收集器引起的任何差异。

总览

以下图表显示了存储需求的差异(越低越好):


这是另一个显示RAM使用率差异的图表(越低越好):


修改代码

如果要修改代码,则需要使用以下内容来重建应用程序:

mvn clean install

然后删除旧的customjre并创建一个新的:

rm -rf customjre/
./build_jre.sh

创建自己的数据库应用程序

如果要连接到自己的数据库并要编写自己的应用程序逻辑,则可以轻松地选择要使用的表和列,然后使用Speedment Tool自动生成自己的Java域模型和应用程序构建器:

本文演示的项目中使用的Speedment工具。

可以将该工具添加到pom.xml文件中的项目中,并由调用
mvn speedment:tool 。 访问Speedment Initializer生成您自己的自定义pom.xml文件和应用程序模板。

可以通过自动Maven构建脚本简化该过程,该脚本将识别任何应用程序依赖项以及自动生成的Docker实例,这些实例可以在自动构建后立即部署。 我将在以后的文章中写更多有关此的内容。

结论

Java平台模块系统(JPMS)允许构建适用于云部署的高度优化的JRE。

可以减少存储和RAM需求。

传统的ORM不支持完整的Java模块封装

Speedment开源Stream ORM支持JPMS,可用于构建高效的数据库云应用程序。

资源资源

JPMS模块的基础知识

在GitHub上加速

Speedment Initializer能够生成项目pom.xml模板

翻译自: https://www.javacodegeeks.com/2019/11/java-how-to-create-lightweight-database-microservices.html

java 轻量级文件数据库

java 轻量级文件数据库_Java:如何创建轻量级数据库微服务相关推荐

  1. java调用webservice_笃学私教:Java开发网站架构演变过程-从单体应用到微服务架构详解...

    原标题:笃学私教:Java开发网站架构演变过程-从单体应用到微服务架构详解 Java开发网站架构演变过程,到目前为止,大致分为5个阶段,分别为单体架构.集群架构.分布式架构.SOA架构和微服务架构.下 ...

  2. java event sourcing_使用Spring Cloud和Reactor在微服务中实现EventSourcing -解道Jdon

    使用Spring Cloud和Reactor在微服务中实现Event Sourcing 当在微服务架构中构建应用时,状态管理成为分布式系统的问题,相比于传统monolithic应用,将状态管理通过事务 ...

  3. java图片保存文件到数据库_java保存图片内容到数据库

    本文使用mysql数据库举例插入图片到数据库和从数据库取出图片在页面显示: 一.建表 创建一个测试保存图片的表 create table t_save_img( name varchar(200), ...

  4. java生成文件夹_java 创建文件夹和文件 汇总

    前提 D盘存在文件夹a,文件D:/a/b/c 不存在 1.默认file.exists().file.isFile().file.isDirectory() 均返回 false 2.使用file.cre ...

  5. java生成文件夹_java 文件和文件夹的创建

    File类的常见方法 1.创建. boolean createNewFile(); //创建文件 boolean mkdir();创建文件夹 boolean mkdirs();创建多级文件夹. 2.删 ...

  6. java web文件夹_JAVA WEB项目文件夹上传下载解决方案

    这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时候,向后端传入参数:当前为第几块文件,和分片总数 下面直接贴代码吧,一些难懂的我大部分都加上注释了: 上传文件实体类: 看得 ...

  7. java io文件操作_java IO 文件操作方法总结

    java IO 文件操作方法总结 对于输入输出的理解: 输入输出,以程序为参考点,外部数据进入程序,通过输入流完成.程序将数据给外部设备,通过输出流完成. 文件Io的操作 //获取文件 File fi ...

  8. java大文件解析_java大文件(百M以上)的上传下载实例解析

    javaweb上传文件 上传文件的jsp中的部分 上传文件同样可以使用form表单向后端发请求,也可以使用 ajax向后端发请求 1.通过form表单向后端发送请求 Save 改进后的代码不需要for ...

  9. java底层 文件操作_JAVA的文件操作【转】

    11.3 I/O类使用 由于在IO操作中,需要使用的数据源有很多,作为一个IO技术的初学者,从读写文件开始学习IO技术是一个比较好的选择.因为文件是一种常见的数据源,而且读写文件也是程序员进行IO编程 ...

  10. java zip 文件夹_Java Zip文件文件夹示例

    java zip 文件夹 Today we will look into java zip file example. We will also compress a folder and creat ...

最新文章

  1. 依赖注入?依赖注入是如何实现解耦的?
  2. 图灵奖得主杨立昆:人工智能比你更聪明吗?
  3. linux系统内存执行elf的多种方式
  4. Spring Cloud开发实践 - 04 - Docker部署
  5. 90. Leetcode 剑指 Offer 62. 圆圈中最后剩下的数字 (动态规划-基础题)
  6. 牛客题霸 NC12 重建二叉树
  7. [html] 怎样禁用页面中的右键、打印、另存为、复制等功能?
  8. 旅游解说系统 VS 旅游信息系统
  9. 01_决策树案例一:鸢尾花数据分类
  10. 了解:shell脚本+脚本优化+脚本注入+正则表达式
  11. 2022-2-20stream流的复习
  12. 使用arecord、aplay 实现录音和播放
  13. iTunes无法验证服务器s.mzstatic.com的身份 服务器证书无效 解决办法
  14. 中序遍历二叉树-Java实现
  15. 生成所有的ALTERs,将所有MyISAM表转换为InnoDB
  16. SQL数据库“正在恢复”,解决和查看方法
  17. 有源电力滤波器APF仿真模型,实验平台,基于dsp28335
  18. 租金多少才算合理?智能分析工具Sophon帮你预测房屋租金
  19. (xml+flash)flash播放器代码!
  20. 路径规划算法——RRTStar

热门文章

  1. Little Boxes UVALive - 8209
  2. K - Triangle 计蒜客 - 42405
  3. P4457-[BJOI2018]治疗之雨【期望dp,高斯消元】
  4. P5488-差分与前缀和【NTT,生成函数】
  5. P4556,jzoj3397-[GDOI2014模拟]雨天的尾巴【树链剖分,线段树】
  6. P3076,jzoj3187-的士【贪心】
  7. nssl1231-Gift【01背包,dp】
  8. 【结论】只不过是长的领带(luogu 6877)
  9. 【dfs】栅栏的木料(2012特长生 T4)
  10. 【贪心】国王游戏(ybtoj 贪心-1-4)