热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java寻找峰值峰谷_云原生的Java与Golang

PhotobyRaquelMartnezonUnsplashJava曾经著名的座右铭:一次编写并在任何地方运行如今已经过时了,我们想要运行代码的唯
02fcbbe92e1e08317af830935291b566.png

> Photo by Raquel Martínez on Unsplash

Java曾经著名的座右铭:"一次编写并在任何地方运行"如今已经过时了,我们想要运行代码的唯一地方是在容器内。 "及时"编译器没有任何意义。

由于这个原因,Java生态系统可能正处于其转型之中,以便更好地适应云。 Oracle的GraalVm允许将字节代码编译为Linux可执行文件(ELF)和Rad Heat的Quarkus以及其他框架,以使其像引导一个反应应用程序一样容易。 Quarkus还以Netty和Vertx.x为核心来构建非常有效的响应式Web服务。

389f6689c6bc5f9cbb2d840cd0b64439.png

> quarkus official performance stats

Java编译为可执行的二进制文件,可在毫秒内启动,并且占用的内存很小。 这可以利用Java生态系统,甚至可以用其他JVM语言(例如Scala和Kotlin)编写!

听起来好得令人难以置信……

如果您不相信,可以使用在线项目生成器或通过使用maven插件在本地生成项目来玩Quarkus。

另一方面,Golang诞生于云中,当在容器中运行时,没有留下任何负担。 它被认为是云的编程语言。 从第一天开始,小型二进制文件,快速启动程序,较小的内存占用量就可以了。 并且被广泛采用。 对Java世界的严峻挑战。

Java有机会吗? 只有时间证明一切。 但是,出于好奇,我想将Java云原生服务与golang同类服务在性能和开发经验方面进行比较。

在这篇文章中,我将强调两项服务。 比较他们的CPU,RAM,延迟和正常运行时间。 这些服务将在具有相同资源分配的容器中启动,并且Apache基准测试将使他们汗流sweat背。

对于我的案例研究来说,这是一个"足够好"的基准,因为我不认为找到最佳/最差的基准结果,而是比较在相同环境下执行的两个基准。

场景

两种服务都将连接到在另一个容器中运行的MySQL数据库,该容器具有一个表和三行。

1b71ad78ee8229ac0d196cf79ec847db.png

> the database

每个服务将获取所有三行,将其转换为域对象,然后编写JSON数组响应。

Apache基准测试将运行10K请求,并发级别为100,这是quarkus JVM版本的两倍(还用于测试"冷" /"热" JVM))

b90e998c610a6ca231adc6622edfa3ec.png

> the apache benchmark command

Golang服务

使用称为gin的流行的反应式Web框架,该框架具有出色的基准。

在寻找golang非阻塞MySQL驱动程序时,我一无所获,互联网上建议同时使用go-sql-driver,这就是我要使用的。

golang样式非常明确。 一个在你脸上的态度。 主要功能启动服务器,配置请求处理程序,并打开数据库连接。

构建本机go可执行文件
5d9df717557eedcf3fb933f5e7b2ca1a.png

> Easy and fast build process. The only tool I had to use was the go compiler. No hustle at all.

Kotlin Cloud本机服务— Quarkus

这是一个Kotlin示例,大致遵循quarkus反应式MySql扩展指南。

82b82b828dca52f7d783bdb2c54228b7.png

> datasource configuration

与go版本相比,存在一些隐式东西,CDI依赖注入,使用javax注释的声明性路由,自动配置解析以及数据源/连接创建/服务器引导程序。 但这是使用框架的代价,它为您带来繁重的工作,并决定了它的工作方式。 但是,它比go版本要短得多,只要我不介意黑魔法就行!

底层有一个Netty反应式Web服务器,由Vert.x多事件循环包装,而Vert.x反应式MySQL驱动程序可以通过一个线程处理多个数据库连接。

另外,我可以使用Kotlin令人惊叹的收藏库来折叠一个列表,其中go版本还没有泛型(但即将推出),也没有丰富的标准收藏库,我不得不手动编写或生成它。

构建Java本机可执行文件
773c987464574fd619f6d11a871be35a.png

> It took 4 minutes, partly because Gradle executes the native image compilation inside a Linux Graa

基本上,我能够弄清楚构建本机可执行文件的容器中发生的事情是SubstrateVM。 设计为可提前编译的可嵌入虚拟机链接到我们的代码,并作为一个单元进行编译。 甲骨文表示,这是惊人的,但并非没有代价,SubstrateVM的优化次数少于HotSpot Vm,并且垃圾回收器更简单。

执行此操作的编译器称为" Graal",它与语言无关,在使用Java字节码之前,需要先将其翻译为中间表示形式,即Truffle语言。 这非常有趣,可以在这篇文章中找到有关Graal和Truffle的详尽解释。

构建Java本机图像看起来更加复杂,速度较慢,并且生成的二进制文件几乎是文件的两倍。 但这有效! 与一个Java Uber(胖)Jar相比,35M可执行二进制文件实际上是什么,它可以轻松地大十倍。 35MB甚至可以放在aws lambda中。

强调服务

我正在使用以下设置在本地计算机上运行所有测试:

5acfabad96df13407add2bdc5b1a1dcd.png

不适使用:

MacBook Pro(15英寸,2017年)

2.9 GHz Intel Core i7(8核)

16 GB 2133 MHz LPDDR3

不适使用名为cAdvisor的工具来监视我的容器的状态。

场景

· quarkus jvm热点容器

· quarkus java本机容器

· golang容器

每个都分配了以下资源

· 100MB / 0.5 CPU | 200MB / 1个CPU | 300MB / 2个CPU

我对……感兴趣

· cpu / ram利用率(多核的利用率)

· cpu / ram峰值

· cpu / ram空闲

· 引导时间

· 响应潜伏时间平均值/最大值

· 吞吐量(每秒请求数)

现在,我将运行许多基准测试,并为每个基准收集许多数据点。 如果有太多信息,请随时跳至摘要结尾

github repo以及该实验的所有代码都可以在这里找到

quarkus jvm热点— 100MB / 0.5 CPU

· 闲置CPU使用率0.25%

· 空闲ram使用情况66MB

· 自举时间6s

93977637915ef25a1bc1ae0516584e26.png

> CPU usage during bootstrap. ( a spike , probably jit + launching JVM )

第一轮压力测试(Cold JVM)

令人惊讶的是,没有失败的请求。

5ceba6b3ade7ee3e9565bfbce3671d70.png

> CPU usage during stress.

ca62e531508fb93d791973f6047604cc.png

> RAM launched from 60 to almost 100 MB (limit) and stayed there.

第2轮压力测试(温暖的JVM)

quarkus jvm热点— 200MB / 1个CPU

· 闲置CPU使用率0.13%

· 空闲ram使用情况66MB

· 引导时间3s

06babec123c303afbd7c2a8f76cf8bec.png

> CPU usage during bootstrap. ( a spike again )

第一轮压力测试(Cold JVM)

88d963abdcdd4c10eea22ade3a1394a5.png

> CPU / RAM usage under stress

af39b728221248b96f9a661db132802b.png

> Surprisingly the JVM did not eat all the allocated 200MB and 140MB was sufficient

第2轮压力测试(温暖的JVM)

quarkus jvm热点— 300MB / 2 CPU

· 空闲cpu / ram与以前的方案相同

· 引导时间1.1s(NICE)

3d3f3b562eb5171b1bf0b6db68ac02ab.png

> CPU usage during bootstrap, a spike again.

第一轮压力测试(Cold JVM)

9fbcfeb7274f955736a0f1114b8e2790.png

> Good CPU utilzation

eab388cd8944495f85683923a7e49f53.png

> 142 mb ram was sufficient

第2轮压力测试(温暖的JVM)

现在,让我们看看本地图像将如何执行。

quarkus Java Native — 100MB / 0.5 CPU

· 引导时间:0.125s。 (!!!)

· 启动时没有CPU高峰

3eb6bce39e3a2fa19823c94674a2bbd8.png

> cpu / ram during bootstrap

压力测试结果

5eec9c8fa9be7c02f848aea2cf429deb.png

> CPU reached 0.5 limit as expected

672852fdb48349de160b97f94b498d68.png

> Good ram usage, 19MB active memory. WOW

quarkus Java Native — 200MB / 1个CPU

· 即时引导(0.0125s)

· 4空闲ram用法

· 在压力下使用19种内存

· 100%的CPU使用率

· 启动时没有CPU高峰

检测结果

quarkus Java Native — 300MB / 2 CPU

没提升。

golang — 100MB / 0.5 CPU

· 空闲CPU 0

· 闲置内存2.3MB(不错)

· 引导时间:几分之一秒

· 启动时没有CPU高峰

结果有点歪斜。 由于某种原因,一小部分请求需要大约7秒钟才能完成。

当再次尝试运行测试以查看偏斜结果是否能够再现测试时,实际上是否已将其压碎!

运行时错误:无效的内存地址或nil指针取消引用。 嗯…可能是我做错了什么? 似乎go-sql库中存在错误。 如文档所述,从表中读取的代码是100%,并且99%的时间都可以工作。 这不应该发生。

golang — 200MB / 1个CPU

我不断收到运行时错误。 可疑总是在测试结束时。 但是,go-mysql驱动程序的校正不是主要问题,因此在完成90%的请求后手动终止测试。

压力下的CPU / RAM使用率

c902c29b60411c93c5fdb9b7c5b4d1ff.png

> cpu utilization during stress

6bcb8bc9e54e00f1ef8c3ac2206679d7.png

> RAM usage during stress. 12.27MB, very nice.

golang — 300MB / 2个CPU

没有明显的改善,所有统计数据几乎相同。 CPU利用率低于1.0。 我不知道为什么go不能充分利用更多的内核,有趣的是……可能是因为该过程受IO约束,或者可能是杜松子酒需要手动配置才能更好地利用多个内核。

摘要
5541484039b783b6976003c43e1ccf48.png

> aggregated stats ( warm jvm/native image | golang )

似乎Quarkus已准备好投入生产,它允许简单的JVM /本机发行版/开发模式,并允许在本地运行本机测试。 而且,只要您不使用反射或JNI,就可以安全地配置GraalVM。 否则,您将必须自己配置graal编译器,并且也有针对此的现有解决方案。

延迟和吞吐量

golang和云原生Java均产生了相似的结果,尽管平均而言稍微偏爱golang服务。 但是,java本机结果更加稳定。 Golang服务有时会在1.25µs内做出响应,而很少在7s内做出响应。

"预热"后的JVM产生了良好的结果,但比本机或go版本差。

CPU利用率

当给定的内核少于单核时,go和native-java在负载下均表现不佳,而在使用2个内核启动时,它们并没有表现出明显的改进。 可能是因为工作负载受IO限制。 或者因为gin / Netty的默认配置没有考虑多个内核。

另一方面,JVM利用了赋予它的所有内核,并在各个方面提高了性能。

RAM使用

压力很大,java本机为40MB,golang服务为24MB。 两种情况都不错,尽管golang版本使用的ram几乎少了两倍。

JVM在压力下使用了140MB。 完全是官方的quarkus统计信息。 对于JVM来说一点都不差,但是几乎是golang版本的6倍。

引导时间

golang和云原生Java均会立即启动,而JVM版本则需要几秒钟(取决于分配的CPU),并在启动时产生CPU峰值。

开发经验

这更是一个宗教问题,而不是一个实际问题。如此病态,请谨慎回答。 Quarkus创建Java世界中非常熟悉的抽象(例如基于注释的DI)。它为您启动服务并创建连接池。可以使用丰富的收藏标准库和泛型。但是,这种感觉有点像黑魔法,一旦停止工作,您会感到无助。此外,将Java代码编译为本地二进制文件并不是那么简单,您必须意识到其中的局限性和注意事项,尽管Red Hat在扩展方面取得了很大的进步,但并非每个Java库都将与本地编译兼容。 。 (预先配置为本地编译的Java库)。使用与本机编译不兼容的库(例如Guice)将需要您手动配置Graal VM。这是可能的,但并非像使用广口瓶那样直接。 Quarkus和Graal VM也"相对"新。因此,有许多冒险等待着。但由于是双模式(JVM或本机)。万一本机版本停止工作,总会有一个退路,这是解决任何新出现问题的好方法。

另一方面,Golang仅在现在(存在10年后)才承认需要泛型。 当然,它不喜欢隐性事件的继续。 从很多方面来说,这都是好事。 另外,尽管go社区在追赶方面确实做得很好,但是可用的工具和库却更少(例如,只有一个流行的阻塞MySQL驱动程序)。 另一方面,它的编译和构建过程非常快速/简单。 每个golang软件包都将为您工作,而不受Java本地平台引入的限制。

结论

Java成为云原生,Golang并没有像JVM那样过度地执行它,这是非常好的。 我相信它将来会被广泛使用。 但是golang绝对可以打架。

因此,请谨慎选择!

而且不要忘了给仙人掌浇水

(本文翻译自Igor Domrev的文章《Cloud-Native Java vs Golang》,参考:https://medium.com/swlh/cloud-native-java-vs-golang-2a72c0531b05)



推荐阅读
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
  • 本文介绍了将mysql从5.6.15升级到5.7.15的详细步骤,包括关闭访问、备份旧库、备份权限、配置文件备份、关闭旧数据库、安装二进制、替换配置文件以及启动新数据库等操作。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了StartingzookeeperFAILEDTOSTART相关的知识,希望对你有一定的参考价值。下载路径:https://ar ... [详细]
  • CentOS 6.5安装VMware Tools及共享文件夹显示问题解决方法
    本文介绍了在CentOS 6.5上安装VMware Tools及解决共享文件夹显示问题的方法。包括清空CD/DVD使用的ISO镜像文件、创建挂载目录、改变光驱设备的读写权限等步骤。最后给出了拷贝解压VMware Tools的操作。 ... [详细]
author-avatar
wiggin
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有