Nodejs关于Http模块疑惑
Nodejs关于Http模块疑惑
我创建了一个http服务端,在接收请求函数中查找数据库里面的数据,将数据传回给客户端,当另外一个请求来临时,他要等到前面那个请求查找完数据返回客户端后,才能执行。如何解决该问题,是否要创建子进程去处理数据查询。
当然可以!你提到的问题主要是关于如何在 Node.js 中处理并发请求,特别是当你需要从数据库中查询数据并返回结果时。默认情况下,Node.js 是单线程的,这意味着如果一个请求正在处理耗时操作(如数据库查询),其他请求会被阻塞直到当前请求完成。
为了解决这个问题,你可以采用几种不同的方法:
- 使用异步操作:确保你的数据库查询是异步的,这样不会阻塞事件循环。
- 使用连接池:如果你使用的是关系型数据库(如 MySQL 或 PostgreSQL),可以考虑使用数据库连接池来管理数据库连接。
- 使用多进程或多线程:虽然不常见,但如果你的应用非常复杂且性能要求很高,可以考虑使用子进程来处理数据库查询。
示例代码
假设你使用的是 Express 框架和 MongoDB 数据库,这里是一个简单的示例:
const express = require('express');
const MongoClient = require('mongodb').MongoClient;
const app = express();
const url = 'mongodb://localhost:27017';
const dbName = 'myproject';
app.get('/data', async (req, res) => {
try {
const client = await MongoClient.connect(url);
const db = client.db(dbName);
// 异步查询数据库
const data = await db.collection('mycollection').findOne({});
res.json(data);
client.close();
} catch (err) {
console.error(err);
res.status(500).send('Internal Server Error');
}
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
解释
- 异步查询:通过
await
关键字确保数据库查询是非阻塞的。这允许其他请求在同一时间被处理。 - 连接管理:每次请求时打开和关闭数据库连接。对于生产环境,建议使用数据库连接池来管理连接,以提高性能和资源利用率。
使用连接池
如果你使用的是 MongoDB,可以考虑使用 mongodb
库的连接池功能。例如:
const { MongoClient } = require('mongodb');
const uri = 'mongodb+srv://<username>:<password>@cluster0.mongodb.net/test?retryWrites=true&w=majority';
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });
async function run() {
try {
await client.connect();
const database = client.db('myproject');
const collection = database.collection('mycollection');
app.get('/data', async (req, res) => {
const data = await collection.findOne({});
res.json(data);
});
} finally {
await client.close();
}
}
run().catch(console.dir);
这种方法可以更好地管理连接,并且更高效地处理多个并发请求。
希望这些示例能帮助你理解如何在 Node.js 中处理并发请求。如果你有更多具体需求或问题,请随时告诉我!
- 用的什么数据库客户端?它只支持同步模式?
- 如果支持异步模式。那么与数据库的连接数多少,是否只有1;查询数据量大不大?如果以上皆是,增加连接数。
用oracle,数据库的数据是亿级的,异步了也没用,还是要等待数据返回给客户端,另外一个请求才能获得请求,就像我们在http响应函数里面,计算一个长时间的计算一样。有什么好的办法吗,用child_process的话,几个请求就把CPU的用光了
数据库调试(tuning)有问题吧。亿级的数据库响应也要快。Goolge,Facebook 的数据量超亿级,响应有多快。
如楼上童鞋所言,楼主的问题在于数据库优化这块。
- 用node.js哪个oracle客户端,请明确写出来。如果路过的童鞋有相关使用经验,就能提出一些更具体的建议,不是吗。
- 首先请确认sql查询语句的执行效率,在pl/sql developer之类的oracle客户端跑一次sql语句。如果比较耗时,下面该干什么就不必说了。
- 开个网络抓包/监视工具之类,在http请求的过程中,监视与oracle数据库的连接数有多少,如果自始至终只有1,那么就如说过的,增加连接数。为什么一直强调连接数?因为连接数只有1的情况下,确实有可能阻塞。有数据库的地方,就有必要使用连接池来控制连接数。
另外,建议把sql查询、发起查询的伪代码(去掉业务逻辑!)贴出来。所谓旁观者清,当局者迷。
目测连接池的问题哈哈,肯定是程序有问题啦,
- pl/sql中执行查询需时4s+,考虑在相关的检索字段上设置索引吧,不过这与本帖的问题主旨无关。
- nodejs连接oracle的客户端模块,看来楼主是自家开发的(访问oracle的nodejs插件,目前支持windows)。结合给出的代码片段-conn没有close,就是说conn由底层的c++来维护,那么这个conn能建立多少个呢。如果只支持单连接,请考虑改进此oracle模块,支持多连接吧。单一连接同一时间只能执行一个查询,要并行执行2个查询,就得建立2个数据库连接。这也就是为什么child_process就能同时执行n个查询,因为oracle客户端模块实例化n个,可用的数据库连接也有n个。 另外conn执行查询的部分,估计也是同步执行的,在查询结束前,程序流程被卡住了?
- 换用其他oracle模块nearinfinity/node-oracle / mariano/node-db-oracle。做个对比,对自家模块的开发也是有好处的,闭门造车不可取。