RateLimiter:生产中部署后的'yii \ base \ UnknownPropertyException'

时间:2016-07-22 10:11:06

标签: php filter yii2 rate-limiting

对于授权用户,我设置了对系统查询频率的限制。如果每个给定时间间隔的请求数超过设置,则返回状态代码为429的响应。在我的特定情况下,它在五秒内不超过一个请求。

在身份类中,我实现了yii\filters\RateLimitInterface

<?php
namespace common\models;

use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
use yii\filters\RateLimitInterface;

/**
 * User model
 *
 * ...
 * @property integer $id
 * ...
 *
 * @property integer $allowance
 * @property integer $allowance_updated_at
  */
class User extends ActiveRecord implements IdentityInterface, RateLimitInterface
{
    ...

    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return '{{%user}}';
    }

    /**
     * Returns the maximum number of allowed requests and the window size.
     * @param \yii\web\Request $request the current request
     * @param \yii\base\Action $action the action to be executed
     * @return array an array of two elements. The first element is the maximum number of allowed requests,
     * and the second element is the size of the window in seconds.
     */
    public function getRateLimit($request, $action)
    {
        return [1, 5];
    }

    /**
     * Loads the number of allowed requests and the corresponding timestamp from a persistent storage.
     * @param \yii\web\Request $request the current request
     * @param \yii\base\Action $action the action to be executed
     * @return array an array of two elements. The first element is the number of allowed requests,
     * and the second element is the corresponding UNIX timestamp.
     */
    public function loadAllowance($request, $action)
    {
        return [$this->allowance, $this->allowance_updated_at];
    }

    /**
     * Saves the number of allowed requests and the corresponding timestamp to a persistent storage.
     * @param \yii\web\Request $request the current request
     * @param \yii\base\Action $action the action to be executed
     * @param integer $allowance the number of allowed requests remaining.
     * @param integer $timestamp the current timestamp.
     */
    public function saveAllowance($request, $action, $allowance, $timestamp)
    {
        $this->allowance = $allowance;
        $this->allowance_updated_at = $timestamp;
        $this->save();
    }
    ...
}

在行为中我添加了以下内容:

'rateLimiter' => [
    'class' => RateLimiter::className(),
]

到表格tbl_user我添加了两个字段:

[allowance] [int] NULL
[allowance_updated_at] [int] NULL

在本地环境中一切正常,如果用户在5秒内发出多个请求,他将看到异常yii\web\TooManyRequestsHttpException和此页面:

enter image description here

好的..接下来,我创建了两个迁移文件,并将它们应用到测试服务器和生产服务器上:

...
yii migrate/create add_allowance_column_to_tbl_user --fields=allowance:integer
yii migrate/create add_allowance_updated_at_column_to_tbl_user --fields=allowance_updated_at:integer

yii migrate
...

迁移文件:

<?php

use yii\db\Migration;

class m160722_073856_add_allowance_column_to_tbl_user extends Migration
{
    public function up()
    {
        $this->addColumn('tbl_user', 'allowance', $this->integer());
    }

    public function down()
    {
        $this->dropColumn('tbl_user', 'allowance');
    }
}

...

<?php

use yii\db\Migration;

class m160722_073932_add_allowance_updated_at_column_to_tbl_user extends Migration
{
    public function up()
    {
        $this->addColumn('tbl_user', 'allowance_updated_at', $this->integer());
    }

    public function down()
    {
        $this->dropColumn('tbl_user', 'allowance_updated_at');
    }
}

在测试服务器上,一切都运行良好。

接下来,我将解决方案移至生产服务器并遇到问题:

2016-07-22 12:17:37 [10.1.80.59][25112][snadvdlp3cb15fs9kc0j3dk5c3][error][yii\base\UnknownPropertyException] exception 'yii\base\UnknownPropertyException' with message 'Getting unknown property: common\models\User::allowance' in D:\wwwroot\aisnew\vendor\yiisoft\yii2\base\Component.php:143
Stack trace:
#0 D:\wwwroot\aisnew\vendor\yiisoft\yii2\db\BaseActiveRecord.php(247): yii\base\Component->__get('allowance')
#1 D:\wwwroot\aisnew\common\models\User.php(388): yii\db\BaseActiveRecord->__get('allowance')
#2 D:\wwwroot\aisnew\vendor\yiisoft\yii2\filters\RateLimiter.php(100): common\models\User->loadAllowance(Object(yii\web\Request), Object(yii\base\InlineAction))
#3 D:\wwwroot\aisnew\vendor\yiisoft\yii2\filters\RateLimiter.php(78): yii\filters\RateLimiter->checkRateLimit(Object(common\models\User), Object(yii\web\Request), Object(yii\web\Response), Object(yii\base\InlineAction))
#4 D:\wwwroot\aisnew\vendor\yiisoft\yii2\base\ActionFilter.php(70): yii\filters\RateLimiter->beforeAction(Object(yii\base\InlineAction))
#5 [internal function]: yii\base\ActionFilter->beforeFilter(Object(yii\base\ActionEvent))
#6 D:\wwwroot\aisnew\vendor\yiisoft\yii2\base\Component.php(541): call_user_func(Array, Object(yii\base\ActionEvent))
#7 D:\wwwroot\aisnew\vendor\yiisoft\yii2\base\Controller.php(269): yii\base\Component->trigger('beforeAction', Object(yii\base\ActionEvent))
#8 D:\wwwroot\aisnew\vendor\yiisoft\yii2\web\Controller.php(121): yii\base\Controller->beforeAction(Object(yii\base\InlineAction))
#9 D:\wwwroot\aisnew\common\components\AisUniversityController.php(22): yii\web\Controller->beforeAction(Object(yii\base\InlineAction))
#10 D:\wwwroot\aisnew\vendor\yiisoft\yii2\base\Controller.php(152): common\components\AisUniversityController->beforeAction(Object(yii\base\InlineAction))
#11 D:\wwwroot\aisnew\vendor\yiisoft\yii2\base\Module.php(454): yii\base\Controller->runAction('readyoperator', Array)
#12 D:\wwwroot\aisnew\vendor\yiisoft\yii2\web\Application.php(84): yii\base\Module->runAction('queue/queue/rea...', Array)
#13 D:\wwwroot\aisnew\vendor\yiisoft\yii2\base\Application.php(375): yii\web\Application->handleRequest(Object(yii\web\Request))
#14 D:\wwwroot\aisnew\backend\web\index.php(18): yii\base\Application->run()

我将本地/测试环境切换到工业数据库,一切正常..

可能是什么原因?

我将非常感谢这些信息。谢谢大家。

0 个答案:

没有答案