網站出現惡意併發攻擊,解決問題第一步,自己先模擬併發,進行測試
注意:
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