
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.二中新功能, 这篇文章。
应用程序
本文中部署的整个应用程序位于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流。
最后,我们:
- 创建
Film
实体Stream
- 筛选评级等于筛选评级 PG-13”的
Film
实体 - 剩余的电影按相反的长度排序(最长优先)
- 前10部电影限制了流量
- 将每个电影实体映射到电影标题和电影长度上
String
- 将每个
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 ? 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/runtime
和speedment/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 38715
num #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 | head
num #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域模型和应用程序构建器:
可以将该工具添加到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安装