Nodo js (getConnection)

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); 

Hola,
Escribí algunos códigos para conectar con nodejs mysql, abrí una nueva conexión en cada operación (publicar, obtener, poner, eliminar) y liberar. ¿Se acerca esto bien? o una conexión es mejor? ¿Cuál es la diferencia entre todas las operaciones en una conexión o una conexión para cada operación?

Para aclarar: Node.js no es de un solo hilo. El código de su aplicación se ejecuta en un solo hilo, pero debajo del capó los usa cuando es necesario. Eche un vistazo aquí (tanto la respuesta como los comentarios a continuación):

Para un progtwig de Javascript en node.js, solo hay un hilo.

Si busca tecnicismos, node.js es libre de usar subprocesos para resolver la E / S asíncrona si el sistema operativo subyacente lo requiere.

Y:

En lo que respecta al usuario de node.js (es decir, el progtwigdor de Javascript), la abstracción es que solo hay un único hilo. En el caso del tiempo de ejecución subyacente (v8), utiliza subprocesos internamente para, por ejemplo, perfiles, y puede hacerlo libremente siempre que no filtre esa información hasta el Javascript.

En otras palabras, si se sumerge en el tiempo de ejecución real, encontrará más de un subproceso que ayuda a mantener el único subproceso de Javascript funcionando sin problemas.

Como puede ver, el módulo mysql que utiliza requiere que pase una callback para el método query() (y probablemente para muchos más). Entonces, cuando lo llama, la ejecución de su código continúa y se llama a la callback cuando llegan los resultados de la base de datos.

En cuanto a su pregunta, no está creando una nueva conexión para cada solicitud. Eche un vistazo al archivo readme del módulo mysql , la sección Pooling Connections :

Las conexiones son perezosamente creadas por la piscina. Si configura el grupo para permitir hasta 100 conexiones, pero solo utiliza 5 simultáneamente, solo se harán 5 conexiones. Las conexiones también tienen un ciclo de estilo round-robin, las conexiones se toman desde la parte superior de la piscina y regresan a la parte inferior.

Cuando se recupera una conexión anterior del grupo, se envía un paquete de ping al servidor para verificar si la conexión sigue siendo buena.

Cuando llama a dbPool.getConnection() la conexión se crea solo si no hay más conexiones disponibles en el grupo; de lo contrario, solo toma una de la parte superior. Llamar a objConn.release() libera la conexión de nuevo al grupo, no se está desconectando. Esta llamada permite que otras partes de su aplicación la reutilicen.

Para resumir:

  • Crear una nueva conexión para cada solicitud no es una buena idea, ya que utilizará más recursos (CPU, RAM) tanto en las máquinas de su aplicación como en la de la base de datos.
  • El uso de una conexión para todas las solicitudes también es incorrecto porque si alguna de las operaciones demora mucho tiempo en completarse, la conexión se bloqueará y todas las demás solicitudes lo esperarán.
  • El uso de un grupo de conexiones es una gran idea que le permite realizar múltiples operaciones en su base de datos al mismo tiempo, incluso si una de ellas tarda mucho tiempo en completarse.

Actualización: Para responder a las preguntas de los comentarios:

Cuando utiliza una conexión para cada solicitud, el módulo mysql tiene que abrir un nuevo socket, conectarse a la base de datos y autenticarse antes de realizar su consulta. Esto requiere tiempo y consume algunos recursos. Por eso es un mal enfoque.

Por otro lado, cuando se usa solo una conexión (no el grupo de conexiones), ejecutar una consulta que tarde mucho tiempo en completarse bloqueará cualquier otra consulta en esa conexión hasta que se complete, lo que significa que cualquier otra solicitud tendrá que esperar. También es un mal enfoque.

Crear un nuevo grupo de conexiones para cada solicitud es muy parecido a usar una nueva conexión, a menos que llame a pool.getConnection() varias veces, entonces es aún peor (tome los recursos utilizados al crear una nueva conexión y multiplíquelo por el número de pool.getConnection() pool.getConnection() llamadas).

Para aclarar aún más la conexión para cada operación frente a todas las operaciones en una pregunta de conexión :

Cada operación en cada conexión se inicia después de que se complete la anterior (es síncrona, pero no en el lado del cliente), por lo que si tiene una tabla con unos pocos miles de millones de filas y emite SELECT * FROM yourtable , llevará algún tiempo completarla, bloquear Cada operación en esta conexión hasta que termine.

Si tiene una conexión para cada operación que debe emitirse en paralelo (por ejemplo, para cada solicitud), el problema desaparece. Pero como se indicó anteriormente, la apertura de una nueva conexión requiere tiempo y recursos, por lo que se introdujo el concepto de agrupación de conexiones .

Entonces, la respuesta es: use un grupo de conexiones para todas las solicitudes (como lo hace en su código de ejemplo): el número de conexiones se escalará de acuerdo con el tráfico en su aplicación.

Actualización # 2:

Basándome en los comentarios, veo que también debo explicar el concepto detrás de las agrupaciones de conexiones. Cómo funciona es que inicias una aplicación con un grupo de conexiones vacío e inicializado para crear un máximo de n conexiones (afaik it 10 para el módulo mysql por defecto).

Cada vez que llama a dbPool.getConnection() comprueba si hay alguna conexión disponible en el grupo. Si lo hay, toma uno (hace que no esté disponible), si no crea uno nuevo. Si se alcanza el límite de conexión y no hay conexiones disponibles, se genera algún tipo de excepción.

Llamar a connection.release() libera la conexión de nuevo al grupo para que esté disponible de nuevo.

El uso de un grupo para obtener solo una conexión global para una aplicación completa es totalmente incorrecto y va en contra del concepto en sí (puede hacer lo mismo simplemente creando la conexión manualmente), por lo que al usar un grupo de conexiones me refiero a usar un grupo de conexiones ya que se suponía que debía usarse para obtener conexiones cuando las necesita .

Es bueno abrir una nueva conexión en diferentes rutas. Hay dos cosas

1) su base de datos puede manejar múltiples conexiones simultáneamente.

2) nodejs es un solo hilo.

Si crea una conexión única para todas las rutas, es probable que una solicitud de base de datos que demore más en la base de datos también anule todas las demás solicitudes en el servidor de node js, hasta que se procese la solicitud existente, ya que solo existe una conexión compartida por la aplicación. .

por otro lado, si usa conexiones diferentes en rutas diferentes, incluso si se realiza una operación de locking en la base de datos con una sola solicitud, esto no afectará a otras solicitudes, ya que puede hacer conexiones de forma reducida a la base de datos.

Usando una conexión cada vez, administre implícitamente su transacción. Por lo tanto, el resultado será comprometido y visible para otros usuarios. Si usa la misma conexión, tiene que comprometerse cuando actualice, agregue o elimine para que otros la puedan ver.

Pero, si, por ejemplo, utiliza un bucle para agregar muchas filas; debe considerar utilizar una transacción única; porque, hay una sobrecarga en el lado del servidor db para administrar el contexto de conexión y las transacciones.

Así que mi respuesta es: depende de lo que planea administrar en su aplicación. Si puede tener un lote de DML, considere usar una conexión única. De lo contrario, puede utilizar varias conexiones.