Nodejs 用request发送了大量的post请求,导致node进程感觉很不稳定?

Nodejs 用request发送了大量的post请求,导致node进程感觉很不稳定?

在express框架里,使用了request发送了大量的psot请求,发现进程第二天挂掉了 代码是这样的: var request = require(‘request’); request({ url: url, //url类似http://XX.XX.XX.XX:8765 metgod: ‘post’, body: JSON.stringify(params) //post的数据 }, function(err, response, body){ return callback(err, response, body); //在回调里处理结果 });

找了下相关资料,有的说是因为没有写头部 headers: {
‘Content-Type’:‘application/x-www-form-urlencoded’, ‘Content-Length’: data.length
} 但是不写头部也能正常得到返回的结果,只是有时候会出现“socket hang up”的错误 而且也不能导致进程挂掉啊~~~ 于是自己写了个守护进程,当进程挂掉后,会自动重启,4天后发现进程是正常启动的,但是缺访问不了网站了

于是有一下几个疑问: 1、使用http.request和request有什么区别嘛,之前用过require(‘http’); 2、为什么进程会挂掉,是因为没加头部,或者是因为没有 req.end()
3、进程挂掉,是因为缓存或者log太多的原因吗?感觉很不稳定,除了守护进程外,有没有其他办法?


8 回复

Node.js 使用 request 发送大量 POST 请求时进程不稳定的问题

背景

在 Express 框架中,使用 request 库发送大量的 POST 请求时,可能会遇到进程不稳定甚至挂掉的情况。这可能是由于多种原因造成的,包括但不限于请求过多、内存泄漏、未正确处理错误等。

问题分析

  1. 使用 http.requestrequest 的区别

    • http.request 是 Node.js 原生的 HTTP 客户端 API,它提供了更底层的控制能力,但需要手动管理请求的生命周期。
    • request 是一个第三方库,简化了 HTTP 请求的编写过程,提供了更加简洁的 API。但是,request 已经不再维护,推荐使用 axiosnode-fetch 等替代库。
  2. 进程挂掉的原因

    • 没有添加头部:虽然你提到不添加头部也能正常工作,但在某些情况下(如服务器需要特定的头部信息),不添加头部可能会导致问题。
    • 没有调用 req.end():在使用原生 http.request 时,必须调用 req.end() 来结束请求。不过,对于 request 库来说,这一步已经由库内部处理了。
    • 请求过多导致资源耗尽:频繁地发起大量请求可能会导致内存不足或文件描述符耗尽,从而导致进程挂掉。
  3. 进程挂掉与缓存/日志的关系

    • 过多的缓存或日志确实可能导致进程不稳定。确保日志文件不会无限增长,并合理配置缓存策略。

解决方案

  1. 使用 axios 替代 request

    const axios = require('axios');
    
    async function sendPostRequest(url, params) {
        try {
            const response = await axios.post(url, params, {
                headers: {
                    'Content-Type': 'application/json'
                }
            });
            return response.data;
        } catch (error) {
            console.error(error);
            throw error;
        }
    }
    
    // 使用示例
    sendPostRequest('http://XX.XX.XX.XX:8765', { key: 'value' })
        .then(data => console.log(data))
        .catch(err => console.error(err));
    
  2. 限制并发请求数量

    使用 async 库来限制并发请求的数量:

    const async = require('async');
    
    const urls = Array(100).fill('http://XX.XX.XX.XX:8765');
    const params = Array(100).fill({ key: 'value' });
    
    async.eachLimit(urls, 10, (url, callback) => {
        sendPostRequest(url, params[urls.indexOf(url)])
            .then(data => {
                console.log(data);
                callback();
            })
            .catch(err => {
                console.error(err);
                callback(err);
            });
    }, err => {
        if (err) {
            console.error('An error occurred:', err);
        } else {
            console.log('All requests completed successfully');
        }
    });
    

通过这些方法,你可以更好地管理和控制你的请求,避免进程因请求过多而挂掉。


估计是keep alive的问题,用完就及时释放链接。

pool: false

metgod: 'post', met god,遇见上帝?是method吧,改过来试试

如果是大量并发的话,建议用async.parallelLimit控制下同时并发数量,太大的话是承受不住的

另外如果是提交POST请求,别把值写到body里,官方文档里有例子

request.post('http://service.com/upload', {form:{key:'value'}})
// or
request.post('http://service.com/upload').form({key:'value'})

re:第一个问题 request和http.request完全是两回事,http.request是node.js里自带的函数,request是一个比较流行的第三方npm包,集成了很多方便功能,建议楼主多看文档,文档里都有楼主不明白的问题。 这个request觉得唯一一个问题就是如果是比如说上传一个大文件,或者从读取速度快的stream pipe到写入速度慢的stream,会有大量memory leak内存泄露。之前遇到过debug了好久终于找到解决方案,提了个pull request,补上后内存占用就正常了。不过这个问题和楼主遇到的无关。楼主的问题是太马虎不细心了,也没看文档

根据你的描述,问题可能与资源管理和错误处理有关。request库已经不再维护,建议使用更现代的HTTP客户端如axiosnode-fetch。以下是一些可能的解决方案:

1. 使用更现代的HTTP客户端

使用 axios 示例:

const axios = require('axios');

async function sendPostRequest(url, params) {
    try {
        const response = await axios.post(url, params, {
            headers: {
                'Content-Type': 'application/json'
            }
        });
        return response.data;
    } catch (error) {
        console.error('Error sending POST request:', error.message);
        throw error;
    }
}

// 调用示例
sendPostRequest(url, params).then(result => {
    console.log('Response:', result);
}).catch(error => {
    console.error('Failed to get a response:', error);
});

2. 解决进程挂掉的问题

进程挂掉可能是由于以下原因:

  • 内存泄漏:确保没有内存泄漏,可以使用工具如 memwatch-next 监控内存。
  • 错误处理:确保所有异步操作都有适当的错误处理。
  • 并发限制:限制并发请求的数量以防止过多的资源消耗。

并发限制示例:

const pLimit = require('p-limit');

const limit = pLimit(10);  // 最多同时进行10个请求

async function sendPostRequest(url, params) {
    await limit(async () => {
        try {
            const response = await axios.post(url, params, {
                headers: {
                    'Content-Type': 'application/json'
                }
            });
            return response.data;
        } catch (error) {
            console.error('Error sending POST request:', error.message);
            throw error;
        }
    });
}

// 调用示例
Promise.all([
    sendPostRequest(url1, params1),
    sendPostRequest(url2, params2)
]).then(results => {
    console.log('All responses:', results);
}).catch(error => {
    console.error('Failed to get all responses:', error);
});

3. 进程稳定性的其他建议

  • 日志记录:使用详细的日志记录来追踪错误和性能瓶颈。
  • 环境配置:确保生产环境有足够的资源(CPU、内存)。

通过这些方法,你应该能够解决进程不稳定的问题并提高应用程序的稳定性。

回到顶部