前言

Java微服务能像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应用程序。

结果如下:

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

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

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

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

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

第二回合

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

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

结果如下:

这一回合是GraalVM 映像赢了!

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

在这个测试中,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

结果如下:

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

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

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

最后

接下来会做更多的测试比赛,来看一看究竟谁更好!有兴趣的你也可以自己试一试,记得告诉我们结果哦!

本文参考:https://medium.com/helidon/can-java-microservices-be-as-fast-as-go-5ceb9a45d673

欢迎关注我的公众号:程序猿DD,获得独家整理的免费学习资源助力你的Java学习之路!另每周赠书不停哦~

Java微服务 vs Go微服务,究竟谁更强!?的更多相关文章

  1. java springboot activemq 邮件短信微服务,解决国际化服务的国内外兼容性问题,含各服务商调研情况

    java springboot activemq 邮件短信微服务,解决国际化服务的国内外兼容性问题,含各服务商调研情况 邮件短信微服务 spring boot 微服务 接收json格式参数 验证参数合 ...

  2. Java生鲜电商平台-微服务架构概述

    Java生鲜电商平台-微服务架构概述 单体架构存在的问题 在传统的软件技术架构系统中,基本上将业务功能集中在单一应用内,或者是单一进程中.尽管现代化的软件架构理论以及设计原则已推广多年,但实际技术衍化 ...

  3. Java生鲜电商平台-微服务入门与服务的拆分架构实战

    Java生鲜电商平台-微服务入门与服务的拆分架构实战 刚开始进入软件行业时还是单体应用的时代,前后端分离的概念都还没普及,开发的时候需要花大量的时间在“强大”的JSP上面,那时候SOA已经算是新技术了 ...

  4. java架构之路-(微服务专题)初步认识微服务与nacos初步搭建

    历史演变: 以前我们都是一个war包,包含了很多很多的代码,反正我开始工作的时候做的就是这样的项目,一个金融系统,代码具体多少行记不清楚了,内部功能超多,但是实际能用到的不多,代码冗余超大,每次部署大 ...

  5. java架构之路-(微服务专题)ribbon的基本使用和内部算法的自我实现

    上次回归: 上次我们主要说了,我们的注册中心nacos的使用,如我们的命名空间.分组.集群.版本等是如何使用的,如果是这样呢?我们现在有三个用户服务和三个订单服务,我们应该如何分发这些请求呢?都请求到 ...

  6. java框架之SpringCloud(1)-微服务及SpringCloud介绍

    微服务概述 是什么 业界大牛 Martin Fowler 这样描述微服务: 参考[微服务(Microservices)-微服务原作者Martin Flower博客翻译]. 下面是关于上述博客中的部分重 ...

  7. java架构之路-(微服务专题)feign的基本使用和nacos的配置中心

    上次回归: 上次我们说了ribbon的基本使用,包括里面的内部算法,算法的细粒度配置,还有我们自己如何实现我们自己的算法,主要还是一些基本使用的知识,还不会使用ribbon的小伙伴可以回去看一下上一篇 ...

  8. 【转】为什么选择Spring Boot作为微服务的入门级微框架

    本文为普元云计算高级工程师许二虎在普元云计算架构设计群的微课堂分享.如需加入普元新一代数字化企业云平台研发设计群参与微课堂.架构设计与讨论直播,请直接回复此公众号:"加群 姓名 公司 职位 ...

  9. Chris Richardson微服务翻译:微服务部署

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现 微服务之事件驱动的数据管理 微服务部署( ...

  10. Chris Richardson微服务翻译:微服务架构中的服务发现

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现(本文) 微服务之事件驱动的数据管理 微服 ...

随机推荐

  1. 【SAP业务模式】之ICS(二):基础数据

    讲完业务,计划在前台做一下ICS的基本操作,不过在操作之前,得先建立好基本的基础数据. 1.首先创建接单公司LEON,对应工厂是ADA: 2.创建生产公司MXPL,对应工厂是PL01: 3.创建接单公 ...

  2. Android 使用 ksoap2-android 访问WebService(C#)

    Android 客户端与后台数据交互的方式有很多种.今天这里记录一下,与WebService的数据交互. 新建一个简单的WebService 创建方式如下: 创建好的项目是这样的. 我们在里面写几句简 ...

  3. Oracle普通索引,唯一索引,主键的区别

    索引是我们经常使用的一种数据库优化手段,适当的业务操作场景使用适当的索引方案,可以显著的提升系统整体查询性能,当然用户体验也随之提高. 在Oracle中,唯一性索引(Unique Index)是我们经 ...

  4. java中set和get方法的理解

    对于JAVA初学者来说,set和get这两个方法似乎已经很熟悉了,这两个方法是JAVA变成中的基本用法,也是出现频率相当高的两个方法. 为了让JAVA初学者能更好的理解这两个方法的使用和意义,今天笔者 ...

  5. canvas图表详解系列(1):柱状图

    本章建议学习时间4小时 学习方式:详细阅读,并手动实现相关代码(如果没有canvas基础,需要先学习前面的canvas基础笔记) 学习目标:此教程将教会大家如何使用canvas绘制各种图表,详细分解步 ...

  6. 初学Python——进程

    什么是进程? 程序不能单独执行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的过程就叫做进程.进程是操作系统调度的最小单位. 程序和进程的区别在于:程序是储存在硬盘上指令的有序集合,是 ...

  7. 通过 sass-resources-loader 全局注册 Sass/Less 变量

    使用webpack引入sass/less全局变量 sass或者less都提供变量设置,在需求切换主题的项目中使用less或者sass变量,只要修改变量值,编译后所有用到该变量的样式都会被修改为你想要的 ...

  8. java常见3种文件上传速度对比和文件上传方法详细代码

    在java里面文件上传的方式很多,最简单的依然是FileInputStream.FileOutputStream了,在这里我列举3种常见的文件上传方法代码,并比较他们的上传速度(由于代码是在本地测试, ...

  9. Kubernetes--kubectl

    一.Kubectl命令行说明 类型 命令 描述 基础命令 create  通过文件名或标准输入创建资源 expose  将一个资源公开为一个新的kubernetes服务 run 创建并运行一个特定的镜 ...

  10. 160227、javascript特效

    1.给网页设定快捷键 js: function getkey(){     event = event || window.event;     url = "www.baidu.com&q ...