java与go接口接入性能对比测试

344 阅读4分钟

前言

在应用开发的过程中,经常会有接口组合包装、代理访问等“网关”类需求。个人理解这类应用含有较少的业务逻辑,作为“胶水层”承担非标对接工作。由于业务逻辑较少的特性,基本是拼装、转发,通常都不存在性能瓶颈。但是在比如图片网关这类高频访问静态资源的场景,CPU、内存、网络都有可能会遇到瓶颈。所以就有了这个选题,测试一下接口的性能。

测试方案

日常业务都是用java进行开发,但是一提到性能,java也是饱受诟病。所以此次测试加入一个对比对象“go”,用实际场景对比一下性能差异,没有对比就没有伤害。接口性能利用Jmeter对接口进行并发访问测试。
为了模拟更真实的场景,接口性能测试完成后,通过模拟工具->java版demo->go版demo这个调用链路,模拟典型的网关转发场景。

编写Demo程序

用2种语言编写一个简单的接口,包含2个参数,接口定义如下:

image.png

Java版

使用主流的spring boot框架编写,核心代码如下:

    @PostMapping("/write")  
    public String write(HttpServletRequest request) throws IOException, ServletException {  
        MultipartHttpServletRequest params = (MultipartHttpServletRequest) request;  
        String token = params.getParameter("token");  
        Part part = request.getPart("data");  
        long size = part.getSize();  
        return String.valueOf(size);
    }

http请求使用httpclient工具类,配置了连接池。图片通过InputStream接收后调用上传,图片不做转存。

go版

使用高性能的web框架gin编写,核心代码如下:

package main

import "github.com/gin-gonic/gin"

func main() {
	r := gin.Default()
	r.MaxMultipartMemory = 8 << 20
	r.POST("/write", func(c *gin.Context) {
		token := c.PostForm("token")
		file, _ := c.FormFile("data")
		c.JSON(200, file.Size)
	})
	r.Run() // 监听并在 0.0.0.0:8080 上启动服务
}

Jmeter测试

Jmeter是常用的接口测试工具,如果使用apifox进行接口管理和测试,在自动化测试用例中可直接导出Jmeter格式,在Jmeter中直接导入即可,使用很方便。可能部分读者对Jmeter还不熟悉,此处详细介绍一下Jmeter的使用方法。

1>下载安装

通过Jmeter下载对应版本的程序。Jmeter是用java编写的带GUI的工具,启动后界面如下:

2>配置测试计划

  1. 添加测试计划
  2. 添加测试线程组
  3. 添加Http请求(配置IP、端口、请求参数)
  4. 添加结果树(查看单条请求结果)
  5. 添加汇总报告(查看性能数据)

详细使用参考全网最全最细的jmeter接口测试教程以及接口测试流程详解

3>执行测试

对线程属性进行配置,线程数可以按照模拟的并发用户数进行配置,我个人电脑通常配置不超过1000,受限硬件性能和网络端口数,线程数不能无限大。Ramp-up period在简单测试场景可直接配置为0,如果线程数比较多,可以设定启动秒数,避免线程启动初期大量异常数据。可以简单根据接口请求耗时线程数接口请求耗时*线程数进行估算,比如接口耗时0.02s,线程数200,此处即可设置为4。

image.png

4>测试结果解读

主要是看平均耗时和QPS2项指标。 image.png

测试结果

测试环境说明
操作系统:win10
CPU:单核3.1GHz
内存:16G
单机测试,使用回环地址调用,排除了网络影响

测试结果表-直接请求

样例版本QPS平均耗时CPU内存
5K图片java33757580%680M
5K图片go27657130%43M
500K图片java18552470%490M
500K图片go63915125%149M

测试结果表-级联调用

样例版本QPS平均耗时CPU内存
5K图片java169123543%790M
500K图片java93105725%748M

级联调用场景未读取InputStream流,直接通过InputStream流请求,节省内存

非严格比对测试,仅简单取样对比,QPS与平均耗时未刻意选取数值,记录大致平稳后的数据

结论

本文目的不是为了对比不同语言、框架的极限性能差异,所以代码编写方法没有做特殊性能优化,测试方法设定也比较粗糙。主要目的还是为了介绍一种辅助日常开发调优的测试方法,通过简单的工具和方法,可以低成本的模拟大规模、大数据的业务场景。通过测试发现性能瓶颈点,然后再做针对性的调优。

  1. go相比java确实有明显性能优势
  2. Java确实比较吃资源,在日常优化中可多关注内存使用
  3. JMeter配置不同的线程数,测试结果有明显差异。在组合调用开发场景,做队列控制并发请求数,反而可以使整体性能提升