我们想进行实验,微服务看看Java微服务是微服务否可以像Go微服务一样快速运行。 业界普遍认为Java是微服务"老的","慢的微服务"和"无聊的"。 Go是微服务"快速","新"和"酷"。微服务 但是微服务我们想知道这些特性是否得到实际性能数据的保证或支持。 我们想要一个公平的微服务测试,所以我们创建了一个非常简单的微服务微服务,没有外部依赖项(例如数据库),微服务并且代码路径非常短(仅处理字符串)。微服务 我们确实包含了指标和日志记录,微服务因为它们似乎总是微服务包含在任何实际的微服务中。 我们使用了小型轻量级的微服务框架(Helidon for Java和Go-Kit for Go),并且还尝试了Java的微服务纯JAX-RS。 我们尝试了不同版本的Java和不同的JVM。 我们对堆大小和垃圾收集器进行了一些基本调整。源码库 我们在测试运行之前对微服务进行了预热。 Java的历史 Java由Sun Microsystems开发,后来被Oracle收购。 其1.0版本于1996年发布,最新版本是2020年的Java15。主要设计目标是Java虚拟机和字节码的可移植性以及带有垃圾回收的内存管理。 它仍然是最流行的语言之一(根据StackOverflow和TIOBE之类的来源),它是在开源中开发的。 让我们谈谈" Java问题"。 多年来,Java有许多不同的垃圾收集算法,包括串行,并行,并发标记/清除,G1和新的ZGC垃圾收集器。 现代垃圾收集器旨在最大程度地减少垃圾收集"停止世界"暂停的时间。 Oracle实验室开发了一种新的名为GraalVM的Java虚拟机,服务器租用该Java虚拟机用Java编写,具有新的编译器和一些令人兴奋的新功能,例如能够将Java字节码转换为无需Java VM即可运行的本机映像。 Go的历史 Go由Google的Robert Griesemer,Rob Pike和Ken Thomson创建。 Go受C,Python,Javascript和C的影响。 它被设计为用于高性能网络和多处理的最佳语言。 在我们演讲时,StackOverflow有27,872个被" Go"标记的问题,而Java则为1,702,730。 Go是一种静态类型的编译语言。 Go是许多CNCF项目的首选语言,例如Kubernetes,Istio,Prometheus和Grafana都(大部分)用Go编写。 它旨在具有快速的构建时间和快速的执行。 Go(与Java相比)有什么好处-根据我的亿华云计算经验,这是我的个人看法: 那么,Go的"问题"是什么? 负载测试方法 我们使用JMeter进行负载测试。 测试多次调用服务,并收集有关响应时间,吞吐量(每秒事务)和内存使用情况的数据。 对于Go,我们收集常驻集大小;对于Java,我们跟踪本机内存。 在许多测试中,我们将JMeter与被测应用程序在同一台计算机上运行。 如果我们在另一台机器上运行JMeter,结果似乎没有任何干扰或差异,因此可以简化设置。 当我们以后将应用程序部署到Kubernetes中时,JMeter在集群外部的远程计算机上运行。 在进行测量之前,我们使用了1,000次服务调用来预热了应用程序。 应用程序本身的源代码以及负载测试的定义都在以下GitHub存储库中: https://github.com/markxnelson/go-java-go 第一轮测试 在第一轮中,我们在"小型"计算机上进行了测试,在这种情况下,该计算机是2.5GHz双核Intel Core i7笔记本电脑,具有16GB RAM,运行macOS。 结果如下: 我们宣布Go成为第一轮的获胜者! 以下是我们根据这些结果得出的观察结果: GraalVM本机映像 GraalVM具有本机映像功能,可让您采用Java应用程序并将其本质上编译为本机可执行代码。 该可执行文件包括应用程序类,其依赖项中的类,运行时库类以及JDK中的静态链接本机代码。 这是再次添加GraalVM本机图像测试(使用GraalVM EE 20.1.1-JDK 11构建的本地图像)的第一轮结果: 在这种情况下,与在JVM上运行应用程序相比,使用GraalVM本机映像没有看到吞吐量或响应时间的任何显着改善,但是内存占用空间较小。 以下是一些测试的响应时间的图表: > Response time graphs for round one 请注意,在所有这三种Java变体中,第一个请求的响应时间要长得多(请在与左轴相对的右上方寻找那条蓝线)。 第二轮 接下来,我们决定在更大的计算机上运行测试。 与第一轮一样,我们使用了100个线程,每个线程10,000个循环,10秒的启动时间以及相同版本的Go,Java,Helidon和GraalVM。 结果如下: 我们宣布GraalVM本机映像是第二轮的赢家! 以下是这些测试的响应时间图: > Response times for test runs with logging enabled but no warmup > Response times for test runs with no logging and no warmup > Response times for test runs with warmup but no logging 第二轮的一些观察: 第三轮-Kubernetes 在第三轮中,我们决定在Kubernetes集群中运行应用程序—您可能会说,这是微服务的更自然的运行时环境。 在这一轮中,我们使用了具有三个工作节点的Kubernetes 1.16.8集群,每个工作节点都有两个内核(每个都有两个执行线程),14GB的RAM和Oracle Linux 7.8。 在某些测试中,我们为每个变体运行了一个Pod,在其他测试中运行了100个Pod。 应用程序访问是通过Traefik入口控制器进行的,其中JMeter在Kubernetes集群外部运行,以进行某些测试,对于其他测试,我们使用ClusterIP并在集群中运行JMeter。 与之前的测试一样,我们使用了100个线程,每个线程10,000个循环,以及10秒的启动时间。 以下是每个变体的容器大小: 结果如下: 以下是一些响应时间表: > Response times from Kubernetes tests 在这一轮中,我们观察到Go有时会更快,而GraalVM本地映像有时会更快,但是两者之间的差异很小(通常小于5%) 那我们学到了什么? 我们对所有这些测试和结果进行了反思,以下是一些结论: 接下来是什么? 这是一个非常有趣的练习,我们打算继续努力,特别是: