当前位置: 首页 > news >正文

go java对比_Java微服务 vs Go微服务,究竟谁更强?

这是我最近一直在思索的一个问题。

去年8月份的the Oracle Groundbreakers Tour 2020 LATAM大会上,Mark Nelson和Peter Nagy就对此做过一系列基础的的测试用以比较。接下来就给大家介绍下。

在程序员圈子里,普遍的看法是Java 老、慢、无聊 ,而Go是 快、新、酷

为了尽可能地进行一个相对公平的测试,他们使用了一个非常简单的微服务,没有外部依赖关系(比如数据库),代码路径非常短(只是操纵字符串),使用了小型的、轻量级的框架(Helidon for Java和Go工具包for Go),试验了不同版本的Java和不同的jvm。

对决双雄

我们先来看下擂台两边的选手:

身穿深色战服的选手是 JAVA

Java是由被甲骨文收购的Sun Microsystems开发的。它的1.0版本是1996年发布的,最新的版本是2020年的Java15。主要的设计目标是Java虚拟机和字节码的可移植性,以及带有垃圾收集的内存管理。它是全世界最流行的语言之一,在开源环境下开发。

我们先看下JAVA的问题,大家普遍认为它最大的问题就是速度慢,已经慢到让人觉得不再是合理的,而是更具历史意义的。不过这么多年来,Java诞生了很多不同的垃圾收集算法用来加快它运行的速度。

Oracle实验室最近已经开发了一个新的Java虚拟机GraalVM,它有一个新的编译器和一些令人兴奋的新特性,比如能够将Java字节码转换成一个本机映像,可以在没有javavm的情况下运行等。

而它的对手就是年轻充满活力的 GO

GO是由谷歌的罗伯特·格里默、罗伯·派克和肯·汤姆森创建的。他们对UNIX、B、C、Plan9、UNIX窗口系统等做出了重大贡献。GO是开源的,在2012年发布了1.0版本(比JAVA晚了16年),在2020年发布了1.15版本。无论是在采用方面,还是在语言和工具生态系统本身方面,它都在快速增长。

GO受C、Python、JavaScript和C++等多种语言的影响。被设计成高性能网络和多处理的最佳语言。

StackOverflow有27872个带“Go”的问题,而Java只有1702730个。足见长江后浪推前浪。

Go是一种静态类型的编译语言。它又称为goroutines的轻量级进程(这些不是OS线程),它们之间有独特的通信通道(类型化的,FIFO)。Go是许多CNCF项目的首选语言,例如Kubernetes、Istio、Prometheus和Grafana

赛前对比

从个人感觉来说,Go相比JAVA来说,优点在于:

Go更容易实现复合、纯函数、不变状态等功能模式。

Go处于生命周期的早期,因此它没有向后兼容性的沉重负担—Go仍然可以轻易打破某些限制来改进。

Go编译成一个本机静态链接的二进制文件-没有虚拟机层-二进制文件拥有运行程序所需的一切,这对于“从头开始”的容器来说非常好。

Go体积小、启动快、执行快(目前是的)

Go没有OOP,继承,泛型,断言,指针算法

Go写法上较少的括号

Go没有循环依赖、没有未使用的变量或导入、没有隐式类型转换的强制

Go样板代码少得多

缺点是:

Go工具生态系统还不成熟,尤其是依赖关系管理——有几个选项,没有一个是完美的,特别是对于非开源开发;仍然存在兼容性挑战。

构建具有新的/更新的依赖项的代码非常慢(比如Maven著名的“下载Internet”问题)

导入将代码绑定到存储库,这使得在存储库中移动代码成为一场噩梦。

调试、评测等仍然是一个挑战

用到了指针

需要实现一些基本的算法

没有动态链接

没有太多旋钮来调优执行或垃圾收集、概要文件执行或优化算法。

比赛开始

使用JMeter来运行负载测试。这些测试多次调用这些服务,并收集有关响应时间、吞吐量(每秒事务数)和内存使用情况的数据。对于Go,收集驻留集大小;对于Java,跟踪本机内存。

在测量之前,使用1000次服务调用对应用程序进行预热。

应用程序本身的源代码以及负载测试的定义都在这个GitHub存储库中: https://github.com/markxnelson/go-java-go

第一回合

在第一轮测试中,在一台“小型”机器上进行了测试,是一台2.5GHz双核Intel core i7笔记本电脑,16GB内存运行macOS。测试运行了100个线程,每个线程有10000个循环,上升时间为10秒。Java应用程序运行在JDK11和Helidon2.0.1上。使用Go 1.13.3编译的Go应用程序。

结果如下:

96ad61a0cc189f552320d21aeec62f3c.png
e1840e098fb4808b80645913be6dab8b.png

可以看出,第一回合是Go赢了!

JAVA占的内存太多了;预热对JVM有很大的影响—我们知道JVM在运行时会进行优化,所以这是有意义的

在第一回合的基础上,意犹未尽的又引入GraalVM映像以使 Java 应用程序的执行环境更接近于 Go 应用程序的环境,添加了 GraalVM 映像测试(用 GraalVM EE 20.1.1ー JDK 11构建的本机映像)的结果是:

c63c16a09b650181e1fae909a4d83ffe.png
9615885750f1274654ffa091c8656684.png

通过使用 GraalVM 映像在 JVM 上运行应用程序,我们没有看到吞吐量或响应时间方面的任何实质性改进,但是内存占用的确变小了。

下面是一些测试的响应时间图:

941cb5064b4c4a2d917f8aa4139b1e5b.png

第二回合

在第二轮测试中,使用一台更大的机器上运行测试。36核(每个核两个线程)、256GB内存、运行oraclelinux7.8的机器。

和第一轮类似,使用了100个线程,每个线程使用了10,000个循环,10秒的加速时间,以及相同版本的 Go,Java,Helidon 和 GraalVM。

结果如下:

3946c1c76684e8e752fde5c6d0275ab7.png

这一回合是GraalVM 映像赢了!

下面是一些测试的响应时间图:

51f109d43fd05406abe7ed8d92bf8e44.png
276315df898ca1dd3864660d535e4261.png
a13cacf28dd2e5762850bfb7104499dc.png

在这个测试中,Java变体的表现要好得多,并且在没有使用Java日志记录的情况下,它的性能大大超过了Go。Java似乎更能使用硬件提供的多核和执行线程(与Go相比)。

这一轮的最佳表现来自GraalVM native image,平均响应时间为0.25毫秒,每秒事务数为82426个,而Go的最佳结果为1.59毫秒和39227个tps,然而这是以多占用两个数量级的内存为代价的!

GraalVM映像比在jvm上运行的同一应用程序快大约30–40%!

第三回合

这次,比赛在Kubernetes集群中运行这些应用程序,这是一个更自然的微服务运行时环境。

这次使用了一个Kubernetes 1.16.8集群,它有三个工作节点,每个节点有两个内核(每个内核有两个执行线程)、14GB的RAM和oraclelinux7.8。

应用程序访问是通过Traefik入口控制器进行的,JMeter在Kubernetes集群外运行,用于一些测试,而对于其他测试,使用ClusterIP并在集群中运行JMeter。

与前面的测试一样,我们使用了100个线程,每个线程使用了10,000个循环,以及10秒的加速时间。

下面是各种不同容器的大小:

Go 11.6MB 11.6 MB

Java/Helidon 1.41GB 1.41 GB

Java/Helidon JLinked 150MB 150mb

Native image 25.2MB 25.2 MB

结果如下:

b766255935f0abca7a11fff6eca4e917.png

下面是一些测试的响应时间图:

cd3cd8aaa164bd422c4bf2423e0d35f8.png

在这一轮中,我们观察到 Go 有时更快,GraalVM 映像有时更快,但这两者之间的差别很小(通常小于5%)。

Java似乎比Go更善于使用所有可用的内核/线程—我们在Java测试中看到了更好的CPU利用率。Java性能在拥有更多内核和内存的机器上更好,Go性能在较小/功能较弱的机器上更好。在一台“生产规模”的机器上,Java很容易就和Go一样快,或者更快

相关文章:

  • 万兆单模模块_华为万兆单模模块 OEM光模块 全面兼容OSX010000
  • mysql查询重复记录中最新的一条_MySQL查询重复数据(删除重复数据保留id最小的一条为唯一数据)...
  • yum mysql centos7_Centos7 yum安装 mysql
  • mysql隔离级别命令_MySQl事务隔离级别(命令及简单理解)
  • mysql更改隔离级别_MySQL修改事务隔离级别的暗门
  • mysql alter user语法_MySQL 最基本的语法/语句
  • percona mysql 同步_Percona MySQL5.6 半同步复制
  • mysql-FONT备份数据库_mysql-FONT备份数据库
  • mysql 批量替换表前缀_如何批量修改mysql的表前缀名称
  • mysql datadir 目录权限不够_MySQL数据目录更改及相关问题解决方案
  • windows mysql开启慢查询日志_mysql开启慢查询日志的方法
  • jsp数据添加乱码mysql_JSP插入MySQL数据库中文乱码问题解决
  • python切片赋值_Python中实现:变量和变量赋值的几种形式
  • linux shell mysql 遍历_shell 脚本中获取mysql多个字段的值
  • mysql current read_浅谈MySQL之 REPEATABLE-READ.
  • 【node学习】协程
  • 【技术性】Search知识
  • 2017前端实习生面试总结
  • Android系统模拟器绘制实现概述
  • Date型的使用
  • ECMAScript入门(七)--Module语法
  • FineReport中如何实现自动滚屏效果
  • flask接收请求并推入栈
  • Go 语言编译器的 //go: 详解
  • JAVA并发编程--1.基础概念
  • java多线程
  • Laravel 菜鸟晋级之路
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • Vue2.x学习三:事件处理生命周期钩子
  • 反思总结然后整装待发
  • 分享几个不错的工具
  • 精彩代码 vue.js
  • 爬虫模拟登陆 SegmentFault
  • 前端性能优化--懒加载和预加载
  • 如何用vue打造一个移动端音乐播放器
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 通过npm或yarn自动生成vue组件
  • 为什么要用IPython/Jupyter?
  • 优化 Vue 项目编译文件大小
  • 在Docker Swarm上部署Apache Storm:第1部分
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • #NOIP 2014#Day.2 T3 解方程
  • #控制台大学课堂点名问题_课堂随机点名
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (rabbitmq的高级特性)消息可靠性
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (汇总)os模块以及shutil模块对文件的操作
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (算法)N皇后问题
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .NET CF命令行调试器MDbg入门(一)
  • .NET 发展历程
  • .Net各种迷惑命名解释
  • .net使用excel的cells对象没有value方法——学习.net的Excel工作表问题
  • .NET下ASPX编程的几个小问题