如何让 Laravel 与 AWS 上的 Redis 集群一起工作
Posted
技术标签:
【中文标题】如何让 Laravel 与 AWS 上的 Redis 集群一起工作【英文标题】:How to make Laravel work with Redis cluster on AWS 【发布时间】:2019-10-23 04:00:34 【问题描述】:我正在尝试将 Laravel (5.4) 与 Redis 的集群版本一起使用。我按照this post 的说明进行操作,如下所示:
/*
|--------------------------------------------------------------------------
| Redis Databases
|--------------------------------------------------------------------------
|
| Redis is an open source, fast, and advanced key-value store that also
| provides a richer set of commands than a typical key-value systems
| such as APC or Memcached. Laravel makes it easy to dig right in.
|
*/
'redis' => [
'client' => 'predis',
'cluster' => 'true',
'default' => [
'host' => env('REDIS_HOST_1', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => 6379,
'database' => 0,
],
'clusters' => [
'default' => [
'host' => env('REDIS_HOST_1', '127.0.01'),
'password' => env('REDIS_PASSWORD', null),
'port' => 6379,
'database' => 0,
],
'jobs' => [
'host' => env('REDIS_HOST_2', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => 6379,
'database' => 0,
],
'content' => [
'host' => env('REDIS_HOST_3', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => 6379,
'database' => 0,
]
],
'options' => [
'cluster' => 'redis'
],
]
但我不断收到此错误
[2019-06-07 15:53:37] local.ERROR: Predis\Response\ServerException: MOVED 5873 127.0.0.1:7001 in /Users/Shared/dev/php/toters-api/vendor/predis/predis/src/Client.php:370 Stack trace:
0 /Users/Shared/dev/php/toters-api/vendor/predis/predis/src/Client.php(335): Predis\Client->onErrorResponse(Object(Predis\Command\StringGet), Object(Predis\Response\Error))
1 /Users/Shared/dev/php/toters-api/vendor/predis/predis/src/Client.php(314): Predis\Client->executeCommand(Object(Predis\Command\StringGet))
2 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Redis/Connections/Connection.php(72): Predis\Client->__call('get', Array)
3 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Redis/Connections/Connection.php(84): Illuminate\Redis\Connections\Connection->command('get', Array)
4 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Cache/RedisStore.php(54): Illuminate\Redis\Connections\Connection->__call('get', Array)
5 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Cache/Repository.php(84): Illuminate\Cache\RedisStore->get('cbwvtr3cxYIFP4H...')
6 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Cache/Repository.php(68): Illuminate\Cache\Repository->get('cbwvtr3cxYIFP4H...')
7 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php(305): Illuminate\Cache\Repository->has('cbwvtr3cxYIFP4H...')
8 /Users/Shared/dev/php/toters-api/vendor/tymon/jwt-auth/src/Providers/Storage/IlluminateCacheAdapter.php(57): Illuminate\Cache\CacheManager->__call('has', Array)
9 /Users/Shared/dev/php/toters-api/vendor/tymon/jwt-auth/src/Blacklist.php(74): Tymon\JWTAuth\Providers\Storage\IlluminateCacheAdapter->has('cbwvtr3cxYIFP4H...')
10 /Users/Shared/dev/php/toters-api/vendor/tymon/jwt-auth/src/JWTManager.php(83): Tymon\JWTAuth\Blacklist->has(Object(Tymon\JWTAuth\Payload))
11 /Users/Shared/dev/php/toters-api/vendor/tymon/jwt-auth/src/JWTAuth.php(190): Tymon\JWTAuth\JWTManager->decode(Object(Tymon\JWTAuth\Token))
12 /Users/Shared/dev/php/toters-api/vendor/tymon/jwt-auth/src/JWTAuth.php(124): Tymon\JWTAuth\JWTAuth->getPayload('eyJ0eXAiOiJKV1Q...')
13 /Users/Shared/dev/php/toters-api/app/Http/Middleware/TokenAuthentication.php(25): Tymon\JWTAuth\JWTAuth->authenticate('eyJ0eXAiOiJKV1Q...')
14 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): App\Http\Middleware\TokenAuthentication->handle(Object(Illuminate\Http\Request), Object(Closure))
15 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\closure(Object(Illuminate\Http\Request))
16 /Users/Shared/dev/php/toters-api/app/Http/Middleware/WeakEtagMiddleware.php(22): Illuminate\Routing\Pipeline->Illuminate\Routing\closure(Object(Illuminate\Http\Request))
17 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): App\Http\Middleware\WeakEtagMiddleware->handle(Object(Illuminate\Http\Request), Object(Closure))
请注意,我没有对应用程序数据进行任何更改,所以我的 Redis 代码仍然如下所示:
use Illuminate\Support\Facades\Redis;
..
Redis::set('key', 'val');
此外,如果我从上述配置中删除默认设置,使其看起来像这样:
'redis' => [
'client' => 'predis',
'cluster' => 'true',
'clusters' => [
'default' => [
'host' => env('REDIS_HOST_1', '127.0.01'),
'password' => env('REDIS_PASSWORD', null),
'port' => 6379,
'database' => 0,
],
'jobs' => [
'host' => env('REDIS_HOST_2', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => 6379,
'database' => 0,
],
'content' => [
'host' => env('REDIS_HOST_3', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => 6379,
'database' => 0,
]
],
'options' => [
'cluster' => 'redis'
],
]
我收到此错误
[2019-06-07 16:00:02] local.ERROR: Symfony\Component\Debug\Exception\FatalThrowableError: Type error: Argument 1 passed to Predis\Connection\Parameters::__construct() must be of the type array, integer given, called in /Users/Shared/dev/php/toters-api/vendor/predis/predis/src/Connection/Factory.php on line 164 in /Users/Shared/dev/php/toters-api/vendor/predis/predis/src/Connection/Parameters.php:34 Stack trace:
0 /Users/Shared/dev/php/toters-api/vendor/predis/predis/src/Connection/Factory.php(164): Predis\Connection\Parameters->__construct(6379)
1 /Users/Shared/dev/php/toters-api/vendor/predis/predis/src/Connection/Factory.php(84): Predis\Connection\Factory->createParameters(6379)
2 /Users/Shared/dev/php/toters-api/vendor/predis/predis/src/Connection/Factory.php(118): Predis\Connection\Factory->create(6379)
3 /Users/Shared/dev/php/toters-api/vendor/predis/predis/src/Client.php(135): Predis\Connection\Factory->aggregate(Object(Predis\Connection\Aggregate\RedisCluster), Array)
4 /Users/Shared/dev/php/toters-api/vendor/predis/predis/src/Client.php(56): Predis\Client->createConnection(Array)
5 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Redis/Connectors/PredisConnector.php(41): Predis\Client->__construct(Array, Array)
6 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Redis/RedisManager.php(102): Illuminate\Redis\Connectors\PredisConnector->connectToCluster(Array, Array, Array)
7 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Redis/RedisManager.php(83): Illuminate\Redis\RedisManager->resolveCluster('default')
8 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Redis/RedisManager.php(61): Illuminate\Redis\RedisManager->resolve('default')
9 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Cache/RedisStore.php(211): Illuminate\Redis\RedisManager->connection('default')
10 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Cache/RedisStore.php(54): Illuminate\Cache\RedisStore->connection()
11 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Cache/Repository.php(84): Illuminate\Cache\RedisStore->get('cbwvtr3cxYIFP4H...')
12 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Cache/Repository.php(68): Illuminate\Cache\Repository->get('cbwvtr3cxYIFP4H...')
13 /Users/Shared/dev/php/toters-api/vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php(305): Illuminate\Cache\Repository->has('cbwvtr3cxYIFP4H...')
14 /Users/Shared/dev/php/toters-api/vendor/tymon/jwt-auth/src/Providers/Storage/IlluminateCacheAdapter.php(57): Illuminate\Cache\CacheManager->__call('has', Array)
15 /Users/Shared/dev/php/toters-api/vendor/tymon/jwt-auth/src/Blacklist.php(74): Tymon\JWTAuth\Providers\Storage\IlluminateCacheAdapter->has('cbwvtr3cxYIFP4H...')
16 /Users/Shared/dev/php/toters-api/vendor/tymon/jwt-auth/src/JWTManager.php(83): Tymon\JWTAuth\Blacklist->has(Object(Tymon\JWTAuth\Payload))
17 /Users/Shared/dev/php/toters-api/vendor/tymon/jwt-auth/src/JWTAuth.php(190): Tymon\JWTAuth\JWTManager->decode(Object(Tymon\JWTAuth\Token))
所以从错误消息看来,Predis 似乎只是忽略了我的集群配置并直接从默认值读取,而默认值不知道如何处理我的集群 Redis 数据存储。想法?
【问题讨论】:
【参考方案1】:在搜索和调试之后,这就是它的工作原理:
'redis' => [
'client' => 'predis',
'cluster' => true,
'options' => [
'cluster' => 'redis',
'parameters' => [
'host' => env('REDIS_DEFAULT_HOST', '127.0.01'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_DEFAULT_PORT', 6379),
'database' => 0,
],
],
'clusters' => [
'default' => [
'host' => env('REDIS_DEFAULT_HOST', '127.0.01'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_DEFAULT_PORT', 6379),
'database' => 0,
],
'jobs' => [
'host' => env('REDIS_JOBS_HOST', '127.0.01'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_JOBS_PORT', 6379),
'database' => 0,
],
'content' => [
'host' => env('REDIS_CONTENT_HOST', '127.0.01'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_CONTENT_PORT', 6379),
'database' => 0,
],
'options' => [
'cluster' => 'redis'
],
]
]
注意:在上述问题中我的配置中的一个明显错误是我将主机和端口组合在一起,我在这里修复了它。这就是我的 .env 文件的样子:
REDIS_DEFAULT_HOST=127.0.0.1
REDIS_JOBS_HOST=127.0.0.1
REDIS_CONTENT_HOST=127.0.0.1
REDIS_DEFAULT_PORT=7000
REDIS_JOBS_PORT=7001
REDIS_CONTENT_PORT=7002
注意:我使用此处的说明创建了集群:https://redis.io/topics/cluster-tutorial#creating-the-cluster
研究方法
由于以下事实: 1. laravel/predis 缺乏这方面的文档 2. 大多数关于堆栈溢出的答案都是这样的:在谷歌搜索和搜索之后..这对我来说很有效没有太多解释发生了什么
我想我可以通过展示如何找到我对上述问题的答案来提供一些帮助。
1) 解决错误问题
解决这个问题
local.ERROR: Symfony\Component\Debug\Exception\FatalThrowableError: 类型错误:参数 1 传递给 Predis\Connection\Parameters::__construct() 必须是数组类型, 给定整数,调用 /Users/Shared/dev/php/toters-api/vendor/predis/predis/src/Connection/Factory.php 在第 164 行 /Users/Shared/dev/php/toters-api/vendor/predis/predis/src/Connection/Parameters.php:34 堆栈跟踪:
我意识到我的 config/database.php 格式完全错误。谷歌搜索并没有给我任何清晰的图片,所以我决定在代码中使用xdebug 和dive。注意:我在一个文档中打印了错误堆栈跟踪(如上面的问题所示),我用它作为鸟瞰图来指导我完成调试步骤(即单步执行/进入/退出等,同时始终打印输出在单独的文档中并将其与我的 config/database.php 进行比较,作为健全性检查/调试指南针)。
在挖掘和打印之后,我遇到了这个:
[ *Locals ] [ Superglobals ] [ User defined constants ]
- Locals at /Users/Shared/dev/php/toters-api/vendor/predis/predis/src/Client.php:55
▾ $options = (array [1])
\
⬦ $options["cluster"] = (string [5]) `redis`
/
▾ $parameters = (array [4])
\
⬦ $parameters[0] = (string [14]) `127.0.0.1:7000`
|
⬦ $parameters[1] = (null)
|
⬦ $parameters[2] = (int) 6379
|
⬦ $parameters[3] = (int) 0
/
▾ $this = (Predis\Client [3])
\
⬦ $this->connection = (null)
|
⬦ $this->options = (null)
|
⬦ $this->profile = (null)
/
我将此与我的 .env 文件的内容进行了比较:
REDIS_DEFAULT_HOST=127.0.0.1:7000
REDIS_JOBS_HOST=127.0.0.1:7001
REDIS_CONTENT_HOST=127.0.0.1:7002
我意识到格式错误,我不应该把主机和端口放在同一个环境变量中。所以我把它改成这样:
REDIS_DEFAULT_HOST=127.0.0.1
REDIS_JOBS_HOST=127.0.0.1
REDIS_CONTENT_HOST=127.0.0.1
REDIS_DEFAULT_PORT=7000
REDIS_JOBS_PORT=7001
REDIS_CONTENT_PORT=7002
这解决了我的第一个问题。
2) 解决其他问题
上述问题解决后,我得到了这个
未提供 CLUSTERDOWN 哈希槽
这很容易,只需在谷歌上搜索错误消息(因为错误消息显然是本机 redis 错误消息,而不是一些像 predis 错误消息这样的神秘库包装器).. 我找到了 @987654324 @。
剩下的很简单。
【讨论】:
最深的回答❤️以上是关于如何让 Laravel 与 AWS 上的 Redis 集群一起工作的主要内容,如果未能解决你的问题,请参考以下文章
如何在 AWS AutoScaling 中添加 Laravel 环境文件
如何让 SSL 与 Rails、AWS Elastic Beanstalk 和 Cloudflare 一起使用
AWS 应用程序负载均衡器上的 Websocket + SSL
Laravel 8 上的 League/flysystem-aws-s3-v3 其他软件包需要较低版本
AWS 服务器上的 Laravel 不返回 Set-Cookie 标头
远程 AWS EB 实例上的“php artisan migrate”上的 PHP 致命错误:laravel.log:权限被拒绝