1. In Yii 2.0, the browser became unresponsive, which in turn caused the request to be sent twice. The first request had no response, and the second request returned an error (the program prohibits duplicate requests). See Figure 1.

2. Viewing the details of the first request, under Headers – General, there is no response status code. See Figure 2.

3. Viewing the details of the first request, under Response, it fails to load response data. See Figure 3.

4. Checking the Log Messages, execution stopped at E:\wwwroot\channel-pub-api\common\services\WeiboWeiboConnectWebAppAccessTokenService.php:92, when it should have continued. See Figure 4.

5. Looking at the code, line 92: $weiboWeiboConnectWebAppUserAccessToken->save()
public function saveModel($data)
{
/* 基于微博的微连接的网页应用的用户ID查找状态为启用的单个资源 */
$weiboWeiboConnectWebAppUserAccessToken = WeiboWeiboConnectWebAppUserAccessToken::find()->where(['weibo_weibo_connect_web_app_user_id' => $data['weiboWeiboConnectWebAppUserId']])->isDeletedNo()->enabled()->one();
if (!isset($weiboWeiboConnectWebAppUserAccessToken)) {
$weiboWeiboConnectWebAppUserAccessToken = new WeiboWeiboConnectWebAppUserAccessToken();
}
// 设置访问令牌的有效截止时间
$time = time();
$accessTokenExpireAt = $time + $data['expires_in'] + Yii::$app->params['weiboAuth']['weiboConnectWebApp']['authPeriod'] - Yii::$app->params['refreshToken']['timeOut'];
$weiboWeiboConnectWebAppUserAccessToken->attributes = [
'weibo_weibo_connect_web_app_id' => $data['weiboWeiboConnectWebAppId'],
'channel_app_source_id' => $data['channelAppSourceId'],
'channel_app_source_uuid' => $data['channelAppSourceUuid'],
'weibo_weibo_connect_web_app_user_id' => $data['weiboWeiboConnectWebAppUserId'],
'weibo_weibo_connect_web_app_user_uuid' => $data['weiboWeiboConnectWebAppUserUuid'],
'grant_type' => $data['grantType'],
'access_token' => $data['access_token'],
'expires_in' => $data['expires_in'],
'expires_at' => $accessTokenExpireAt,
'scope' => isset($data['scope']) ? $data['scope'] : '',
'user_id' => $data['uid'],
'status' => WeiboWeiboConnectWebAppUserAccessToken::STATUS_ENABLED,
];
if ($weiboWeiboConnectWebAppUserAccessToken->save()) {
return ['status' => true, 'data' => ['channel_app_source_uuid' => $data['channelAppSourceUuid']]];
} elseif ($weiboWeiboConnectWebAppUserAccessToken->hasErrors()) {
$firstError = '';
foreach ($weiboWeiboConnectWebAppUserAccessToken->getFirstErrors() as $message) {
$firstError = $message;
break;
}
return ['status' => false, 'code' => 214010, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '214010'), ['first_error' => $firstError]))];
} elseif (!$weiboWeiboConnectWebAppUserAccessToken->hasErrors()) {
throw new ServerErrorHttpException('Failed to insert/update the object (microblogging micro-connected web application user\'s access token) for unknown reason.');
}
}
6. Printing the object before line 92: $weiboWeiboConnectWebAppUserAccessToken. The printed result is as follows. And the first request returned a 200 response. See Figure 5.

common\logics\WeiboWeiboConnectWebAppUserAccessToken Object
(
[_attributes:yii\db\BaseActiveRecord:private] => Array
(
[weibo_weibo_connect_web_app_id] => 1
[channel_app_source_id] => 39
[channel_app_source_uuid] => c28915a6a8cb11ebba6254ee75d2ebc1
[weibo_weibo_connect_web_app_user_id] => 6
[weibo_weibo_connect_web_app_user_uuid] => c28a3efea8cb11ebb69354ee75d2ebc1
[grant_type] => authorization_code
[access_token] => 2.00bAKoqCV9i7fEee243e798c0zzui2
[expires_in] => 2626935
[expires_at] => 1622394001
[scope] =>
[user_id] => 2612590013
[status] => 1
)
)
7. Editing the code, line 92: $weiboWeiboConnectWebAppUserAccessToken->save(false), to skip validation before saving the record (the data is trusted), in order to avoid excessive validation time, which leads to a long response time and causes the browser to send duplicate requests. Note: Previously, this was a Redis AR model, which was later changed to a MySQL AR model. Viewing its duration in the browser: 2.57 seconds. See Figure 6 and Figure 7.


public function saveModel($data)
{
/* 基于微博的微连接的网页应用的用户ID查找状态为启用的单个资源 */
$weiboWeiboConnectWebAppUserAccessToken = WeiboWeiboConnectWebAppUserAccessToken::find()->where(['weibo_weibo_connect_web_app_user_id' => $data['weiboWeiboConnectWebAppUserId']])->isDeletedNo()->enabled()->one();
if (!isset($weiboWeiboConnectWebAppUserAccessToken)) {
$weiboWeiboConnectWebAppUserAccessToken = new WeiboWeiboConnectWebAppUserAccessToken();
}
// 设置访问令牌的有效截止时间
$time = time();
$accessTokenExpireAt = $time + $data['expires_in'] + Yii::$app->params['weiboAuth']['weiboConnectWebApp']['authPeriod'] - Yii::$app->params['refreshToken']['timeOut'];
$weiboWeiboConnectWebAppUserAccessToken->attributes = [
'weibo_weibo_connect_web_app_id' => $data['weiboWeiboConnectWebAppId'],
'channel_app_source_id' => $data['channelAppSourceId'],
'channel_app_source_uuid' => $data['channelAppSourceUuid'],
'weibo_weibo_connect_web_app_user_id' => $data['weiboWeiboConnectWebAppUserId'],
'weibo_weibo_connect_web_app_user_uuid' => $data['weiboWeiboConnectWebAppUserUuid'],
'grant_type' => $data['grantType'],
'access_token' => $data['access_token'],
'expires_in' => $data['expires_in'],
'expires_at' => $accessTokenExpireAt,
'scope' => isset($data['scope']) ? $data['scope'] : '',
'user_id' => $data['uid'],
'status' => WeiboWeiboConnectWebAppUserAccessToken::STATUS_ENABLED,
];
if ($weiboWeiboConnectWebAppUserAccessToken->save(false)) {
return ['status' => true, 'data' => ['channel_app_source_uuid' => $data['channelAppSourceUuid']]];
} elseif ($weiboWeiboConnectWebAppUserAccessToken->hasErrors()) {
$firstError = '';
foreach ($weiboWeiboConnectWebAppUserAccessToken->getFirstErrors() as $message) {
$firstError = $message;
break;
}
return ['status' => false, 'code' => 214010, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '214010'), ['first_error' => $firstError]))];
} elseif (!$weiboWeiboConnectWebAppUserAccessToken->hasErrors()) {
throw new ServerErrorHttpException('Failed to insert/update the object (microblogging micro-connected web application user\'s access token) for unknown reason.');
}
}
8. Checking the response time of the first request when the duplicate requests occurred, both are over 2500 ms. See Figure 8.

9. Reverting the code, line 92: $weiboWeiboConnectWebAppUserAccessToken->save(). When the environment is set to Production, the response time is not excessively long either. Viewing its duration in the browser: 1.56 seconds. This leads to the conclusion: whether validation is enabled certainly affects the response time, but the root cause still lies in the environment setting (Development). See Figure 9.

