Java微服务 vs Go微服务,究竟谁更强!?

程序猿DD 2021-01-14 15:57:46
java 服务 vs 微服


前言

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应用程序。

结果如下:

file

file

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

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

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

file

file

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

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

file

第二回合

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

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

结果如下:

file

这一回合是GraalVM 映像赢了!

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

file

file

file

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

结果如下:

file

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

file

在这一轮中,我们观察到 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学习之路!另每周赠书不停哦~

版权声明
本文为[程序猿DD]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/didispace/p/14277702.html

  1. Centos7 one click installation of JDK1.8 shell script
  2. Mounting of file system in Linux (centos7)
  3. How does serverless deal with the resource supply demand of k8s in the offline scenario
  4. Detailed explanation of HBase basic principle
  5. Spring security oauth2.0 authentication and authorization 4: distributed system authentication and authorization
  6. Redis performance Part 5 redis buffer
  7. JavaScript this keyword
  8. Summary of Java multithreading (3)
  9. Sentry(v20.12.1) K8S 云原生架构探索, SENTRY FOR JAVASCRIPT 手动捕获事件基本用法
  10. Sentry(v20.12.1) K8S 云原生架构探索, SENTRY FOR JAVASCRIPT 手动捕获事件基本用法
  11. (10) Spring from the beginning to the end
  12. Summary of Java multithreading (2)
  13. Spring source notes! From the introduction to the source code, let you really understand the source code
  14. A stormy sunny day
  15. Zookeeper (curator), the implementation of distributed lock
  16. Show the sky! Tencent T4's core Java Dictionary (framework + principle + Notes + map)
  17. Spring boot project, how to gracefully replace the blank value in the interface parameter with null value?
  18. Spring boot project, how to gracefully replace the blank value in the interface parameter with null value?
  19. docker+mysql集群+读写分离+mycat管理+垂直分库+负载均衡
  20. docker+mysql集群+读写分离+mycat管理+垂直分库+负载均衡
  21. To what extent can I go out to work?
  22. Java 使用拦截器无限转发/重定向无限循环/重定向次数过多报错(StackOverflowError) 解决方案
  23. Implementation of rocketmq message sending based on JMeter
  24. How to choose the ticket grabbing app in the Spring Festival? We have measured
  25. Implementation of rocketmq message sending based on JMeter
  26. My programmer's Road: self study java
  27. My programmer's Road: self study java
  28. All in one, one article talks about the use of virtual machine VirtualBox and Linux
  29. All in one, one article talks about the use of virtual machine VirtualBox and Linux
  30. Java 使用拦截器无限转发/重定向无限循环/重定向次数过多报错(StackOverflowError) 解决方案
  31. [Java training project] Java ID number recognition system
  32. How does serverless deal with the resource supply demand of k8s in the offline scenario
  33. Detailed explanation of HBase basic principle
  34. Explain the function of thread pool and how to use it in Java
  35. Kubernetes official java client 8: fluent style
  36. 010_MySQL
  37. Vibrant special purchases for the Spring Festival tiktok section, hundreds of good things to make the year more rich flavor.
  38. 010_MySQL
  39. Of the 4 million docker images, 51% have high-risk vulnerabilities
  40. Rocketmq CPP client visual studio 2019 compilation
  41. Rocketmq CPP client visual studio 2019 compilation
  42. Usage of data custom attribute in jquery
  43. Common decompression in Linux
  44. Upload large files in Java
  45. Sentry (v20.12.1) k8s cloud native architecture exploration, sentry for JavaScript manual capture event basic usage
  46. Sentry (v20.12.1) k8s cloud native architecture exploration, sentry for JavaScript manual capture event basic usage
  47. Docker + MySQL Cluster + read / write separation + MYCAT Management + vertical sub database + load balancing
  48. Docker + MySQL Cluster + read / write separation + MYCAT Management + vertical sub database + load balancing
  49. Java use interceptor infinite forwarding / redirection infinite loop / redirection times too many error (stack overflow error) solution
  50. Java use interceptor infinite forwarding / redirection infinite loop / redirection times too many error (stack overflow error) solution
  51. 010_ MySQL
  52. 010_ MySQL
  53. Fast integration of imsdk and Huawei offline push
  54. 消息队列之RabbitMQ
  55. Rabbitmq of message queue
  56. 初学java进制转换方面补充学习
  57. Learn java base conversion supplementary learning
  58. 了解一下RPC,为何诞生RPC,和HTTP有什么不同?
  59. 了解一下RPC,为何诞生RPC,和HTTP有什么不同?
  60. 初学java进制转换方面补充学习