如何模擬併發請求

網站出現惡意併發攻擊,解決問題第一步,自己先模擬併發,進行測試

	注意:
		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




 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章