var nodePort = 3030;
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var db = require('mysql');
var dbPool = db.createPool({
host : 'localhost',
user : 'root',
password : '1234',
database : 'test',
port : 3306
});
app.use( bodyParser.json() );
app.get('/api/db', function(req, res){
res.setHeader('content-type', 'application/json');
dbPool.getConnection(function(objErr, objConn){
if(objErr){
sendError(res, 503, 'error', 'connection', objErr); //503 - Service Unavailable
}else{
objConn.query("SELECT * FROM person", function(Err, Rows, Fields){
if(Err){
sendError(res, 500, 'error', 'query', Err);
}else{
res.send({
results : 'success',
err : '',
err_type : '',
fields : Fields,
rows : Rows,
length : Rows.length
});
objConn.release();
}//else
});
}//else
});
});
/*
app.get('/api/db:id', function(req, res){
var id = req.params.id;
res.setHeader('content-type', 'application/json');
dbPool.getConnection(function(objErr, objConn){
if(objErr){
sendError(res, 503, 'error', 'connection', objErr); //503 - Service Unavailable
}else{
objConn.query("SELECT * FROM person WHERE id = ? ",[id], function(Err, Rows, Fields){
if(Err){
sendError(res, 500, 'error', 'query', Err);
}else{
res.send({
results : 'success',
err : '',
err_type : '',
fields : Fields,
rows : Rows,
length : Rows.length
});
objConn.release();
}//else
});
}//else
});
});
*/
app.post('/api/db', function(req, res){
if(!req.body.tableName){
var data = {
ID : req.body.id,
Name : req.body.name
}
tableName = 'person';
}else{
var data = {
email : req.body.email,
regid : req.body.regid
}
tableName = 'users';
}//else
console.log(req.body.regid);
console.log(req.body.tableName);
console.log(req.body.email);
res.setHeader('content-type', 'application/json');
dbPool.getConnection(function(objErr, objConn){
if(objErr){
sendError(res, 503, 'error', 'connection', objErr); //503 - Service Unavailable
}else{
objConn.query("INSERT INTO "+tableName+" SET ? ", data, function(Err, Rows, Fields){
if(Err){
sendError(res, 500, 'error', 'query', Err);
}else{
res.send({
results : 'success'
});
objConn.release();
if(!req.body.tableName){ gcmSend(); }
}//else
});
}//else
});
});
app.put('/api/db', function(req, res){
var id = req.body.id;
var data = {
Name : req.body.name
}
res.setHeader('content-type', 'application/json');
dbPool.getConnection(function(objErr, objConn){
if(objErr){
sendError(res, 503, 'error', 'connection', objErr); //503 - Service Unavailable
}else{
objConn.query("UPDATE person SET ? WHERE ID = ? ", [data,id], function(Err, Rows, Fields){
if(Err){
sendError(res, 500, 'error', 'query', Err);
}else{
res.send({
results : 'success'
});
objConn.release();
gcmSend();
}//else
});
}//else
});
});
app.delete('/api/db/:id', function(req, res){
var id = req.params.id;
res.setHeader('content-type', 'application/json');
dbPool.getConnection(function(objErr, objConn){
if(objErr){
sendError(res, 503, 'error', 'connection', objErr); //503 - Service Unavailable
}else{
objConn.query("DELETE FROM person WHERE ID = ? ",[id], function(Err, Rows, Fields){
if(Err){
sendError(res, 500, 'error', 'query', Err);
}else{
res.send({
results : 'success'
});
objConn.release();
gcmSend();
}//else
});
}//else
});
});
function gcmSend(){
message = new gcm.Message({
collapseKey: 'demo',
delayWhileIdle: true,
timeToLive: 3,
data: {
title: 'Node.js den mesaj gönderildi'
}
});
sender.send(message, registrationIds, 4, function (err, result) {
console.log(result);
});
}
function sendError(res, iStatusCode, strResult, strType, objError){
res.send({
results : strResult,
err : objError.type,
err_type : strType
});
}
app.listen(nodePort);
console.log('App listening on port' + nodePort);
您好,
我写了一些代码来连接nodejs mysql,我打开了每个操作的新连接(post,get,put,delete)和release。这很好吗?或者一个连接更好?每个操作在一个连接中的所有操作或每个操作的一个连接之间有什么区别?
答案 0 :(得分:3)
澄清 - Node.js是不单线程。您的应用程序代码在一个线程中执行,但在需要时它会使用它们 - 看看here(答案和它下面的注释):
对于node.js上的Javascript程序,只有一个线程。
如果您正在寻找技术细节,node.js可以自由使用线程 如果底层操作系统需要,解决异步I / O. 它
和
就node.js(即Javascript程序员)的用户而言 涉及,抽象是只有一个线程。在 在底层运行时(v8)的情况下,它在内部使用线程 例如 - 分析,只要它可以自由地进行分析 不会将该信息泄露给Javascript。
换句话说,如果你在实际运行时内潜入,你会 找到多个线程帮助保持单个Javascript线程 运行顺利。
正如您所看到的,您使用的mysql
模块要求您传递query()
方法的回调(可能还有更多)。因此,当您调用它时,代码的执行将继续,并且当数据库的结果到达时将调用回调。
至于您的问题 - 您没有为每个请求创建新连接。查看mysql
模块的自述文件文件Pooling Connections section:
游泳池懒洋洋地创建了连接。如果配置池 允许多达100个连接,但只能同时使用5个, 只会建立5个连接。连接也是循环的 循环式,连接从顶部开始 游泳池并返回底部。
从池中检索先前的连接时,ping数据包 被发送到服务器以检查连接是否仍然良好。
当您致电dbPool.getConnection()
时,只有在池中没有更多可用连接时才会创建连接 - 否则它只会从其顶部抓取一个连接。调用objConn.release()
会将连接释放回池中 - 它没有被断开连接。此调用允许它被应用程序的其他部分重用。
总结一下:
<强>更新强> 要回答评论中的问题:
当您为每个请求使用一个连接时,mysql
模块必须打开一个新套接字,连接到数据库并在进行查询之前进行身份验证 - 这需要时间并占用一些资源。因此,这是一个糟糕的方法。
另一方面,当仅使用一个连接(不是连接池)时,运行需要很长时间才能完成的查询将阻止该连接上的任何其他查询,直到完成为止 - 这意味着任何其他请求都必须等待。这也是一个糟糕的方法。
为每个请求创建一个新的连接池非常类似于使用新连接,除非您多次调用pool.getConnection()
- 然后情况更糟(使用创建新连接所使用的资源并繁殖它取决于pool.getConnection()
次呼叫的数量。
进一步明确每个操作的一个连接 vs 一个连接中的所有操作问题:
每个连接中的每个操作都是在前一个连接完成后启动的(它是同步的,但不是在客户端),所以如果你有一个包含几十亿行的表并发出SELECT * FROM yourtable
它将需要一些时间来完成,阻止此连接上的每个操作,直到它完成。
如果每个需要并行发出的操作都有一个连接(例如,对于每个请求),问题就会消失。但如前所述,打开新连接需要时间和资源,这就是引入连接池概念的原因。
答案是:为所有请求使用一个连接池(就像您在示例代码中所做的那样) - 连接数将相应地缩放到应用上的流量。
更新#2:
根据评论,我看到我还应该解释连接池背后的概念。它是如何工作的,你启动一个连接池为空的应用程序并初始化,以创建最多的 n 连接(默认情况下,它为mysql
模块提供10个。)< / p>
每当您致电dbPool.getConnection()
时,它会检查池中是否有可用的连接。如果它有抓取一个(使它不可用),如果没有它创建一个新的。如果达到连接限制且没有可用的连接,则会引发某种异常。
调用connection.release()
会将连接释放回池中,以便再次可用。
使用池只为整个应用程序获取一个全局连接是完全错误的并且违背了概念本身(你可以通过手动创建连接来做同样的事情),所以通过使用连接池我的意思是使用连接池,因为它应该被使用 - 在需要时从它获取连接。
答案 1 :(得分:2)
最好在不同路线上打开新连接。 有两件事,
1)您的数据库可以同时处理多个连接。
2)nodejs是单线程的。
如果为所有路由创建单个连接,则可能是数据库请求需要更长的时间才会使节点js服务器上的所有其他请求都饿死,直到处理现有请求为止,因为只有一个连接已共享通过申请。
另一方面,如果在不同的路由上使用不同的连接,那么即使单个请求对数据库执行阻塞操作,这也不会影响其他请求,因为它可以与数据库建立绝对连接
答案 2 :(得分:1)
每次使用一个连接,隐式管理您的交易。因此,结果将被提交并且对其他用户可见。 如果使用相同的连接,则必须在更新,添加或删除时提交,以使其他人可以看到。
但是,例如,如果您使用循环添加许多行;你应该考虑使用一个独特的交易;因为,数据库服务器端有一个开销来管理连接上下文和事务。
所以我的答案是:这取决于你打算在你的app中管理什么。如果您可能有批量DML,请考虑使用唯一连接。否则,您可以使用多个连接。