性能比拼: Go vs Java
本内容是对着名性能评测博主 Anton Putra Go (Golang) vs Java: Performance Benchmark 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准在本视频中,我们将比力 Go 和 Java。
我们将基于 Golang 的 Fiber 框架和 Java 的 Spring Boot 创建几个简单的应用程序,并利用 Prometheus 将它们摆设到 Kubernetes。我们将从 Nginx Ingress 控制器收集耽误和流量信息。
为了收集基本的容器指标,比方 CPU 利用率,我们将摆设 cAdvisor 作为一个守护进程集(DaemonSet)。您可以监控 CPU 利用率,既可以看作是分配给容器限定的百分比,也可以是实际利用的 CPU 核心数,并将请求(requests)和限定(limits)以线的形式绘制出来。在 Kubernetes 中,由于利用了 cgroups,丈量 CPU 节流(throttling)至关紧张,由于它会极大地影相应用程序的性能。
同样的情况也实用于内存。我们可以将其可视化为百分比,大概利用实际利用量,并标注请求(requests)和限定(limits)。监控 Nginx Ingress Pod 的 CPU 利用率也至关紧张,至少需要关注这一点,由于它大概成为您应用程序的瓶颈,并显著增加耽误。
我们还将利用原生的 Prometheus 客户端来检测(instrument)我们应用程序的部分代码。比方,在这个仪表板中,我们将丈量 S3 调用的请求连续时间和 MongoDB 插入操纵的耗时。
由于我们将利用一个基于开源 MinIO 项目的自托管 S3 解决方案,我认为用 Prometheus 对其进行监控也是一个好主意。我们还将在 Kubernetes 中摆设 MongoDB,并利用 Prometheus exporter 对其进行监控。
这些技术不仅对基准测试有效,对于一样平常运维也很有资助。您可以在我的 GitHub 堆栈中找到源代码。
首先,我们将利用 Terraform 创建 VPC 和 EKS。然后,为了在 VPC 内暴露我们的应用程序,我们将利用 Helm chart 和 Terraform 摆设一个私有的 Nginx Ingress 控制器。接着,将 Go 语言和 Java 应用程序摆设到 Kubernetes。
https://i-blog.csdnimg.cn/img_convert/780fade4ad52fad92c36d73af0c92ca9.png
对于第一个测试,我们简单地利用 k6 负载测试工具来并排比力 Fiber 和 Spring Boot 应用程序。
对于第二个更贴近实际的测试,在每次请求中,我们将从 S3 存储桶下载一张图片,并将末了修改日期保存到 MongoDB 数据库。
现在,让我们来看一下代码。首先,您可以在 AWS 环境中找到用于创建所有网络组件和 EKS 的 Terraform 代码。然后,我们有 Prometheus 和其他监控组件。比方,MinIO 可以或许开箱即用地天生 Prometheus 指标。而要监控 MongoDB,我们需要单独摆设 Prometheus exporter。
对于第一个测试,我们只需向客户端返回 10 个设备信息。Java 的实现也一样。在这里,我额外加入了一个 Prometheus 计数器变量,以防您想统计这个端点被调用了多少次。
对于第二个测试,在 Go 语言中,我们有一个 getImage Fiber 处置惩罚器(Handler),它利用 download 函数从 S3 存储桶拉取 S3 图片,并利用 save 函数将末了修改日期插入到 MongoDB。为了共享 S3 客户端和 MongoDB 连接池,我们创建了一个自界说的处置惩罚器,并添加了 session 和 client 属性。然后,在初始化处置惩罚器时,我们调用辅助方法来创建与 S3 和 MongoDB 的连接。您不必共享 S3 客户端,但每次访问 S3 时,它都会重新进行身份验证,这也会消耗时间。
https://i-blog.csdnimg.cn/img_convert/8a648e78da6f0e517c75fced58956034.png
谈到 Prometheus 指标,首先,我们需要在一个布局体(struct)中声明它们。然后创建一个 newMetrics 函数来初始化它们。在这个测试中,我利用了 summary 范例,这对于单个副本来说是没问题的,而且您不必预先设定时间间隔桶(interval buckets)。但是,假如您操持程度扩展此应用程序,您将无法聚合 summary 范例;请改用 histogram 范例来记载观测值。您可以如许做来记载观测值:简单地在函数调用之前和之后记载时间,大概,您当然可以利用中间件模式来包装这个函数,这取决于您。
对于 Java,您遵循相同的原则。声明指标,在这个例子中,我有 S3 和 MongoDB 的连续时间指标,并利用它们来记载观测值。对于 Java,您需要添加一些依赖项,以允许您利用 Prometheus 指标。要暴露 Prometheus 端点,您可以利用 application.yaml 设置,大概只是在代码中利用 setProperty 手动启用它。
末了,让我们看一下第一个测试场景。我们将从 1 个虚拟用户开始,在 5 分钟内缓慢扩展到 100 个用户。然后立刻将用户数增加到 500 个,并保持 5 分钟。再过 5 分钟后,将用户扩展到 3000 个,直到其中一个应用程序失败。
第二个测试类似,我们只是减少了客户端数量,并利用了不同的端点。
我还必须提到,Java 现在具有容器支持,可以直接从 cgroup 获取限定。然而,有些人仍旧建议手动设置最小和最大堆巨细(Min and Max Heap size),而且那些 Java 的最大和最小内存百分比(Java Max and Min RAM percentages)非常令人困惑。
让我们开始运行第一个测试。正如您大概预期的那样,在这个简单的测试中,Java 的 CPU 利用率和内存利用率远高于 Go。
https://i-blog.csdnimg.cn/img_convert/ce2bab6e599fdfd76df90417abe3e503.png
当我们达到约莫每秒 600 次请求时,Java 根本无法处置惩罚它们并拒绝了请求。这在接下来的测试中会有所改变。
https://i-blog.csdnimg.cn/img_convert/ed78f26327731fee77e059393626a7ff.png
在这个包含详细 CPU 利用率的仪表板中,您可以看到 Java 进程受到了相称严峻的节流(throttled)。
这是内存利用情况,在整个测试期间,Java 和 Go 的内存利用都保持安稳。
https://i-blog.csdnimg.cn/img_convert/a79bb710a0a3794fe9a023c2d62e3751.png
每次利用 Ingress 时,您必须至少监控 Ingress 控制器的 CPU 利用率。假如它们没有足够的资源,大概会导致耽误大幅增加,特别是当您利用 Nginx Ingress 的默认 Helm chart 时。
https://i-blog.csdnimg.cn/img_convert/254122f76d72b2842f7b3a07eb870497.png
在测试结束时,您可以找到 Java 和 Go 的 P95 和 P90 耽误。
让我们运行第二个测试,即下载图片并保存末了修改日期。在开始时,您可以看到与第一个测试相同的模式:Java 的 CPU 利用率更高。但当请求达到每秒 20 次时,差别显著缩小。到测试结束时,当我们增加用户数量时,Go 语言的 CPU 现在变得更高了,这让我感到惊讶,而且耽误也急剧上升。
https://i-blog.csdnimg.cn/img_convert/2b20737d9479fdd91d1ea824c0fce051.png
需要说明的是,这些测试仅仅代表了真实世界的场景,它们在比力语言本身方面大概不是很正确,由于我们利用了大量的外部库。但是,当您在生产环境中运行应用程序时,它们可以向您展示实际的差别。从 DevOps 的角度来看,这比斐波那契(Fibonacci)测试紧张得多。
假如您发现任何错误,请告诉我,以便我可以在下一个视频中修复它们。感谢您的观看,我们下个视频再见。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]