-feat: Implementación robusta de monitoreo de pool de conexiones y peticiones activas -Este commit resuelve problemas críticos en el monitoreo del pool de conexiones (C3P0) y el conteo de peticiones activas por base de datos, mejorando significativamente la visibilidad y fiabilidad del rendimiento del servidor jRDC2-Multi. -Problemas Identificados y Resueltos: -1. **Métricas de `BusyConnections` y `TotalConnections` inconsistentes o siempre en `0` en el `Manager` y `query_logs`:** * **Problema**: Anteriormente, la métrica `busy_connections` en `query_logs` a menudo reportaba `0` o no reflejaba el estado real. De manera similar, el panel de `Manager?command=totalcon` consistentemente mostraba `BusyConnections: 0` y `TotalConnections` estancadas en `InitialPoolSize`, a pesar de que Oracle sí reportaba conexiones activas. Esto generaba confusión sobre el uso real y la expansión del pool. * **Solución**: Se modificó la lógica en los *handlers* (`DBHandlerJSON.bas` y `DBHandlerB4X.bas`) para capturar la métrica `BusyConnections` directamente del pool de C3P0 **inmediatamente después de que el *handler* adquiere una conexión** (`con = Connector.GetConnection(finalDbKey)`). Este valor se pasa explícitamente a la subrutina `Main.LogQueryPerformance` para su registro en `query_logs` y para ser consumido por `Manager.bas` a través de `RDCConnector.GetPoolStats`. Esto garantiza que el valor registrado y reportado refleje con precisión el número de conexiones activas en el instante de su adquisición. Pruebas exhaustivas confirmaron que C3P0 sí reporta conexiones ocupadas y sí expande `TotalConnections` hasta `MaxPoolSize` cuando la demanda lo exige. -2. **Contador `handler_active_requests` no decrementaba correctamente:** * **Problema**: El contador de peticiones activas por base de datos (`GlobalParameters.ActiveRequestsCountByDB`) no mostraba un decremento consistente, resultando en un conteo que solo aumentaba o mostraba valores erráticos en los logs. * **Solución**: * Se aseguró la declaración `Public ActiveRequestsCountByDB As Map` en `GlobalParameters.bas`. * Se garantizó su inicialización como un `srvr.CreateThreadSafeMap` en `Main.AppStart` para un manejo concurrente seguro de los contadores. * En `DBHandlerJSON.bas`, la `dbKey` (obtenida del parámetro `dbx` del JSON) ahora se resuelve *antes* de incrementar el contador, asegurando que el incremento y el decremento se apliquen siempre a la misma clave de base de datos correcta. * Se implementó una coerción explícita a `Int` (`.As(Int)`) para todas las operaciones de lectura y escritura (`GetDefault`, `Put`) en `GlobalParameters.ActiveRequestsCountByDB`, resolviendo problemas de tipo que causaban inconsistencias y el fallo en el decremento. * La lógica de decremento en `Private Sub CleanupAndLog` (presente en ambos *handlers*) se hizo más robusta, verificando que el contador sea mayor que cero antes de decrementar para evitar valores negativos. -Beneficios de estos Cambios: * **Monitoreo Preciso y Fiable**: Las métricas `busy_connections` y `handler_active_requests` en `query_logs` y el panel `Manager` ahora son totalmente fiables, proporcionando una visión clara y en tiempo real del uso del pool de conexiones y la carga de peticiones activas por base de datos. * **Diagnóstico Mejorado**: La visibilidad interna del estado del pool de C3P0 durante las pruebas confirma que la configuración de `RDCConnector` es correcta y que el pool se expande y contrae según lo esperado por la demanda. * **Robustez del Código**: La gestión de contadores de peticiones activas es ahora consistente, thread-safe y a prueba de fallos de tipo, mejorando la estabilidad general del servidor bajo carga.
Servidor jRDC2-Multi Mod (B4J)
1. Introducción
Este proyecto es una versión modificada del servidor jRDC2 original, diseñada para actuar como un backend robusto y flexible. Su función principal es recibir peticiones HTTP, ejecutar comandos SQL predefinidos contra una base de datos y devolver los resultados en un formato estructurado.
Ha sido adaptado para servir tanto a clientes nativos (B4A/B4i) como a clientes web modernos (JavaScript, a través de frameworks como NodeJS, React, Vue, Angular, etc.).
2. Características Principales
- Soporte para Múltiples Bases de Datos: Puede cargar y gestionar hasta 4 archivos de configuración (
config.properties) simultáneamente. - Comandos SQL Externalizados: Las sentencias SQL se definen en los archivos de configuración, permitiendo modificarlas sin recompilar el servidor.
- Doble Handler de Peticiones: Incluye un handler clásico para clientes B4X y un handler JSON para clientes web.
- Validaciones de Seguridad: Verifica la existencia de comandos y la correspondencia en el número de parámetros antes de la ejecución.
- Administración Remota: Permite verificar el estado, recargar la configuración y reiniciar el servidor a través de URLs específicas, con un sistema de autenticación.
3. Configuración
3.1. Archivos de Configuración
El sistema está preparado para manejar hasta cuatro configuraciones de bases de datos (de DB1 a DB4). No es necesario tener los cuatro archivos; el servidor cargará únicamente los que encuentre.
La nomenclatura de los archivos es fundamental:
config.properties(paraDB1)config.DB2.propertiesconfig.DB3.propertiesconfig.DB4.properties
Notas importantes:
- El puerto del servidor se toma únicamente del archivo principal
config.properties, sin importar lo que digan los demás. - Los datos de conexión (
JdbcUrl,usuario,contraseña) sí se toman del archivo correspondiente a cada base de datos.
3.2. Añadir Drivers de Bases de Datos Adicionales
Si necesitas conectarte a otros tipos de bases de datos (ej. Oracle), debes agregar el archivo del controlador .jar al proyecto antes de compilar. En el módulo Main, añade una línea como la siguiente:
' Este es el nombre del archivo .jar, en este caso "C:\\Ruta\\LibsAdicionales\\ojdbc11.jar"
#AdditionalJar: ojdbc11
Al compilar, el driver se incluirá en el .jar final del servidor, por lo que no será necesario copiarlo por separado al directorio de producción.
4. Validaciones de Seguridad
El servidor realiza dos comprobaciones automáticas en ambos handlers (B4X y JSON) antes de ejecutar cualquier consulta:
-
Verificación de Existencia del Comando: El servidor comprueba que el nombre del comando SQL solicitado (ej.
"get_user") exista como una clave válida en el archivo.propertiescorrespondiente. Si no lo encuentra, devolverá un error y no intentará ejecutar nada. -
Conteo de Parámetros: Si el comando SQL en el archivo de configuración espera parámetros (contiene
?), el servidor cuenta cuántos son y lo compara con el número de parámetros recibidos en la petición. Si las cantidades no coinciden, devolverá un error específico, evitando una ejecución fallida en la base de datos.
Estas validaciones aseguran que el desarrollador reciba feedback inmediato y claro si una petición está mal formada.
5. Uso del Handler Clásico (Para Clientes B4X)
Este handler mantiene la compatibilidad con DBRequestManager. La selección de la base de datos se realiza dinámicamente a través de la URL.
- Para
config.properties=>http://tu-dominio.com:8090 - Para
config.DB2.properties=>http://tu-dominio.com:8090/DB2 - Para
config.DB3.properties=>http://tu-dominio.com:8090/DB3 - Para
config.DB4.properties=>http://tu-dominio.com:8090/DB4
6. Uso del DBHandlerJSON (Para Clientes Web)
Este handler está diseñado para clientes que se comunican vía JSON, como aplicaciones web JavaScript.
6.1. Endpoint y Métodos de Envío
Las peticiones van dirigidas al endpoint /DBJ. El handler es flexible y acepta datos de dos maneras:
Método Recomendado: POST con Body JSON
- Método HTTP: POST
- URL:
http://tu-dominio.com:8090/DBJ - Header Requerido:
Content-Type: application/json - Body (Payload): El objeto JSON se envía directamente en el cuerpo de la petición.
Ejemplo de Body:
{
"dbx": "DB2",
"query": "get_user",
"exec": "executeQuery",
"params": [
"CDAZA"
]
}
Método Legacy: GET con Parámetro j
- Método HTTP: GET
- URL: El JSON completo se envía como el valor del parámetro
jen la URL.
Ejemplo con GET:
http://tu-dominio.com:8090/DBJ?j={"dbx":"DB2","query":"get_user","exec":"executeQuery","params":["CDAZA"]}
6.2. Formato del Payload JSON
La estructura del objeto JSON es la misma para ambos métodos:
{
"exec": "executeQuery",
"query": "nombre_del_comando_sql",
"dbx": "DB1",
"params": [
"valor1",
123
]
}
exec:"executeQuery"(paraSELECT) o"executeCommand"(paraINSERT,UPDATE,DELETE).query: Nombre del comando SQL tal como está definido en el archivo de configuración.dbx(opcional): La llave de la base de datos (DB1,DB2, etc.). Si se omite, se usará DB1.params(opcional): Un array que contiene los parámetros para la consulta SQL, en el orden exacto que se esperan.
6.3. Respuestas JSON
Las respuestas del servidor siempre son en formato JSON e incluyen un campo booleano success.
- Si
successestrue, los datos se encontrarán en la llaveresult. - Si
successesfalse, el mensaje de error se encontrará en la llaveerror.
7. Administración del Servidor
Se pueden ejecutar comandos de gestión directamente desde un navegador o una herramienta como cURL.
7.1. Comandos de Administración
Comandos Públicos (sin autenticación)
- Verificar Conectividad:
http://tu-dominio.com:8090/ping- Responde con un simple
PONGy lahorapara confirmar que el servidor está en línea.
- Responde con un simple
- Verificar Estado Detallado:
http://tu-dominio.com:8090/test- Muestra información sobre las conexiones a la base de datos y el estado general.
Comandos Protegidos (requieren autenticación)
- Recargar Configuración:
http://tu-dominio.com:8090/manager?command=reload(Vuelve a leer todos los archivosconfig.*.propertiessin reiniciar el servidor). - Reiniciar Servidor (Estándar):
http://tu-dominio.com:8090/manager?command=rsx(Ejecuta los scriptsstart.bat,start2.batystop.bat). - Reiniciar Servidor (con PM2):
http://tu-dominio.com:8090/manager?command=rpm2(EjecutareiniciaProcesoPM2.baty asume que el nombre del proceso es "RDC-Multi". Modificar el.batsi el nombre es diferente).