1.应用场景

模拟并发请求, 来测试api性能.

以及需要后端[如: php ]直接请求远程服务器[调用远程服务],但是需求是一次发送多个请求.

 2.学习/操作

1. 文档

高性能的 PHP 封装的 HTTP Restful 多线程并发请求库-MultiHttp

Mac下的Web性能压力测试工具:ab(ApacheBench)

http://httpd.apache/docs/2.0/programs/ab.html // 官网 Apache Benchmark

cURL - 学习/实践_william_n的博客-CSDN博客 -- curl也支持多并发

PHP使用curl_multi实现并发请求的方法示例php技巧-php教程-PHP中文网

https://www.php/manual/zh/function.curl-multi-init.php  

使用PHP并发执行任务–curl_multi应用

PHP中使用CURL之php curl详细解析和常见大坑

如何模拟并发请求_beyond__devil的博客-CSDN博客_模拟并发请求

2. 整理输出

2.1 环境

Windows 10 64位 专业版  WAMP [apache 2.x  mysql 8.0  php 7.x]

这里直接通过PHPstudy 集成安装. Phpstudy v8.0 - 创建本地站点域名_william_n的博客-CSDN博客

模拟/实现并发请求方式:

无非两种, 一种借助工具, 另外一种则是使用代码去做.

2.2 工具

AB

ApacheBench 是 Apache服务器自带的一个web压力测试工具,简称ab。ab又是一个命令行工具,对发起负载的本机要求很低,根据ab命令可以创建很多的并发访问线程,模拟多个访问者同时对某一URL地址进行访问,

因此可以用来测试目标服务器的负载压力。总的来说ab工具小巧简单,上手学习较快,可以提供需要的基本性能指标,但是没有图形化结果,不能监控。

后补充:

ab是非图形化的并发测试工具,没有Jmeter、Loadrunner那样有各种场景设计、各种图形报告和监控,只需一个命令即可,有输出描述,可以简单的进行一些压力测试。

当然,您也可以选择webbench、siege、http_load、Load impact、阿里云PTS等工具进行很方便的测试。

1). AB测试实践

Windows环境下

1.1) 打开cmd, 进入指定目录:

这里推荐一个小技巧:

直接在在文件地址栏中输入cmd, 按下回车即可, 就会出现cmd窗口, 而且已经处于目标目录下.

查看使用命令:

1.2) 开始使用AB测试

常用格式:

ab [options] [http[s]://]hostname[:port]/path

以下, 先使用百度进行测试:

ab -n 100 -c 10 http://www.baidu/

参数解读

-n : requests     Number of requests to perform  //执行的请求数[共计]
-c : concurrency  Number of multiple requests to make at a time //一次发出的请求数 即一次并发数

两者的关系:

-n >= -c 否则会提示报错

或者

ab -n 100 -c 10 -w http://www.baidu/ >> baidu.html // 结果以html文件形式保存

截图如下

由上可知:

请求只有99个完成, 结果以请求超时结束. [应该是百度做了防护的原因]

------- 现在使用我们自己的接口-------

查询接口

http://laravel7.1-admin.test/datetime  get请求方式,先使用postman做单次查询

开始使用AB进行压测

ab -n 1000 -c 10 http://laravel7.1-admin.test/datetime

上面重要的参数指标, 已经使用荧光笔标注出来.

写入接口

http://laravel7.1-admin.test/datetime  post请求方式

开始AB 压测

ab -n 10 -c 5 -m post http://laravel7.1-admin.test/datetime

将请求参数直接写在后端接口中~

写入的结果,查看数据库:

可以看到并发请求完成, 一次写入10条记录. 

详细解读:对比参考

Note

1. 如果不想安装apache但是又想使用ab命令的话,我们可以直接安装apache的工具包httpd-tools[https://pkgs/download/httpd-tools]。如下:

yum -y install httpd-tools

查看ab是否安装成功,可以切换到上述目录下,使用ab –V命令进行检测。

如下:

ab -V

如果ab安装成功,通过ab –V命令则会显示ab的相应版本。

注意以上是在linux平台下进行安装的,

如果是windows平台下,我们也可以下载对应的apache版本进行安装。

Mac下自带apache

执行如下命令

apachectl -v

ab -V

补充 --- 注意事项

当请求需要设置请求头时,如下各式即可

这里是get请求

ab -n 10 -c 10 -m get -H "x-kumu-token:52fae12be5123456bc3a17aa3adfb0a5" -H "device-id:C625A84ABD0E12349CE248FEFFABE9D7" -H "device-type:ios" -H "version-code:1043" -H "x-kumu-userid:BCRdNJ1234xWThvJ" https://dev-api.xxxxx/v1/sig/list

 

当如果有Query String时,需要将url做转义处理

https://dev-api.xxx/v1/sig/list\?size\=20\&lek\=

更多用法:

http://httpd.apache/docs/2.0/programs/ab.html

补充

如果是post请求,同时是application/json

https://gist.github/kelvinn/6a1c51b8976acf25bd78#file-cmd-sh

# post_loc.txt contains the json you want to post
# -p means to POST it
# -H adds an Auth header (could be Basic or Token)
# -T sets the Content-Type
# -c is concurrent clients
# -n is the number of requests to run in the test

ab -p post_loc.txt -T application/json -H 'Authorization: Token abcd1234' -c 10 -n 2000 http://example/api/v1/locations/

➜  practice and test ab -n 10 -c 2 \

-H "x-kumu-token:155dc02sdfsadfasdf53144b7d5dd372ff7ae2" \

-H "device-id:C625A84ABD0E12349CE248FEFFABE9D7" \

-H "device-type:ios" \

-H "version-code:1043" \

-H "x-kumu-userid:BCRdNsdfsad4xWThvJ" \

-p ./params.json \

-T application/json https://dev-api.sdfasd/feed/sdfasdf

截图

2. 需要认真理解这里性能指标, 如果不理解它们所代表的含义,那么就失去压测的意义~~

因为你不知道测试的结果是什么,是否良好, 是否需要改进~~~

后续补充

...

 3.问题/补充

1. PHP 暂停函数 sleep() 与 usleep() 的区别

在PHP中暂停代码执行一定时间,有两个函数可以实现,一个是sleep(),另一个是usleep(),它们参数都是一个整数值。

sleep()是暂停多少秒,usleep()是暂停多少微秒。


注意:

usleep()单位是微秒,1秒 = 1000毫秒 ,1毫秒 = 1000微秒,即1微秒等于百万分之一秒。


如果程序中要使用要暂停多少毫秒,只能使用usleep(),务必注意参数的单位,假设暂停 50毫秒,应该使用 usleep(50000),

而不是usleep(50)。


另外,这个暂停的时候不可能是百分百的准确,跟系统的调度、CPU时钟周期等等有一定关系。

2. 如果想实验/测试MySQL的并发写入,可以直接通过SQL去做,或者通过PHP代码去做均可

我们要明白一件事,那就是并发是什么,简单说,就是同一时刻, 多个请求.

关键点: 同一时刻,这是一个尺度, 看你怎么定义, 同一秒可以认为是同一时刻, 同一毫秒可认为是同一时刻, 甚至同一分钟也可以认为是同一时刻. 

至于选择那个作为你的标准,更多取决于你的业务逻辑, 因为首先要满足业务逻辑才可以,然后可以在其基础进行优化.

例如:

我们要完成这样一个需求,同一秒中只能插入一条记录.

解决方案之一:

数据表中,在时间戳类型的字段中,新建一个唯一索引即可.

这里选择 create_at字段

模拟并发操作:

直接写入几条插入SQL即可,点击执行.

INSERT INTO `test` (`learn_date`, `learn_time`, `learn_time_tz`, `learn_datetime`, `learn_datetime_tz`, `learn_timestamp`, `learn_timestamp_tz`, `learn_year`, `created_at`, `updated_at`, `learn_index`) VALUES
    ('2020-08-13', '17:18:35', '17:18:36', '2020-08-13 17:18:40', '2020-08-13 17:18:50', '2020-08-13 17:18:51', '2020-08-13 17:18:53', '2020', NOW(), NOW(), 1);
    
    INSERT INTO `test` (`learn_date`, `learn_time`, `learn_time_tz`, `learn_datetime`, `learn_datetime_tz`, `learn_timestamp`, `learn_timestamp_tz`, `learn_year`, `created_at`, `updated_at`, `learn_index`) VALUES
    ('2020-08-13', '17:18:35', '17:18:36', '2020-08-13 17:18:40', '2020-08-13 17:18:50', '2020-08-13 17:18:51', '2020-08-13 17:18:53', '2020', NOW(), NOW(), 1);

然后查看结果, 是否满足条件.

执行结果如下:

旧数据

执行SQL,出现如下报错提示:

报错提示: 重复的输入. 即,唯一索引导致的结果.

新数据//只是新插入一条记录,因为唯一性约束.

...

4.参考

参加文档阅读列表

后续补充

...

更多推荐

AB - 模拟/实现并发请求 - PHP (代码) - 压力测试