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模块封装。 通常,这需要交付大量不必要的代码。

在本文中,我将使用基于流的开源Java ORM Speedment ,它的最新版本支持Java平台模块系统(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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/340627.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

垃圾分类毕设java程序_垃圾“拍一拍”,分类不用愁!生活垃圾分类查询小程序上线啦...

垃圾种类太多?分类容易搞混?乐清人 注意啦,拿起手机就能查!11月6日,生活垃圾分类查询系统登陆乐清市综合行政执法局官方微信公众号,输入垃圾名称即可快速了解垃圾所属哪一类,还有拍照识别查询&a…

带有Prometheus的弹簧靴和千分尺第5部分:旋转Prometheus

以前,我们获得了Spring Boot Application适配器,以便为Prometheus公开端点。 该博客将重点介绍如何设置和配置Prometheus,以便为Spring Boot端点提供服务器。 因此,让我们开始使用docker来启动Prometheus服务器。 在继续进行Pr…

允许跨域访问_PHP设置多域名允许跨域访问

php中文网最新课程 每日17点准时技术干货分享 针对 PHP 语言设置多域名允许跨域访问 服务器变量: 服务器变量存储在 $_SERVER 数组中,在这个数组中有一个特殊的键值:HTTP_ORIGIN。 这个键只在跨域的时候才会存在值,同源时为空字符串 响应头设置允许某域名访问:access-cont…

python函数的作用降低编程复杂度_Python函数式编程

lambda本文将介绍Python中函数式编程的特性。在对函数式编程的概念有了了解后,本文会介绍iterators和generators等语言特性,还有itertools和functools等相关的库。函数式编程本章节将会介绍函数式编程的一些基本概念;如果只是对Python的语言特…

Apache Camel 3.1 –即将推出更多骆驼核心优化

希望一切都很好,您可以安全进入2020年。 Camel团队已经在忙于开发下一个Camel 3.1版本。 目标之一是继续优化骆驼核心,这一次我们花了一些时间来寻找路由引擎中的一些热点。 我们所研究的方面之一也是在Camel路由的每个消息中发生的对象分配。 JVM本身…

判断字符为空_算法题:字符串转换整数 (atoi)

题目描述题解分析他人更优解一、题目描述二、题解import math class Solution:def myAtoi(self,str):str str.strip() #去除字符串两边的空格if len(str) 0: return 0 #如果字符串为空返回0if not str[0].isdigit() and str[0] ! - and str[0] ! : #判断第一个字符是…

python 3.5.2设计页面_怎么解决win10系统搭建Python 3.5.2开发环境的处理方案

今天小编告诉大家如何对win10系统搭建Python 3.5.2开发环境进行设置,可能很多用户都不知道怎么对win10系统搭建Python 3.5.2开发环境进行设置,但当我们遇到对win10系统搭建Python 3.5.2开发环境进行设置的问题怎么办呢?遇到这种情况不要着急&…

Eclipse系列的隐藏宝藏-2019年版

Eclipse Collections是一个开放源代码Java Collections框架。 在此博客中,我将演示该框架的五个鲜为人知的功能。 我在去年的Java Advent Calendar中发布了一个类似的博客 。 请参阅博客末尾的资源以获取有关该框架的更多信息。 1. countBy() :要查找特…

mongodb一致性协议_mongo的怎么保持事物的一致性-问答-阿里云开发者社区-阿里云...

http://docs.mongoing.com/manual-zh/tutorial/perform-two-phase-commits.html要么操作全都执行,要么都不执行,不能执行一半,改了几条数据了,看哎哟好像不对,那扔着吧。Consistency 在数据库领域的意思跟在分布式系统…

picturectrl控件中加载图片并显示_在 CRA 中使用 webp 图片提升加载性能

webp 是 google 提倡的一种新的 image 格式,意在为 web 提供体积更小的图片格式。通常情况下,无损压缩可以减小 25%-35% 的体积(有例外情况,反而会增大体积,但是是因为转换图片格式不兼容引起的)&#xff0…

怎么打开网卡rss_RSS 进阶篇:Huginn - 真·为任意网页定制 RSS 源(PhantomJs 抓取)...

定制网页RSS源主要有FEED43和Huginn两种方法。FEED43:简单免费,六小时抓取一次,每次抓取20条静态页面。使用攻略- RSS 入门篇:FEED43&FeedEx-为静态网页定制 RSS 源2. Huginn:自由度高,可设定抓取频率、…

编写junit 测试_编写JUnit测试的另一种方法(Jasmine方法)

编写junit 测试最近,我为一个小型个人项目编写了很多Jasmine测试。 我花了一些时间才终于感到正确地完成了测试。 在此之后,当切换回JUnit测试时,我总是很难过。 由于某种原因,JUnit测试不再那么好,我想知道是否有可能…

python4 什么时候_Python4要来了?快来看看Python之父怎么说

大家好,我是菜鸟哥,今天跟大家一起聊一下Python4的话题!从2020年的1月1号开始,Python官方正式的停止了对于Python2的维护。Python也正式的进入了Python3的时代。而随着时间的发展,关于Python4的发布也逐渐的成为了大家…

python类成员变量_Python 类变量和成员变量

Python 类变量和成员变量类与对象的方法我们已经讨论了类与对象的功能部分,现在我们来看一下它的数据部分。事实上,它们只是与类和对象的名称空间 绑定 的普通变量,即这些名称只在这些类与对象的前提下有效。有两种类型的 域 ——类的变量和对…

JDK 14 – JEP 361从预览中切换表达式

在我以前的文章中 ,我写了有关作为JDK 12的预览功能发布的开关表达式和相关增强功能的信息。随后,在JDK 13中提出了一些更改,例如使用yield关键字从switch块返回值并在预览中发布。 在即将于明年3月在GA上发布的即将发布的JDK 14版本中&…

输入一个正整数求所有素数因子_一个数如果恰好等于它的因子之和,这个数就称为完数。编写应用程序求1000以内所有的完数...

运行截图&#xff1a;代码import java.util.*;public class wanshu {public static void main(String args[]) {int sum 0,i,j,k,m 0;System.out.println(" 完数有&#xff1a;");for( j 2; j < 1000 ; j){for ( i 2 ; i < j; i){if( j%i 0) //此判…

安卓禁用硬件加速_Android硬件加速详解

从Android3.0(API Level 11)开始&#xff0c;支持硬件加速&#xff0c;可充分利用GPU的特性&#xff0c;使得界面渲染更加平滑。但是硬件加速自身并非完美&#xff0c;在某些Webview版本上&#xff0c;比如Android5初期的一些rom上的Webview版本是chrome37、38版本&#xff0c;…

mac svn工具_程序员或产品经理,这些Mac的效率工具一定不要错过

工欲善其事必先利其器!用好工具能很大的提高我们的工作效率&#xff0c;尤其是程序员和产品经理等。今天给大家介绍一些好用的工具随时记下闪现的灵感人的一天中大脑会产生大约6万个想法, 其中有不少优秀的 idea. 如果我们能学会捕捉哪怕是部分灵感, 也将会收获巨大. 因此工作中…

案例 github_github 项目搜索技巧-让你更高效精准地搜索项目

作者&#xff1a;Suwanbinwww.cnblogs.com/suwanbin/p/12113751.htmlgithub 搜索技巧参考自 B站 up 主 CodeSheep 的视频【如何高效地在网上找开源项目做&#xff01;在职程序员实际演示一波视频教程操作】&#xff0c;然后写着写着一好奇就去看文档了现在这篇博客相当于官方文…

使用Spring和JSR 303进行方法参数验证

Spring提供了一种使用JSR 303 bean验证来验证方法参数的简便方法。 在这篇文章中&#xff0c;我们将看到如何使用此功能。 设定 首先&#xff0c;我们需要通过创建MethodValidationPostProcessor bean添加对方法参数验证的支持&#xff1a; Configuration public class MyCon…