【问题标题】:Laravel + Redis Cache via SSL?通过 SSL 的 Laravel + Redis 缓存?
【发布时间】:2017-06-05 09:20:38
【问题描述】:

我正在尝试使用信息https://github.com/nrk/predis 使用 predis 1.1 和 SSL 连接到 Redis,在示例中使用了以下配置:

// Named array of connection parameters:
$client = new Predis\Client([
  'scheme' => 'tls',
  'ssl'    => ['cafile' => 'private.pem', 'verify_peer' => true],
]);

我的 Laravel 配置如下:

'redis' => [
        'client' => 'predis',
        'cluster' => env('REDIS_CLUSTER', false),

        'default' => [
            'host' => env('REDIS_HOST', 'localhost'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => 0,
        ],

        'options' => [
            'cluster' => 'redis',
            'parameters' => ['password' => env('REDIS_PASSWORD', null)],
            'scheme' => 'tls',
        ],
    ],

不幸的是,我收到以下错误:

ConnectionException in AbstractConnection.php line 155:
Error while reading line from the server. [tcp://MY_REDIS_SERVER_URL:6380]

欢迎提出建议:)

【问题讨论】:

  • 请发布您的 .env 文件。错误是它在您的 .env 中显示 MY_REDIS_SERVER_URL
  • MY_REDIS_SERVER_URL 只是 Redis 服务器的 URL。我可以通过端口 6379 访问它,但不能通过 6380。两者都应该可以访问(这是 Azure Redis 缓存,默认打开 6380)。
  • 您找到解决方案了吗?
  • 很遗憾还没有,有什么建议吗? :)
  • 这里也一样,我只是无法使用 SSL

标签: php laravel predis


【解决方案1】:

我能够让它工作!

您需要将“方案”从'options' 移动到'default'

我的工作配置:

'redis' => [
    'client' => 'predis',
    'cluster' => env('REDIS_CLUSTER', false),

    'default' => [
        'scheme' => 'tls',
        'host' => env('REDIS_HOST', 'localhost'),
        'password' => env('REDIS_PASSWORD', null),
        'port' => env('REDIS_PORT', 6379),
        'database' => 0,
    ],

    'options' => [
        'parameters' => ['password' => env('REDIS_PASSWORD', null)],
    ],
],

注意:我还从'options' 中删除了'cluster' 选项,但我不怀疑这是这个问题的成败。

在我的最终配置中,我将其更改为:'scheme' => env('REDIS_SCHEME', 'tcp'),,然后在我的 env 文件中定义了REDIS_SCHEME=tls

使用启用了 TLS 的 AWS ElastiCache 进行测试。

编辑: 上述配置仅适用于单节点 redis。如果您碰巧启用了集群 TLS,那么您将需要完全不同的配置。

'redis' => [
        'client' => 'predis',
        'cluster' => env('REDIS_CLUSTER', false),

        // Note! for single redis nodes, the default is defined here.
        // keeping it here for clusters will actually prevent the cluster config
        // from being used, it'll assume single node only.
        //'default' => [
        //    ...
        //],

        // #pro-tip, you can use the Cluster config even for single instances!
        'clusters' => [
            'default' => [
                [
                    'scheme'   => env('REDIS_SCHEME', 'tcp'),
                    'host'     => env('REDIS_HOST', 'localhost'),
                    'password' => env('REDIS_PASSWORD', null),
                    'port'     => env('REDIS_PORT', 6379),
                    'database' => env('REDIS_DATABASE', 0),
                ],
            ],
            'options' => [ // Clustering specific options
                'cluster' => 'redis', // This tells Redis Client lib to follow redirects (from cluster)
            ]
        ],
        'options' => [
            'parameters' => [ // Parameters provide defaults for the Connection Factory
                'password' => env('REDIS_PASSWORD', null), // Redirects need PW for the other nodes
                'scheme'   => env('REDIS_SCHEME', 'tcp'),  // Redirects also must match scheme
            ],
        ]
    ]

上面的解释:

  • 'client' => 'predis':指定要使用的 PHP 库 Redis 驱动程序 (predis)。
  • 'cluster' => 'redis':这告诉 Predis 假设服务器端集群。这只是意味着“跟随重定向”(例如-MOVED 响应)。与集群一起运行时,节点会以-MOVED 响应您必须要求提供特定密钥的节点。
  • 如果您没有在 Redis 集群中启用此功能,Laravel 将抛出 -MOVED 异常 1/n 次,n 是 Redis 中的节点数集群(它会很幸运并每隔一段时间询问正确的节点)
  • 'clusters' => [...] :指定节点列表,但仅设置“默认”并将其指向 AWS 'Configuration endpoint' 将使其动态找到任何/所有其他节点(推荐用于 Elasticache,因为您不知道节点何时出现'或去')。
  • 'options':对于 Laravel,可以在顶层、集群级别和节点选项中指定。 (它们在被传递给 Predis 之前在 Illuminate 中组合)
  • 'parameters':这些“覆盖”了 Predis 用于新连接的默认连接设置/假设。由于我们为“默认”连接明确设置了它们,因此不使用它们。但对于集群设置,它们至关重要。 “主”节点可能会发回重定向 (-MOVED),除非为 passwordscheme 设置参数,否则它将采用默认值,并且与新节点的新连接将失败。

【讨论】:

  • 优秀的细分!如果我错了,请有人纠正我,但是在查看 Laravel 5.5 源代码后,顶级 'cluster' => env('REDIS_CLUSTER', false), 什么也没做。要使用集群,您只需要有一个顶级 clusters 数组,并且像 @CenterOrbit 提到的那样,删除顶级 default 连接配置。如果 Laravel 找到带有连接名称的顶级键(默认为 default),它不会在 clusters 配置中查找连接。 github.com/laravel/framework/blob/5.5/src/Illuminate/Redis/…
  • @CenterOrbit 提到的每个集群 options 还要求您将关联的 options 值混入非关联的节点数组中,例如:'redis' => [ 'clusters' => [ 'default' => [ 'options' => [ 'cluster' => 'redis' ], [ 'scheme' => env('REDIS_SCHEME', 'tcp'), /* ... */ ], ], ], ]
  • A gist 具有更好的格式和更多与my previous comment 相关的信息。
【解决方案2】:

谢谢CenterOrbit!!

我可以确认第一个解决方案确实允许 Laravel 通过 TLS 连接到 Redis 服务器。在带有 TLS 的 AWS ElastiCache 上使用 Redis 3.2.6 进行测试,配置为单节点和单分片。

我还可以确认第二个解决方案确实允许 Laravel 通过 TLS 连接到 Redis 集群。在带有 TLS 的 AWS ElastiCache 上使用 Redis 3.2.6 进行测试,配置为“启用集群模式”,1 个分片,每个分片 1 个副本。

我第一次尝试实施集群解决方案时收到以下错误:

Error: Unsupported operand types

当我将“默认”设置移动到“集群”数组中时,我错过了额外的一组数组括号。

不正确

'clusters' => [
  'default' => [
    'scheme' ...
  ]
]

正确

'clusters' => [
  'default' => [
    [
      'scheme' ...
    ]
  ]
]

我希望这可以为其他人节省一些故障排除时间。

【讨论】:

    猜你喜欢
    • 2018-01-30
    • 1970-01-01
    • 1970-01-01
    • 2018-03-01
    • 2020-08-20
    • 2020-03-12
    • 2023-03-12
    • 2023-03-10
    相关资源
    最近更新 更多