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

React+Node服务GET请求前几次正常后报socket hang up、代理错误

GET请求前几次正常后续失败问题排查

基础环境与初始现象

  • 技术栈:React v16.8.6、Node v12.16.2
  • 初始问题:本地与云服务器环境测试时,fetch发起的GET请求前2~3次可正常响应,后续请求直接失败。

问题复现与补充测试结果

  • Postman测试云服务器接口:所有GET接口(含/usr-info、/some-other-info、/another-info等)前几次可正常返回,之后抛出Error: socket hang up错误
  • 本地环境测试:同类请求耗时较长(约1~2分钟)但最终可正常返回
  • 浏览器直连测试:地址栏输入cloud_ip:4200/usr-info访问,前几次正常,多次刷新后返回ERR_EMPTY_RESPONSE,与之前现象一致
  • 页面交互表现:
    • 执行登录、退出操作23次后,本地环境登录按钮会禁用12分钟,云服务器环境永久处于禁用状态
    • 按钮禁用时提交账号密码,会因dbUserInfo为null无法匹配对应用户信息,抛出undefined错误
    • 报错后刷新页面触发代理错误:

Proxy error: Could not proxy request /usr-info from localhost(or cloud public ip):3000 to localhost(or cloud public ip):4200.

相关代码

1. package.json配置

{
    ...
    "proxy": "https://localhost (or cloud public ip):4200",
    ...
    "scripts": {
        "start": "env-cmd -f .env.development react-app-rewired start",
        "run": "env-cmd -f .env.development node server/index.js",
        "start:prod": "env-cmd -f .env.production react-app-wired start",
        "run:prod": "env-cmd -f .env.production node server/index.js"
    }
}

2. login.jsx核心逻辑

const login = () => {
    const [dbUserInfo, setDbUserInfo] = useState([]);

    const getData = async (route) => {
        // 校验登录信息后拉取用户信息及其他数据
        const response = await fetch(route);
        return response.json();
    }

    useEffect(() => {
        // setLoading仅用于测试,控制登录按钮禁用状态
        setLoading(true)
        getData('/usr-info').then((res) => { setDbUserInfo(res); setLoading(false); }).catch(error => console.log(error));
    }, []);
    ...
}

3. 服务端index.js核心逻辑

const express = require('express');
const mysql = require('mysql');

const conn = mysql.createPool({
    host: host,
    user: user,
    password: password,
    database: 'database'
})

const app = express();
app.use(express.json());

app.get('/usr-info', function (req, res) {
    conn.getConnection(function (err, connection) {
        connection.query('SELECT * from TABLE where COL = "VAL1"', function (error,results, fields) {
            if (error) throw error;

            res.send(results)
        });
    });
});

app.listen(4200, () => {
    console.log('server started on 4200')
})

已尝试方案

  • 已确认服务端接口配置了res.send返回逻辑
  • 尝试在handleSubmit方法中添加event.preventDefault(),未解决问题
  • 初步怀疑3000端口客户端到4200端口服务端的前序请求未释放导致服务异常,无法定位根因

根因定位

核心问题出在服务端MySQL连接池的使用逻辑:
调用conn.getConnection()从连接池获取连接后,执行完查询操作没有主动释放连接归还到连接池。几次请求后连接池的所有可用连接会被完全占满,后续请求无法获取到可用数据库连接,就会出现请求挂起、超时、socket hang up的现象,和测试表现完全吻合:

  • 本地环境等待1~2分钟后MySQL主动断开空闲连接,连接被回收后请求可正常响应
  • 云服务器环境网络代理超时时间更短,请求直接被断开返回错误

另外package.json中proxy配置为https://前缀,如果服务端Express没有配置HTTPS证书,也可能引发偶发的连接异常。

修复方案

  1. 修改服务端接口逻辑,查询完成后无论成功失败都主动释放数据库连接,同时补充错误处理逻辑,修复后代码如下:
app.get('/usr-info', function (req, res) {
    conn.getConnection(function (err, connection) {
        // 处理获取连接失败场景
        if (err) {
            console.error('获取数据库连接失败:', err);
            return res.status(500).send({msg: '服务内部错误'});
        }
        connection.query('SELECT * from TABLE where COL = "VAL1"', function (error, results, fields) {
            // 查询执行完先释放连接
            connection.release();
            if (error) {
                console.error('数据查询失败:', error);
                return res.status(500).send({msg: '数据查询失败'});
            }
            res.send(results)
        });
    });
});
  1. 优化MySQL连接池配置,根据服务器性能调整最大连接数:
const conn = mysql.createPool({
    host: host,
    user: user,
    password: password,
    database: 'database',
    connectionLimit: 20 // 按需调整,默认值为10
})
  1. 检查服务端是否开启HTTPS,若仅使用HTTP协议,将package.json中proxy配置修改为http://localhost:4200即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 22:21:37