Swagger生成API文档及Postman测试请求

6/7/2021 SwaggerPostman压力测试

# 1. Swagger生成接口文档

# 1.1 Swagger2是什么

前后端分离后,维护接口文档基本上是必不可少的工作。Swagger2是一个开源工具,可以在开发过程使用注解生成接口文档。这个接口文档可以直接在上面请求接口。

项目地址:https://github.com/swagger-api/swagger-ui (opens new window)

Swagger

# 1.2 Swagger2基本使用

# 1.2.1 整合Swagger2

创建一个Springboot项目,加入web依赖,然后再加入两个Swagger2相关的依赖,如下:

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>
1
2
3
4
5
6
7
8
9
10

Swagger2的配置也是比较容易的,配置类示例如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class Swagger2Config {

    @Bean
    public Docket controllerApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(new ApiInfoBuilder()
                        .title("API接口文档")
                        .version("版本号:1.0")
                        .build())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.xxx.xxx.controller"))
                .paths(PathSelectors.any())
                .build();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

此时启动项目,输入http://localhost:8080/swagger-ui.html即可看到接口文档。

说明:如果Swagger启动时报错Unable to scan documentation context default,无法显示Swagger文档,可能是因为开启了分组模式。

在 SwaggerConfig 中加入@Bean 注解,就是启用了分组模式,如果都没有 @Bean 就是默认模式。默认模式访问 /v2/api-docs 直接可以获取到所有的 json 数据。

另注:Swagger去掉basic-error-controller,在该配置文件后面再加一个bean即可。

    @Bean
    public Docket demoApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.regex("(?!/error.*).*"))
                .build();
    }
1
2
3
4
5
6
7
8

# 1.2.2 Swagger2注解

@Api:用在请求的类上,表示对类的说明
    tags="说明该类的作用,可以在UI界面上看到的注解"
    value="该参数没什么意义,在UI界面上也看到,所以不需要配置"

@ApiOperation:用在请求的方法上,说明方法的用途、作用
    value="说明方法的用途、作用"
    notes="方法的备注说明"

@ApiImplicitParams:用在请求的方法上,表示一组参数说明
    @ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
        name:参数名
        value:参数的汉字说明、解释
        required:参数是否必须传
        paramType:参数放在哪个地方
            · header --> 请求参数的获取:@RequestHeader
            · query --> 请求参数的获取:@RequestParam
            · path(用于restful接口)--> 请求参数的获取:@PathVariable
            · body(不常用)
            · form(不常用)    
        dataType:参数类型,默认String,其它值dataType="Integer"       
        defaultValue:参数的默认值
        
@ApiResponses:用在请求的方法上,表示一组响应
    @ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息
        code:数字,例如400
        message:信息,例如"请求参数没填好"
        response:抛出异常的类

@ApiModel:用于响应类上,表示一个返回响应数据的信息
            (这种一般用在post创建的时候,使用@RequestBody这样的场景,
            请求参数无法使用@ApiImplicitParam注解进行描述的时候)
    @ApiModelProperty:用在属性上,描述响应类的属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

注:@ApiIgnore 可以隐藏请求参数,使其不显示在swagger文档里,但该参数仍然可以使用。

# 1.3 Swagger2高级使用

# 1.3.1 导出离线接口文档

前面部署的Swagger接口文档是一个在线文档,需要启动项目才能查看,不够方便。可以通过 swagger2markup (opens new window) 将其导出离线版。

支持的格式很多,以下我只导出html、markdown、asciidoc三种格式,下图是html格式

Swagger离线版接口文档

Step1:首先在pom.xml导入以下4个依赖(严格按照这个版本号,不然可能会出错)

        <!-- swagger2导出离线接口文档 https://github.com/Swagger2Markup/swagger2markup -->
        <dependency>
            <groupId>io.github.swagger2markup</groupId>
            <artifactId>swagger2markup</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>ch.netzwerg</groupId>
            <artifactId>paleo-core</artifactId>
            <version>0.10.2</version>
        </dependency>
        <dependency>
            <groupId>io.vavr</groupId>
            <artifactId>vavr</artifactId>
            <version>0.9.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
        </dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Step2:编写生成接口文档的工具类,先启动Appliation运行项目,再运行该工具类生成markdown、asciidoc格式的接口文档

import io.github.swagger2markup.GroupBy;
import io.github.swagger2markup.Language;
import io.github.swagger2markup.Swagger2MarkupConfig;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;
import io.github.swagger2markup.markup.builder.MarkupLanguage;
import org.junit.Test;
import java.net.URL;
import java.nio.file.Paths;

/**
 * 生成各种格式的接口文档(需要先启动Appliation)
 */

public class ExportSwagger {

    /**
     * 生成Markdown格式文档--单文件版
     * @throws Exception
     */
    @Test
    public void generateMarkdownDocsToFile() throws Exception {
        //    输出Markdown到单文件
        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                .withMarkupLanguage(MarkupLanguage.MARKDOWN)
                .withOutputLanguage(Language.ZH)
                .withPathsGroupedBy(GroupBy.TAGS)
                .withGeneratedExamples()
                .withoutInlineSchema()
                .build();

        Swagger2MarkupConverter.from(new URL("http://localhost:8080/v2/api-docs"))
                .withConfig(config)
                .build()
                .toFile(Paths.get("src/main/resources/docs/markdown/interface-doc"));
    }

    /**
     * 生成AsciiDocs格式文档--单文件版(用于转换HTML)
     * @throws Exception
     */
    @Test
    public void generateAsciiDocsToFile() throws Exception {
        //    输出Ascii到单文件
        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                .withMarkupLanguage(MarkupLanguage.ASCIIDOC)
                .withOutputLanguage(Language.ZH)
                .withPathsGroupedBy(GroupBy.TAGS)
                .withGeneratedExamples()
                .withoutInlineSchema()
                .build();

        Swagger2MarkupConverter.from(new URL("http://localhost:8080/v2/api-docs"))
                .withConfig(config)
                .build()
                .toFile(Paths.get("src/main/resources/docs/asciidoc/interface-doc"));
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

Step3:再在pom.xml里添加asciidoc转html的Maven插件

            <!--将asciidoc格式的接口文档转换成html格式-->
            <plugin>
                <groupId>org.asciidoctor</groupId>
                <artifactId>asciidoctor-maven-plugin</artifactId>
                <version>1.5.6</version>
                <configuration>
                    <!--asciidoc文件目录-->
                    <sourceDirectory>src/main/resources/docs/asciidoc</sourceDirectory>
                    <!---生成html的路径-->
                    <outputDirectory>src/main/resources/docs/html</outputDirectory>
                    <backend>html</backend>
                    <sourceHighlighter>coderay</sourceHighlighter>
                    <attributes>
                        <!--导航栏在左-->
                        <toc>left</toc>
                        <!--显示层级数-->
                        <toclevels>3</toclevels>
                        <!--自动打数字序号-->
                        <sectnums>true</sectnums>
                    </attributes>
                </configuration>
            </plugin>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

注意资源路径要与生成的asciidoc路径相对应,然后双击下图选中的asciidoctor:process-asciidoc即可生成html格式的离线文档。

使用asciidoc转html的插件

# 1.3.2 Swagger的knife4j UI

如果觉得原生Swagger UI太丑,可以将其换成knife4j UI,配置与之完全相同,只需要添加如下依赖即可。

   <!--Knife4J版的Swagger UI-->
   <dependency>
       <groupId>com.github.xiaoymin</groupId>
       <artifactId>knife4j-spring-boot-starter</artifactId>
       <version>2.0.2</version>
   </dependency>
1
2
3
4
5
6

注意,使用Knife4j2.0.6及以上的版本,SpringBoot的版本必须大于等于2.2.x。

knife4j-UI

# 1.3.3 Swagger添加权限验证

pom.xml引入依赖:

        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.6</version>
        </dependency>
1
2
3
4
5

application.properties添加配置:

# If this is set to true, the swagger page is hidden
swagger.production=false
# This setting is true to enable account password verification
swagger.basic.enable=true
swagger.basic.username=admin
swagger.basic.password=123456
1
2
3
4
5
6

SwaggerConfig.java添加注解:

@EnableSwaggerBootstrapUI
1

页面验证效果:

Swagger权限校验

# 1.3.4 Swagger页面出现警告

问题描述:打开swagger页面时,出现 java.lang.NumberFormatException: For input string 警告

报错原因:这是由于实体类使用@ApiModelProperty时,example属性没有赋值导致的,在AbstractSerializableParameter的getExample方法中会将数值属性的example的转换数值类返回,example的默认值是"",因此当example没有赋值时,会出现上面的异常。

解决办法:排除swagger2的annotations和models依赖,然后再引入1.5.21版本的annotations和models依赖即可解决。

<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger2</artifactId>
	<!--排除swagger2的annotations和models依赖,然后再引入1.5.21版本的annotations和models依赖-->
	<exclusions>
		<exclusion>
			<groupId>io.swagger</groupId>
			<artifactId>swagger-annotations</artifactId>
		</exclusion>
		<exclusion>
			<groupId>io.swagger</groupId>
			<artifactId>swagger-models</artifactId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<!--引入1.5.21版本的annotations和models依赖-->
<dependency>
	<groupId>io.swagger</groupId>
	<artifactId>swagger-annotations</artifactId>
	<version>1.5.21</version>
</dependency>
<dependency>
	<groupId>io.swagger</groupId>
	<artifactId>swagger-models</artifactId>
	<version>1.5.21</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 2. 使用postman工具测试API

# 2.1 postman简介

# 2.1.1 postman是什么

Postman是一个测试接口和http请求的开源工具,功能十分强大,它的优点如下:

  • 支持各种的请求类型: get、post、put、patch、delete 等
  • 支持在线存储数据,通过账号就可以进行迁移数据
  • 很方便的支持请求 header 和请求参数的设置
  • 支持不同的认证机制,包括 Basic Auth,Digest Auth,OAuth 1.0,OAuth 2.0 等
  • 响应数据是自动按照语法格式高亮的,包括 HTML,JSON 和 XML

Postman汉化版的工作界面如下:

Postman汉化版

# 2.1.2 安装postman工具

Github项目地址:https://github.com/postmanlabs (opens new window)

官网:https://www.postman.com/ (opens new window)

Postman 可以单独作为一个应用安装,也可以作为 Chrome 的一个插件安装,建议选择前者。

如果你英文不好,可选择汉化版下载:https://github.com/hlmd/Postman-cn/releases (opens new window)

  • 方式1:Postman-win64.zip 解压直接用
  • 方式2:app.zip 解压&&替换文件 应用程序目录/resources/app.asar(注意:请替换相同版本的文件)

# 2.2 基础知识储备

# 2.2.1 Web API简介及示例接口

  • Web API是网站的一部分,用于与使用非常具体的URL请求特定信息的程序交互,这种请求称为API调用。请求的数据将以易于处理的格式(如JSON或CSV)返回,依赖于外部数据源的大多数应用程序都依赖于API调用。

  • 以下我们使用Github的API作为示例进行测试:https://api.github.com/search/repositories?q=language:python&sort=stars (opens new window)

    注:很多API都要求你注册获得API密钥后才能执行API调用。目前GitHub没有这样的要求,但获得API密钥后,配额将高得多。

# 2.2.2 Get与Post的区别

GET与POST是我们常用的两种HTTP Method,二者最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数。简单粗暴的理解就是GET是明文传递数据,POST是加密传递数据。所以后者比前者安全,通常用户名密码使用POST传递。

  • (1) 从功能上讲,GET一般用来从服务器上获取资源,POST一般用来更新服务器上的资源;
  • (2) 从REST服务角度上说,GET是幂等的,即读取同一个资源,总是得到相同的数据,而POST不是幂等的,因为每次请求对资源的改变并不是相同的;进一步地,GET不会改变服务器上的资源,而POST会对服务器资源进行改变;
  • (3) 从请求参数形式上看,GET请求的数据会附在URL之后,即将请求数据放置在HTTP报文的 请求头 中,以?分割URL和传输数据,参数之间以&相连。特别地,如果数据是英文字母/数字,原样发送;否则,会将其编码为 application/x-www-form-urlencoded MIME字符串(如果是空格,转换为+,如果是中文或其他字符,则直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII);而POST请求会把提交的数据则放置在是HTTP请求报文的请求体中。
  • (4) 就安全性而言,POST的安全性要比GET的安全性高,因为GET请求提交的数据将明文出现在URL上,而且POST请求参数则被包装到请求体中,相对更安全。
  • (5) 从请求的大小看,GET请求的长度受限于浏览器或服务器对URL长度的限制,允许发送的数据量比较小,而POST请求则是没有大小限制的。

# 2.2.3 常见网络状态码及含义

  • 1×× : 请求处理中,请求已被接受,正在处理
  • 2×× : 请求成功,请求被成功处理(200 OK)
  • 3×× : 重定向,要完成请求必须进行进一步处理(301: 永久性转移、302:暂时性转移、304:已缓存)
  • 4×× : 客户端错误,请求不合法(400:请求有语法问题、403:拒绝请求、404:客户端所访问的页面不存在)
  • 5×× : 服务器端错误,服务器不能处理合法请求(500:服务器内部错误、503:服务不可用)

# 2.3 Postman基本使用

# 2.3.1 Postman基本使用流程

Postman基本使用流程

[1] 新建——请求 or 直接点工作区上面Tab页的“+”

[2] 在下拉框选择 HTTP 的 Method 方法并在Text框输入 API 的地址

[3] 在“头”处设置相关请求头信息

[4] 在“主体”处设置相关GET或POST等的参数

[5] 填写好之后,点击 Send 去发送请求 Request

[6] 请求成功之后,底部便可查看Response响应的信息

# 2.3.2 Postman设置环境变量

需求描述:

在Postman测试本地环境和服务器的测试环境,动态改变接口的访问地址前缀,可以使用Postman中的环境变量来解决。

Postman设置环境变量

解决思路:

[1] 在Postman中设置两个环境,本地环境、测试环境。

[2] 在两个环境中分别设置变量名为 base_url 的变量,存放各自环境的IP地址。

[3] 在Postman的URL地址栏中设置 为 /login。

[4] 切换不同的环境,base_url的值就会发生改变,这样就达到了IP地址切换的效果。

# 2.3.3 从Swagger导入接口文档

可以通过swagger一键导入所有api接口至Postman:导入——链接,URL参照如下填写即可(IP和端口号换成自己的):

http://localhost:8080/v2/api-docs
1

从Swagger导入接口文档

# 2.3.4 Postman系统代理问题

问题情景:一个项目需要对接外部系统接口,外部接口需要开启思科VPN才能调用,外部接口在curl命令及代码中可以请求通过,但在Postman里请求不通(502错误),关闭了ClashX代理工具也依旧不行。

解决办法:关闭Postman里的系统代理配置即可(这个默认是开启的)

Postman取消使用系统代理

# 2.4 特殊形式的请求

# 2.4.1 上传文件请求

上传文件请求:主体——新建一个键,类型选择文件,值那里上传文件即可。

上传文件请求

# 2.4.2 下载文件请求

下载文件请求:点击发送按钮旁边下拉框里的“发送并下载”即可。

下载文件请求

# 2.4.3 数组形式的请求

直接设置多个相同key的键值对即可。

数组形式的请求

# 2.4.4 Elasticsearch安全认证

Elasticsearch通常会设置密码,无法直接请求,如果需要通过http请求直接查询,可以如下操作:授权——Basic Auth——输入用户名和密码即可。

Elasticsearch安全认证

# 2.4.5 请求头添加Token

授权——类型选择“OAuth 2.0”,输入登录接口获得的Token。

请求头添加Token

# 2.5 自动设置登录信息

# 2.5.1 Postman自动设置Token

情景描述:登录接口获取token,其他接口访问都要带上这个token,个个接口复制粘贴token太过麻烦。

解决方案:把登录接口返回的Token自动设置到Postman的环境变量中,然后用自动引用。

在登录接口添加Tests,代码如下所示:

pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});
 
// 把responseBody转为json字符串
var data = JSON.parse(responseBody);
// 设置环境变量token,供后面的接口引用,位置就是上一步获取的位置
pm.environment.set("token", data.token);  // data.token要根据自己登录接口返回值里token的位置来取值
1
2
3
4
5
6
7
8

Postman自动设置Token-1

点击Send按钮发送请求后,就Postman会自动在环境变量中设置一个变量,变量名为token,值为ResponseBody中的token值。

Postman自动设置Token-2

具体的业务接口,点击“Authorization”,类型选择“OAuth 2.0”,Access Token处填写成即可。

Postman自动设置Token-3

注:Postman 提供了 Pre-request Script 和 Tests 功能,开发调试时建议打开左下角的Console查看日志。

  • Pre-request Script(预请求脚本)会在发送实际请求之前执行,可以对请求进行预处理(比如设置请求头、请求体),确保请求正常发送。
  • Tests(测试脚本):会在接收到请求响应后执行,可以用来验证返回的数据是否符合预期,或者对响应数据进行处理(比如将token保存到环境变量)。

# 2.5.2 获取浏览器Cookie自动同步Postman

需求情景:登录请求在浏览器中完成,后续的接口测试在Postman中进行,想要在Postman里获取浏览器中的Cookie,手动填写过于费事,想要自动实现。

解决办法:Postman Interceptor工具可以通过配置拦截浏览器 Cookie 并将其自动同步到 Postman 工具中。

# 2.6 使用curl发送接口请求

在Postman工具中,右侧的Code功能可以获取到接口请求对应的curl命令。

使用curl命令直接发送get/post/put/delete请求,其中curl -h查看请求参数的含义 -v 显示请求的信息 -X 选项指定其它协议

get:
    curl -v http://127.0.0.1:8080/girls/age/18
post:
    curl -v -X POST http://127.0.0.1:8080/girls -d 'age=14&cupSize=C'
put:
    curl -v -X PUT -d "age=19&cupSize=C" http://127.0.0.1:8080/girls/3
delete:
    curl -v -X DELETE http://127.0.0.1:8080/girls/3
1
2
3
4
5
6
7
8

-H ‘xxx’ 带请求头

curl -v -H 'ApiKey:xxx' -H 'Sign:xxx' -H 'RequestTime:xxx' -H 'Content-Type:application/json' -H 'User-Agent:PostmanRuntime/7.26.10' -H 'Accept:*/*' -H 'Accept-Encoding:gzip, deflate, br' -H 'Connection:keep-alive' -X POST 192.xxx.xx.xx:xxxx/test/xxxx -d '{"orgCode":"xxx","districtId":"1"}'
1

例子:在body体以JSON格式传参的post请求

$ curl -X POST http://127.0.0.1:8080/girls -H "Content-type: application/json" -d'{"param":"test param"}'
1

# 3. 对API或URL进行压力测试

# 3.1 压测概述

# 3.1.1 压测是什么

压测,即压力测试,是确立系统稳定性的一种测试方法,通常在系统正常运作范围之外进行,以考察其功能极限和隐患。

主要检测服务器的承受能力,包括用户承受能力(多少用户同时玩基本不影响质量)、流量承受等。

# 3.1.2 为什么要压测

  • 压测的目的就是通过压测(模拟真实用户的行为),测算出机器的性能(单台机器的 QPS),从而推算出系统在承受指定用户数(100W)时,需要多少机器能支撑得住。
  • 压测是在上线前为了应对未来可能达到的用户数量的一次预估(提前演练),压测以后通过优化程序的性能或准备充足的机器,来保证用户的体验。

# 3.2 压测术语解释

# 3.2.1 压测类型解释

压测类型 解释
压力测试(Stress Testing) 也称之为强度测试,测试一个系统的最大抗压能力,在强负载(大数据、高并发)的情况下,测试系统所能承受的最大压力,预估系统的瓶颈
并发测试(Concurrency Testing) 通过模拟很多用户同一时刻访问系统或对系统某一个功能进行操作,来测试系统的性能,从中发现问题(并发读写、线程控制、资源争抢)
耐久性测试(Configuration Testing) 通过对系统在大负荷的条件下长时间运行,测试系统、机器的长时间运行下的状况,从中发现问题(内存泄漏、数据库连接池不释放、资源不回收)

# 3.2.2 压测名词解释

压测名词 解释
并发(Concurrency) 指一个处理器同时处理多个任务的能力(逻辑上处理的能力)
并行(Parallel) 多个处理器或者是多核的处理器同时处理多个不同的任务(物理上同时执行)
QPS(每秒钟查询数量 Queries Per Second) 服务器每秒钟处理请求数量(req/sec 请求数/秒 一段时间内总请求数/请求时间)
事务(Transactions) 是用户一次或者是几次请求的集合
TPS(每秒钟处理事务数量 Transaction Per Second) 服务器每秒钟处理事务数量(一个事务可能包括多个请求)
请求成功数(Request Success Number) 在一次压测中,请求成功的数量
请求失败数(Request Failures Number) 在一次压测中,请求失败的数量
错误率(Error Rate) 在压测中,请求成功的数量与请求失败数量的比率
最大响应时间(Max Response Time) 在一次压测中,从发出请求或指令系统做出响应的最大时间
最少响应时间(Mininum Response Time) 在一次压测中,从发出请求或指令系统做出响应的最少时间
平均响应时间(Average Response Time) 在一次压测中,从发出请求或指令系统做出响应的平均时间

# 3.2.3 机器性能指标解释

机器性能 解释
CPU利用率(CPU Usage) CPU 利用率分用户态、系统态和空闲态,它是指 CPU 执行非系统空闲进程的时间与 CPU 总执行时间的比率
内存使用率(Memory usage) 内存使用率指的是此进程所开销的内存
IO(Disk input / output) 磁盘的读写包速率
网卡负载(Network Load) 网卡的进出带宽

# 3.2.4 访问指标解释

访问 解释
PV(页面浏览量 Page Views) 一定时间范围内(时间范围可以是一天、一个月等自定义的时间段),用户每打开 1 个网站页面,记录 1 个 PV。用户多次打开同一页面,PV 值累计多次
UV(网站独立访客 Unique Visitors) 一定时间范围内(时间范围可以是一天、一个月等自定义的时间段),通过互联网访问、流量网站的自然人。相同访客多次访问网站,只计算为 1 个独立访客

# 3.3 常见压测工具

# 3.3.1 ApacheBench

ApacheBench 是 Apache 服务器自带的一个web压力测试工具,简称 ab。它是一个命令行工具,对发起负载的本机要求很低,根据 ab 命令可以创建很多的并发访问线程,模拟多个访问者同时对某一 URL 地址进行访问,因此可以用来测试目标服务器的负载压力。总的来说 ab 工具小巧简单,上手学习较快,可以提供需要的基本性能指标,但是没有图形化结果,不能监控。它属于一个轻量级的压测工具,结果不会特别准确,可以用作参考。

$ apt-get install apache2-utils
$ ab -n 100 -c 1 https://www.baidu.com/    // 使用ab压测工具,对百度的链接请求100次,并发数1
1
2

使用ab压测工具示例

工具的用法:

Usage: ab [options] [http[s]://]hostname[:port]/path
用法:ab [选项] 地址

选项:
Options are:
    -n requests      #执行的请求数,即一共发起多少请求。
    -c concurrency   #请求并发数。
    -s timeout       #指定每个请求的超时时间,默认是30秒。
    -k               #启用HTTP KeepAlive功能,即在一个HTTP会话中执行多个请求。默认时,不启用KeepAlive功能
1
2
3
4
5
6
7
8
9

主要关注的测试指标:

- Concurrency Level 并发请求数
- Time taken for tests 整个测试时间
- Complete requests 完成请求个数
- Failed requests 失败个数
- Requests per second 吞吐量,指的是某个并发用户下单位时间内处理的请求数。等效于 QPS,其实可以看作同一个统计方式,只是叫法不同而已。
- Time per request 用户平均请求等待时间
- Time per request 服务器处理时间
1
2
3
4
5
6
7

# 3.3.2 go-stress-testing

项目简介:一个使用 go 实现的压测工具。

查看用法:不带任何参数即可查看用法。

$ ./go-stress-testing-linux      // 查看用法

示例: go run main.go -c 1 -n 1 -u https://www.baidu.com/ 
压测地址或curl路径必填 
当前请求参数: -c 1 -n 1 -d false -u  
Usage of ./go-stress-testing-linux:
  -H value
        自定义头信息传递给服务器 示例:-H 'Content-Type: application/json'
  -c uint
        并发数 (default 1)
  -code int
        请求成功的状态码 (default 200)
  -cpuNumber int
        CUP 核数,默认为一核 (default 1)
  -d string
        调试模式 (default "false")
  -data string
        HTTP POST方式传送数据
  -http2
        是否开http2.0
  -k    是否开启长连接
  -m int
        单个host最大连接数 (default 1)
  -n uint
        请求数(单个并发/协程) (default 1)
  -p string
        curl文件路径
  -timeout int
        超时时间 单位 秒,默认不设置
  -u string
        压测地址
  -v string
        验证方法 http 支持:statusCode、json webSocket支持:json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

使用示例:

// 使用请求百度页面
$ ./go-stress-testing-linux -c 1 -n 25 -u https://www.baidu.com/

// 使用debug模式请求百度页面
$ ./go-stress-testing-linux -c 1 -n 1 -d true -u https://www.baidu.com/

// 使用curl文件的方式请求
$ ./go-stress-testing-linux -c 1 -n 1 -p curl/baidu.curl.txt

// 压测webSocket连接
$ ./go-stress-testing-linux -c 10 -n 10 -u ws://127.0.0.1:8089/acc
1
2
3
4
5
6
7
8
9
10
11

使用go-stress-testing压测工具示例

# 4. 参考资料

[1] Postman 接口测试神器 from Gitbook (opens new window)

[2] api_tool_postman form Github (opens new window)

[3] Postman汉化版 from GitHub (opens new window)

[4] Postman记录您的API from Postman学习中心 (opens new window)

[5] 快速掌握Postman实现接口测试 from 知乎 (opens new window)

[6] 常见网络错误 from CSDN (opens new window)

[7] Postman设置环境变量 from CSDN (opens new window)

[8] Postman自动获取token,Postman自动设置token from CSDN (opens new window)

[9] curl模拟delete/put/post/get请求 from CSDN (opens new window)

[10] 【Swagger异常】AbstractSerializableParameter:Illegal DefaultValue null for parameter type integer解决方案 from CSDN (opens new window)

[11] 前端嫌弃原生Swagger界面太low,于是我给她开通了超级VIP from 博客园 (opens new window)

[12] 将Swagger2文档导出为HTML或markdown等格式离线阅读 from segmentfault (opens new window)

[13] Swagger2 导出api文档(AsciiDocs、Markdown) from CSDN (opens new window)

[14] SpringBoot整合Swagger2,再也不用维护接口文档了!from CSDN (opens new window)

[15] Swagger2 注解 from Github (opens new window)

[16] springboot /v2/api-docs 无法访问 from CSDN (opens new window)

[17] SpringBoot Swagger去掉basic-error-controller from CSDN (opens new window)

[18] Postman调接口时获取Chrome浏览器Cookie数据携带发送 from CSDN (opens new window)

Last Updated: 5/4/2025, 3:44:16 PM