You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel+Predis微服务多频道Pub/Sub报错:无效流资源

Laravel + Predis 微服务架构下Redis发布订阅报错:fclose(): supplied resource is not a valid stream resource

问题场景

  • App 1:控制器中向timeslot频道发布事件,代码如下:
Redis::connection('timeslot')->publish('timeslot/updateStatus', json_encode([
    'timeslot' => $this->timeSlot,
    'customer' => $this->file->customer_id
]));
  • App 2:订阅timeslot频道,接收事件后修改模型(此步骤正常);在模型的updated监听器中,向App 1的event频道发布Redis事件,代码如下:
static::updated(function (TimeSlot $model) {
    if($model->isDirty('state') && $model->state->value === 'booked'){
        $result = json_encode(array_merge($model->toArray(), $model->agency->toArray()));
        Redis::connection('event')->publish('timeslot/booked', $result);
    }
});

报错信息

fclose(): supplied resource is not a valid stream resource

at vendor/predis/predis/src/Connection/StreamConnection.php:247
    243▕      */
    244▕     public function disconnect()
    245▕     {
    246▕         if ($this->isConnected()) {
  ➜ 247▕             fclose($this->getResource());
    248▕             parent::disconnect();
    249▕         }
    250▕     }
    251▕ 

解决方法

1. 避免复用订阅进程的Redis连接

订阅进程的Redis连接处于长驻订阅状态,复用该连接执行发布操作会导致资源异常。手动创建新连接实例处理发布:

static::updated(function (TimeSlot $model) {
    if($model->isDirty('state') && $model->state->value === 'booked'){
        $result = json_encode(array_merge($model->toArray(), $model->agency->toArray()));
        // 新建独立连接处理发布
        $redis = new \Predis\Client(config('database.redis.event'));
        $redis->publish('timeslot/booked', $result);
        $redis->disconnect();
    }
});

2. 调整Redis连接的持久化配置

检查config/database.php中event连接的持久化设置,避免连接被意外回收:

'event' => [
    'host' => env('REDIS_EVENT_HOST', '127.0.0.1'),
    'password' => env('REDIS_EVENT_PASSWORD', null),
    'port' => env('REDIS_EVENT_PORT', '6379'),
    'database' => env('REDIS_EVENT_DB', '0'),
    'persistent' => false, // 关闭持久化,避免连接状态异常
],

3. 用队列异步执行发布操作

将发布任务放入异步队列,让独立的队列进程处理Redis发布,规避订阅进程的连接冲突:

static::updated(function (TimeSlot $model) {
    if($model->isDirty('state') && $model->state->value === 'booked'){
        $data = array_merge($model->toArray(), $model->agency->toArray());
        dispatch(new PublishTimeslotBookedEvent($data));
    }
});

// 队列任务类
class PublishTimeslotBookedEvent implements ShouldQueue
{
    public $data;

    public function __construct($data)
    {
        $this->data = $data;
    }

    public function handle()
    {
        $result = json_encode($this->data);
        Redis::connection('event')->publish('timeslot/booked', $result);
    }
}

4. 升级Predis版本

该错误可能是Predis旧版本的已知bug,升级到最新稳定版修复:

composer require predis/predis:^2.2

内容的提问来源于stack exchange,提问作者Khaled sb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 14:45:31