我正在开发一个 PHP Yii2 应用程序。我对 yii2 有一个奇怪的问题,这是我的问题。
众所周知,Yii2 元素中有一个 web\assets 文件夹,它会加载自己的 Assets 包,但是在配置负载平衡时,我发现 chrome 的开发者工具控制台抛出一些错误如下:
http://firekylin.eastasia.cloudapp.azure.com/assets/fde0fce1/css/bootstrap.css Failed to load resource: the server responded with a status of 404 (Not Found)
http://firekylin.eastasia.cloudapp.azure.com/assets/ebd0699a/css/AdminLTE.min.css Failed to load resource: the server responded with a status of 404 (Not Found)
http://firekylin.eastasia.cloudapp.azure.com/assets/5e97633a/jquery.js Failed to load resource: the server responded with a status of 404 (Not Found)
yii.js:464 Uncaught ReferenceError: jQuery is not defined(…)
http://firekylin.eastasia.cloudapp.azure.com/assets/14e563af/yii.validation.js Failed to load resource: the server responded with a status of 404 (Not Found)
http://firekylin.eastasia.cloudapp.azure.com/assets/fde0fce1/js/bootstrap.js Failed to load resource: the server responded with a status of 404 (Not Found)
yii.activeForm.js:14 Uncaught TypeError: Cannot read property 'fn' of undefined(…)
http://firekylin.eastasia.cloudapp.azure.com/assets/fde0fce1/js/bootstrap.js Failed to load resource: the server responded with a status of 404 (Not Found)
app.min.js:13 Uncaught Error: AdminLTE requires jQuery(…)
index.php:555 Uncaught ReferenceError: jQuery is not defined(…)
http://firekylin.eastasia.cloudapp.azure.com/assets/88d3a068/css/font-awesome.min.css Failed to load resource: the server responded with a status of 404 (Not Found)
http://firekylin.eastasia.cloudapp.azure.com/assets/ebd0699a/css/skins/_all-skins.min.css Failed to load resource: the server responded with a status of 404 (Not Found)
使用负载均衡ip访问是找不到js,css文件的,但是当我使用正好有Yii2应用运行的服务器ip时,网页会成功加载js,css文件:
left one is using load balance server to visit and right one is using Yii2 server to visit
有两台服务器完全运行 Yii2,它们都有自己的 web\assets 文件夹和不同的缓存:
web\assets folders in two Yii2 servers
我发现一旦我停止其中一个Yii2 Server,负载均衡服务器就会正常工作。因此,我猜测问题可能出在Yii2的web\assets文件夹。从上面两张图我们可以发现Yii2使用的是md5重命名其中的文件夹,所以可能是因为两个 Yii2 服务器的 web\assets 文件夹具有不同的命名子文件夹导致问题发生?
不过,我尝试用下面的代码解决这个问题:
<?php
$params = require(__DIR__ . '/params.php');
$config = [
'id' => 'basic',
'defaultRoute'=>'firekylin',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'components' => [
'view' => [
'theme' => [
'pathMap' => [
'@app/views' => '@app/views/dmstr/yii2-adminlte-asset/example-views/yiisoft/yii2-app'
],
],
],
'assetManager' => [
'class' => 'yii\web\AssetManager',
'forceCopy' => true,
],
'request' => [
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => '2MhlyGaaGs_uqt_apwy1jLahR_wZ8dBv',
'parsers' => [
'application/json' => 'yii\web\JsonParser',
'text/json' => 'yii\web\JsonParser',
]
],
'cache' => [
'class' => 'yii\caching\FileCache',
],
'user' => [
'identityClass' => 'app\models\OriginUser',
'enableAutoLogin' => true,
],
'errorHandler' => [
'errorAction' => 'site/error',
],
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
// send all mails to a file by default. You have to set
// 'useFileTransport' to false and configure a transport
// for the mailer to send real emails.
'useFileTransport' => true,
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'db' => require(__DIR__ . '/db.php'),
/*
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
],
],
*/
],
'params' => $params,
];
if (YII_ENV_DEV) {
$config['bootstrap'][] = 'debug';
$config['modules']['debug'] = [
'class' => 'yii\debug\Module',
];
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
'class' => 'yii\gii\Module',
];
$config['components']['assetManager']['forceCopy'] = true;
}
return $config;
和
public function beforeAction($action){
Yii::$app->assetManager->forceCopy = YII_DEBUG;
return parent::beforeAction($action);
}
我尝试使用 assetManager 或
$config['components']['assetManager']['forceCopy'] = true;
在我自己的controller中的config\web.php或者function beforeAction中禁止assets文件夹,但是没有用,请问有什么办法可以解决这个问题吗?
最佳答案
确保两台服务器上的文件路径和 yii2 核心版本相同。
扩展assetManager
类和自定义hash()
函数。 每次更改 Assets 时请记住清除 Assets 文件夹。
例如:
Class MyAssetManager extend yii\web\AssetManager{
protected function hash($path)
{
$path = is_file($path) ? dirname($path) : $path;
return sprintf('%x', crc32($path . Yii::getVersion()));
}
}
其他方式:
- 使用 hashCallback 属性:http://www.yiiframework.com/doc-2.0/yii-web-assetmanager.html# $hashCallback-详细信息
- 将负载平衡配置更改为基于 session 的路由 例如:NGINX session 持久性
- 对 Assets 使用 CDN
关于javascript - yii2 和负载均衡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40553273/