如何模拟并发请求

网站出现恶意并发攻击,解决问题第一步,自己先模拟并发,进行测试

	注意:
		session 登录状态,我们需要设置 cookie

		api 登录状态,我们一般需要设置 Bearer token


	1.并发工具:
		postman - 网上各种说 postman 并发测试,那是迭代请求,并非并发,错误

		AB(Apache Bench) - 这个是经常听说的一款,很简单
			参考:
				ab(Apache Bench)命令详解以及压力测试模拟
					https://blog.csdn.net/jiajiren11/article/details/79486967

		JMeter - Apache JMeter是Apache组织开发的基于Java的压力测试工具
			参考:
				使用 JMeter 进行压力测试
					https://www.cnblogs.com/stulzq/p/8971531.html

		其他工具,没看,参考:
			10大主流压力测试工具
				https://blog.csdn.net/langzitianya/article/details/81479422

			九款Web服务器性能压力测试工具
				https://blog.csdn.net/qq_33440246/article/details/80591070

	2.自己使用 PHP 来模拟并发
		1>使用 guzzlehttp 的并发请求

			use GuzzleHttp\Client;
			use GuzzleHttp\Promise;
			use Psr\Http\Message\ResponseInterface;
			use GuzzleHttp\Exception\RequestException;
			use GuzzleHttp\Exception\ServerException;

		    /**
		     * 模拟发红包 - 异步并发
		     */
		    public function mockSendRedPacketConcurrent($token)
		    {
		        $client = new Client([
		            'base_uri' => 'http://xxx/api/',
		        ]);

		        $promises = [];
		        for($i = 0; $i < 20; $i++){
		            $promise = $client->postAsync('red/sent', [
		                'headers' => [
		                    'Accept' => 'application/json',

		                    // 登录 token
		                    'Authorization' => 'Bearer ' . $token,

		                    // 模拟不同的虚拟IP
		                    'X-Forwarded-For' => '168.1.1.' . $i,
		                ],
		                'query' => [
		                    'red_money' => 100,
		                    'red_type' => 1,
		                    'red_group' => 184,
		                    'red_num' => 1,
		                    'red_title' => '恭喜发财',
		                ],
		            ]);
		            $promises[] = $promise;
		        }

		        $results = Promise\unwrap($promises);

		        foreach($results as $result){
		            $body = $result->getBody();
		            $content = $body->getContents();
		            dump($content);
		        }
		    }

		2>使用 curl 并发请求
			https://www.cnblogs.com/52fhy/p/8908315.html
			https://www.oschina.net/question/54100_58279

		    /**
		     * 模拟发红包 - Rolling cURL并发
		     */
		    public function mockSendRedPacketCurl()
		    {
		    	$token = '';

		        $urls = [];
		        for($i = 0; $i < 600; $i++){
		            $urls[] = 'http://xxx/api/red/sent';
		        }

		        $responses = $this->rolling_curl($urls, $token, 30);
		        dd($responses);
		    }

		    /**
		     * Rolling cURL并发
		     */
		    private function rolling_curl($urls, $token, $delay) {
		        $queue = curl_multi_init();
		        $map = array();

		        foreach ($urls as $i => $url) {
		            $ch = curl_init();

		            $headers = [
	                    'Accept' => 'application/json',

	                    // 登录 token
	                    'Authorization' => 'Bearer ' . $token,

	                    // 模拟不同的虚拟IP
	                    'X-Forwarded-For' => '168.1.1.' . $i,
		            ];
		            $params = [
		                'red_money' => 1,
		                'red_type' => 2,
		                'red_group' => '201910270025455db473899d72f',
		                'red_num' => 1,
		                'red_title' => '并发测试',
		            ];
		            // $params = [
		            //     'red_money' => 100,
		            //     'red_type' => 1,
		            //     'red_group' => 184,
		            //     'red_num' => 1,
		            //     'red_title' => '恭喜发财',
		            // ];
		            curl_setopt($ch, CURLOPT_URL, $url);
		            curl_setopt($ch, CURLOPT_POST, 1);
		            curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
		            curl_setopt($ch, CURLOPT_TIMEOUT, 100);
		            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		            curl_setopt($ch, CURLOPT_HEADER, 0);
		            curl_setopt($ch, CURLOPT_NOSIGNAL, true);
		            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

		            curl_multi_add_handle($queue, $ch);
		            $map[(string) $ch] = $url;
		        }

		        $responses = array();
		        do {
		            while (($code = curl_multi_exec($queue, $active)) == CURLM_CALL_MULTI_PERFORM) ;

		            if ($code != CURLM_OK) { break; }

		            // a request was just completed -- find out which one
		            while ($done = curl_multi_info_read($queue)) {

		                // get the info and content returned on the request
		                $info = curl_getinfo($done['handle']);
		                $error = curl_error($done['handle']);
		                $content = curl_multi_getcontent($done['handle']);
		                // $results = callback(curl_multi_getcontent($done['handle']), $delay);
		                // $responses[$map[(string) $done['handle']]] = compact('info', 'error', 'results');
		                $responses[] = [
		                    'info' => $info,
		                    'error' => $error,
		                    'content' => $content,
		                ];

		                // remove the curl handle that just completed
		                curl_multi_remove_handle($queue, $done['handle']);
		                curl_close($done['handle']);
		            }

		            // Block for data in / output; error handling is done by curl_multi_exec
		            if ($active > 0) {
		                curl_multi_select($queue, 0.5);
		            }

		        } while ($active);

		        curl_multi_close($queue);
		        return $responses;
		    }

		参考文章:
			模拟 ip 是可以的
				https://blog.csdn.net/intel80586/article/details/8906779
				不过 laravel 的 ip() 好像检测比较准确 

			使用 guzzlehttp 来实现并发请求:
				https://segmentfault.com/q/1010000007683839
					使用guzzle发送异步请求返回的promise 调用 then 方法不会立即执行, 还必须要调用wait去等待所有的请求结束,才会执行

			curl 并发:
				https://www.cnblogs.com/52fhy/p/8908315.html
				https://www.oschina.net/question/54100_58279




 

你可能感兴趣的:(php,laravel框架)