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

Laravel+Socket.io+Redis本地连接失败:ECONNREFUSED ::1:6379

Laravel实时Web应用搭建问题:Socket.io+Redis+Node.js Redis连接失败

问题背景

我基于Laravel搭建实时Web应用,采用Socket.io、Redis与Node.js服务架构,但启动Node服务后,客户端连接时出现Redis连接拒绝错误,无法正常实现实时消息推送。

相关代码

server.js(Node.js服务)

var app = require('express')();

app.use(function (req, res, next) {
    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8888');

    // Request methods you wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

    // Request headers you wish to allow
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader('Access-Control-Allow-Credentials', true);

    // Pass to next layer of middleware
    next();
});

var server = require('http').Server(app);
var io = require('socket.io')(server, {
    cors: { origin: '*' },
});

var redis = require('redis');

server.listen(3000, () => {
    console.log('hel');
});

io.on('connection', async function (socket) {
    console.log('client connected');

    var redisClient = redis.createClient({
        legacyMode: true,
    });

    await redisClient.connect().catch(console.error);

    redisClient.subscribe('message');
    redisClient.on('message', function (channel, data) {
        console.log('message received');
        socket.emit(channel, data);
    });
    socket.on('disconnect', function () {
        redisClient.quit();
    });
});

Laravel控制器代码

public function store(Request $request, BaiDang $baiDang)
{
    try {
        $baiDang->create($request->all());
        if ($request->hasFile('files')) {
            foreach ($request->file('files') as $file) {
                $name = time() . rand(1, 100) . Str::random(40) . '.' . $file->extension();
                Storage::putFileAs('files', $file, $name);

                $fileData['bai_dang_id'] = DB::table('bai_dang')->max('id');
                $fileData['link'] = 'files/' . $name;

                FileBaiDang::create($fileData);
            }
        }
        Redis::connection();
        Redis::publish('message', json_encode($request->all()));
        return $this->success($baiDang, 201, 'Created');
    } catch (Exception $e) {
        //catch exception
        echo 'Message: ' . $e->getMessage();
        return $this->error(400, 'Lỗi server update không thành công');
    }
}

客户端socket.io.js代码

import { io } from 'socket.io-client';

const socket_host = '127.0.0.1';
const socket_port = '3000';
const socket = io(socket_host + ':' + socket_port);

socket.on('message', (data) => {
    console.log('aaahhahaahah');
});

已在app.js中导入:import './socket.io';

错误信息

执行node server启动Node服务后,客户端连接时输出:

client connected
Error: connect ECONNREFUSED ::1:6379
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1300:16) {
  errno: -4078,
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '::1',
  port: 6379
}

已尝试的排查

  • 检查Redis服务状态,确认服务正在运行
  • 核对Redis主机与端口配置,默认6379端口未修改
  • 尝试过多种修复方案,问题仍未解决

解决方案

1. 强制Node.js使用IPv4连接Redis

错误显示Node尝试通过IPv6地址::1连接Redis,但Redis可能未监听IPv6。修改server.js中的Redis客户端配置,明确指定IPv4地址:

var redisClient = redis.createClient({
    legacyMode: true,
    socket: {
        host: '127.0.0.1', // 强制使用IPv4
        port: 6379
    }
});

2. 检查Redis监听配置

打开Redis配置文件(通常路径为/etc/redis/redis.conf),确认以下配置:

  • 确保bind指令包含127.0.0.1,或设置为bind 0.0.0.0(允许所有IPv4连接)
  • 测试环境下可设置protected-mode no(生产环境需谨慎,建议通过其他方式限制访问)
    修改完成后重启Redis服务:
sudo systemctl restart redis

3. 验证Redis连接

在终端执行以下命令,确认Redis可通过IPv4正常访问:

redis-cli -h 127.0.0.1 -p 6379 ping

如果返回PONG说明连接正常;若执行redis-cli -h ::1 -p 6379 ping失败,说明Redis确实未监听IPv6,此时通过步骤1的配置即可解决问题。

4. 优化Redis连接复用逻辑

当前代码在每个客户端连接时创建新的Redis客户端,频繁创建销毁连接会影响性能,建议全局复用一个Redis客户端:

// 全局创建Redis客户端,仅初始化一次
var redisClient = redis.createClient({
    legacyMode: true,
    socket: {
        host: '127.0.0.1',
        port: 6379
    }
});

// 全局订阅频道,避免重复订阅
redisClient.connect().then(() => {
    redisClient.subscribe('message');
}).catch(console.error);

// 全局监听消息,广播给所有连接的客户端
redisClient.on('message', function (channel, data) {
    console.log('message received');
    io.emit(channel, data); // 广播给所有连接的socket
});

io.on('connection', async function (socket) {
    console.log('client connected');

    socket.on('disconnect', function () {
        // 无需关闭Redis连接,全局客户端供所有连接复用
    });
});

内容的提问来源于stack exchange,提问作者Võ Khương Duy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 02:37:53