En esta página se describe el concepto avanzado de sesiones en Spanner, incluidas las prácticas recomendadas para las sesiones al crear una biblioteca de cliente, usar las APIs REST o RPC, o usar las bibliotecas de cliente de Google.
Una sesión representa un canal de comunicación con el servicio de base de datos de Spanner. Una sesión se usa para realizar transacciones que leen, escriben o modifican datos en una base de datos de Spanner. Cada sesión se aplica a una sola base de datos.
Las sesiones pueden ejecutar una o varias transacciones a la vez. Cuando se realizan varias transacciones, la sesión se denomina sesión multiplexada. Las lecturas, escrituras y consultas independientes usan una transacción internamente.
Ventajas de rendimiento de un grupo de sesiones
Crear una sesión resulta caro. Para evitar el coste de rendimiento cada vez que se realiza una operación de base de datos, los clientes deben mantener un grupo de sesiones, que es un grupo de sesiones disponibles listas para usarse. El grupo debe almacenar las sesiones existentes y devolver el tipo de sesión adecuado cuando se solicite, así como gestionar la limpieza de las sesiones no utilizadas. Para ver un ejemplo de cómo implementar un grupo de sesiones, consulta el código fuente de una de las bibliotecas de cliente de Spanner, como la biblioteca de cliente de Go o la biblioteca de cliente de Java.
Las sesiones están diseñadas para durar mucho tiempo, por lo que, después de usar una sesión para una operación de base de datos, el cliente debe devolverla al grupo para que se pueda reutilizar.
Información general sobre los canales de gRPC
El cliente de Spanner usa canales gRPC para comunicarse. Un canal gRPC es aproximadamente equivalente a una conexión TCP. Un canal gRPC puede gestionar hasta 100 solicitudes simultáneas. Esto significa que una aplicación necesitará al menos tantos canales gRPC como el número de solicitudes simultáneas que vaya a ejecutar, dividido entre 100.
El cliente de Spanner crea un grupo de canales gRPC cuando lo creas.
Prácticas recomendadas al usar bibliotecas de cliente de Google
A continuación, se describen las prácticas recomendadas al usar las bibliotecas de cliente de Google para Spanner.
Configurar el número de sesiones y canales gRPC en los grupos
Las bibliotecas de cliente tienen un número predeterminado de sesiones en el grupo de sesiones y un número predeterminado de canales gRPC en el grupo de canales. Ambos valores predeterminados son adecuados para la mayoría de los casos. A continuación, se indican los valores predeterminados de las sesiones mínimas y máximas, así como el número predeterminado de canales gRPC para cada lenguaje de programación.
C++
MinSessions: 100
MaxSessions: 400
NumChannels: 4
C#
MinSessions: 100
MaxSessions: 400
NumChannels: 4
Go
MinSessions: 100
MaxSessions: 400
NumChannels: 4
Java
MinSessions: 100
MaxSessions: 400
NumChannels: 4
Node.js
El cliente de Node.js no admite varios canales gRPC. Por lo tanto, se recomienda crear varios clientes en lugar de aumentar el tamaño del grupo de sesiones a más de 100 sesiones para un solo cliente.
MinSessions: 25
MaxSessions: 100
PHP
El cliente de PHP no admite un número configurable de canales gRPC.
MinSessions: 1
MaxSessions: 500
Python
Python admite cuatro tipos de grupos de sesiones que puedes usar para gestionar sesiones.
Ruby
El cliente de Ruby no admite varios canales gRPC. Por lo tanto, se recomienda crear varios clientes en lugar de aumentar el tamaño del grupo de sesiones a más de 100 sesiones para un solo cliente.
MinSessions: 10
MaxSessions: 100
El número de sesiones que usa tu aplicación es igual al número de transacciones simultáneas que ejecuta. Solo debes modificar la configuración predeterminada del grupo de sesiones si esperas que una sola instancia de aplicación ejecute más transacciones simultáneas de las que puede gestionar el grupo de sesiones predeterminado.
En el caso de las aplicaciones con alta simultaneidad, se recomienda lo siguiente:
- Asigna a
MinSessions
el número de transacciones simultáneas que se espera que ejecute un solo cliente. - Define
MaxSessions
como el número máximo de transacciones simultáneas que puede ejecutar un solo cliente. - Define
MinSessions=MaxSessions
si la simultaneidad esperada no cambia mucho durante el ciclo de vida de la aplicación. De esta forma, se evita que el grupo de sesiones aumente o disminuya. Aumentar o reducir la escala del grupo de sesiones también consume algunos recursos. - Asigna el valor
MaxSessions / 100
aNumChannels
. Un canal gRPC puede gestionar hasta 100 solicitudes simultáneamente. Aumente este valor si observa una latencia de cola alta (latencia p95/p99), ya que podría ser un indicador de congestión del canal gRPC.
Si aumenta el número de sesiones activas, se usarán recursos adicionales en el servicio de base de datos de Spanner y en la biblioteca de cliente. Si aumentas el número de sesiones más allá de las necesidades reales de la aplicación, el rendimiento del sistema podría verse reducido.
Aumentar el número de sesiones en lugar del número de clientes
El tamaño del grupo de sesiones de una aplicación determina el número de transacciones simultáneas que puede ejecutar una sola instancia de la aplicación. No se recomienda aumentar el tamaño del grupo de sesiones por encima de la simultaneidad máxima que puede gestionar una sola instancia de la aplicación. Si la aplicación recibe una ráfaga de solicitudes que supera el número de sesiones del grupo, las solicitudes se ponen en cola mientras esperan a que haya una sesión disponible.
La biblioteca de cliente consume los siguientes recursos:
- Cada canal de gRPC usa una conexión TCP.
- Cada invocación de gRPC requiere un subproceso. El número máximo de hilos que usa la biblioteca cliente es igual al número máximo de consultas simultáneas que ejecuta la aplicación. Estos hilos se añaden a los que usa la aplicación para su propia lógica empresarial.
No se recomienda aumentar el tamaño del grupo de sesiones por encima del número máximo de hilos que puede gestionar una sola instancia de la aplicación. En su lugar, aumenta el número de instancias de la aplicación.
Gestionar la fracción de sesiones de escritura
En algunas bibliotecas de cliente, Spanner reserva una parte de las sesiones para las transacciones de lectura y escritura, denominada fracción de sesiones de escritura. Si tu aplicación agota todas las sesiones de lectura, Spanner usará las sesiones de lectura y escritura, incluso para las transacciones de solo lectura. Las sesiones de lectura y escritura requieren spanner.databases.beginOrRollbackReadWriteTransaction
. Si el usuario tiene el rol de gestión de identidades y accesos spanner.databaseReader
, la llamada fallará y Spanner devolverá este mensaje de error:
generic::permission_denied: Resource %resource% is missing IAM permission:
spanner.databases.beginOrRollbackReadWriteTransaction
En el caso de las bibliotecas de cliente que mantienen una fracción de sesiones de escritura, puede definir la fracción de sesiones de escritura.
C++
Todas las sesiones de C++ son iguales. No hay sesiones de solo lectura ni de lectura y escritura.
C#
La fracción de sesiones de escritura predeterminada de C# es 0,2. Puedes cambiar la fracción con el campo WriteSessionsFraction de SessionPoolOptions
.
Go
Todas las sesiones de Go son iguales. No hay sesiones de solo lectura ni de lectura y escritura.
Java
Todas las sesiones de Java son iguales. No hay sesiones de solo lectura ni de lectura y escritura.
Node.js
Todas las sesiones de Node.js son iguales. No hay sesiones de solo lectura ni de lectura y escritura.
PHP
Todas las sesiones de PHP son iguales. No hay sesiones de solo lectura ni de lectura y escritura.
Python
Python admite cuatro tipos de grupos de sesiones que puedes usar para gestionar sesiones de lectura y de lectura y escritura.
Ruby
La fracción de sesiones de escritura predeterminada de Ruby es 0,3. Puedes cambiar la fracción con el método de inicialización client.
Prácticas recomendadas al crear una biblioteca de cliente o usar REST/RPC
A continuación, se describen las prácticas recomendadas para implementar sesiones en una biblioteca de cliente de Spanner o para usar sesiones con las APIs REST o RPC.
Estas prácticas recomendadas solo se aplican si desarrollas una biblioteca de cliente o si usas APIs REST o RPC. Si usas una de las bibliotecas de cliente de Google para Spanner, consulta las prácticas recomendadas para usar bibliotecas de cliente de Google.
Crear y dimensionar el grupo de sesiones
Para determinar el tamaño óptimo del grupo de sesiones de un proceso de cliente, defina el límite inferior como el número de transacciones simultáneas previstas y el límite superior como un número de prueba inicial, como 100. Si el límite superior no es adecuado, auméntalo. Si aumenta el número de sesiones activas, se utilizarán recursos adicionales en el servicio de base de datos de Spanner, por lo que, si no se eliminan las sesiones que no se usan, el rendimiento puede verse afectado. Si los usuarios trabajan con la API RPC, recomendamos que no haya más de 100 sesiones por canal gRPC.
Gestionar sesiones eliminadas
Hay tres formas de eliminar una sesión:
- Un cliente puede eliminar una sesión.
- El servicio de base de datos de Spanner puede eliminar una sesión cuando esté inactiva durante más de una hora.
- El servicio de base de datos de Spanner puede eliminar una sesión si tiene más de 28 días.
Si se intenta usar una sesión eliminada, se produce un error NOT_FOUND
. Si se produce este error, crea y usa una sesión nueva, añádela al grupo y elimina la sesión que has eliminado del grupo.
Conservar una sesión inactiva
El servicio de base de datos de Spanner se reserva el derecho de eliminar una sesión que no se utilice. Si definitivamente necesitas conservar una sesión inactiva, por ejemplo, si se espera un aumento significativo en el uso de la base de datos a corto plazo, podrás evitar que la sesión se elimine. Realiza una operación económica, como
ejecutar la consulta SQL SELECT 1
, para mantener activa la sesión. Si tienes una sesión inactiva que no necesitas a corto plazo, deja que Spanner la elimine y crea una nueva la próxima vez que necesites una.
Se requerirá conservar todas las sesiones en casos como la gestión de una la demanda máxima habitual en la base de datos. Si el uso intensivo de la base de datos se produce todos los días de 9:00 a 18:00, deberás conservar algunas sesiones inactivas durante ese periodo, ya que es probable que se necesiten para alcanzar el uso máximo. Después de las 18:00, puedes dejar que Spanner elimine las sesiones inactivas. Crea algunas sesiones nuevas todos los días antes de las 9:00 para que estén listas para afrontar la demanda esperada.
Otro caso es si tienes una aplicación que usa Spanner, pero debe evitar la sobrecarga de conexión cuando lo hace. Puedes conservar un conjunto de sesiones para evitar la sobrecarga de la conexión.
Ocultar detalles de la sesión del usuario de la biblioteca cliente
Si vas a crear una biblioteca de cliente, no expongas las sesiones al consumidor de la biblioteca de cliente. Permite que el cliente realice llamadas a bases de datos sin la dificultad de tener que crear y mantener sesiones. Para ver un ejemplo de una biblioteca de cliente que oculta los detalles de la sesión al consumidor de la biblioteca de cliente, consulta la biblioteca de cliente de Spanner para Java.
Gestionar errores de transacciones de escritura que no son idempotentes
Las transacciones de escritura sin protección de reproducción pueden dar lugar a mutaciones en más de una ocasión.
Si una mutación no es idempotente, aplicarla en más de una ocasión podría provocar un fallo. Por ejemplo, una inserción puede fallar con
ALREADY_EXISTS
aunque la fila no existiera antes del
intento de escritura. Esto podría ocurrir si el servidor backend aplica la mutación, pero no puede informar de la realización correcta al cliente. En ese caso, se podría volver a intentar la mutación, lo que provocaría un error ALREADY_EXISTS
.
Estas son algunas formas posibles de afrontar esta situación cuando despliegas tu propia biblioteca cliente o usas la API REST:
- Estructura tus escrituras para que sean idempotentes.
- Usa escrituras con protección de reproducción.
- Implementa un método que realice una lógica de "upsert": insertar si es nuevo o actualizar si ya existe.
- Gestionar el error en nombre del cliente.
Mantener conexiones estables
Para obtener el mejor rendimiento, la conexión que uses para alojar una sesión debe mantenerse estable. Cuando cambia la conexión que aloja una sesión, Spanner puede anular la transacción activa en la sesión y provocar una pequeña carga adicional en la base de datos mientras actualiza los metadatos de la sesión. No pasa nada si algunas conexiones cambian de forma esporádica, pero debes evitar situaciones que provoquen que cambie un gran número de conexiones al mismo tiempo. Si usas un proxy entre el cliente y Spanner, debes mantener la estabilidad de la conexión en cada sesión.
Monitorizar sesiones activas
Puedes usar el comando ListSessions
para monitorizar las sesiones activas de tu base de datos desde la línea de comandos, con la API REST o con la API RPC. ListSessions
muestra las sesiones activas de una base de datos determinada. Esto resulta útil si necesitas encontrar la causa de una fuga de sesión. Una fuga de sesiones es un incidente en el que se crean sesiones, pero no se devuelven a un grupo de sesiones para reutilizarse.
ListSessions
te permite ver metadatos sobre tus sesiones activas, como cuándo se creó una sesión y cuándo se usó por última vez. Analizar estos datos te ayudará a
orientarte a la hora de solucionar problemas con las sesiones. Si la mayoría de las sesiones activas no tienen un approximate_last_use_time
reciente, puede que tu aplicación no esté reutilizando las sesiones correctamente. Consulta la referencia de la API RPC para obtener más información sobre el campo approximate_last_use_time
.
Para obtener más información sobre el uso de ListSessions
, consulta la referencia de la API REST, la referencia de la API RPC o la referencia de la herramienta de línea de comandos gcloud.
Limpieza automática de fugas de sesiones
Cuando usas todas las sesiones de tu grupo de sesiones, cada nueva transacción espera hasta que se devuelva una sesión al grupo. Cuando se crean sesiones, pero no se devuelven al grupo de sesiones para reutilizarlas, se produce una fuga de sesiones. Cuando se produce una fuga de sesión, las transacciones que esperan una sesión abierta se quedan bloqueadas indefinidamente y bloquean la aplicación. Las fugas de sesiones suelen deberse a transacciones problemáticas que se ejecutan durante un tiempo extremadamente largo y no se confirman.
Puedes configurar tu grupo de sesiones para que resuelva automáticamente estas transacciones inactivas. Si habilita la biblioteca de cliente para que resuelva automáticamente las transiciones inactivas, se identificarán las transacciones problemáticas que puedan provocar una fuga de sesión, se eliminarán del grupo de sesiones y se sustituirán por una nueva sesión.
El registro también puede ayudar a identificar estas transacciones problemáticas. Si el registro está habilitado, los registros de advertencia se comparten de forma predeterminada cuando se utiliza más del 95% de tu grupo de sesiones. Si el uso de sesiones es superior al 95%, debe aumentar el número máximo de sesiones permitidas en su grupo de sesiones o puede que tenga una fuga de sesiones. Los registros de advertencia contienen seguimientos de pila de transacciones que se ejecutan durante más tiempo del esperado y pueden ayudar a identificar la causa de la alta utilización del grupo de sesiones. Los registros de advertencia se envían en función de la configuración del exportador de registros.
Habilitar la biblioteca de cliente para que resuelva automáticamente las transacciones inactivas
Puedes habilitar la biblioteca de cliente para que envíe registros de advertencia y resuelva automáticamente las transacciones inactivas, o bien habilitarla para que solo reciba registros de advertencia.
Java
Para recibir registros de advertencia y eliminar transacciones inactivas, usa setWarnAndCloseIfInactiveTransactions
.
final SessionPoolOptions sessionPoolOptions = SessionPoolOptions.newBuilder().setWarnAndCloseIfInactiveTransactions().build()
final Spanner spanner =
SpannerOptions.newBuilder()
.setSessionPoolOption(sessionPoolOptions)
.build()
.getService();
final DatabaseClient client = spanner.getDatabaseClient(databaseId);
Para recibir solo los registros de advertencia, usa
setWarnIfInactiveTransactions
.
final SessionPoolOptions sessionPoolOptions = SessionPoolOptions.newBuilder().setWarnIfInactiveTransactions().build()
final Spanner spanner =
SpannerOptions.newBuilder()
.setSessionPoolOption(sessionPoolOptions)
.build()
.getService();
final DatabaseClient client = spanner.getDatabaseClient(databaseId);
Go
Para recibir registros de advertencia y eliminar transacciones inactivas, usa
SessionPoolConfig
con InactiveTransactionRemovalOptions
.
client, err := spanner.NewClientWithConfig(
ctx, database, spanner.ClientConfig{SessionPoolConfig: spanner.SessionPoolConfig{
InactiveTransactionRemovalOptions: spanner.InactiveTransactionRemovalOptions{
ActionOnInactiveTransaction: spanner.WarnAndClose,
}
}},
)
if err != nil {
return err
}
defer client.Close()
Para recibir solo los registros de advertencia, usa customLogger
.
customLogger := log.New(os.Stdout, "spanner-client: ", log.Lshortfile)
// Create a logger instance using the golang log package
cfg := spanner.ClientConfig{
Logger: customLogger,
}
client, err := spanner.NewClientWithConfig(ctx, db, cfg)
Sesiones multiplexadas
Las sesiones multiplexadas te permiten crear un gran número de solicitudes simultáneas en una sola sesión. Una sesión multiplexada es un identificador que usas en varios canales gRPC. No introduce ningún cuello de botella adicional. Las sesiones multiplexadas tienen las siguientes ventajas:
- Se ha reducido el consumo de recursos del backend gracias a un protocolo de gestión de sesiones más sencillo. Por ejemplo, evitan las actividades de mantenimiento de sesiones asociadas al mantenimiento de la propiedad de la sesión y a la recogida de elementos no utilizados.
- Sesión de larga duración que no requiere solicitudes keep-alive cuando está inactiva.
Las sesiones multiplexadas se admiten en los siguientes casos:
- Las bibliotecas de cliente de Java, Go, Node y Python.
Herramientas del ecosistema de Spanner que dependen de las bibliotecas de cliente mencionadas, como PGAdapter, JDBC, Hibernate, el controlador database/sql, el controlador dbAPI y GORM.
Herramientas del ecosistema de Spanner que dependen de las bibliotecas de clientes de Java y Go, como PGAdapter, JDBC, Hibernate, controladores de bases de datos o SQL, y GORM. Puede usar las métricas de OpenTelemetry para ver cómo se divide el tráfico entre el grupo de sesiones actual y la sesión multiplexada. OpenTelemetry tiene un filtro de métricas,
is_multiplexed
, que muestra las sesiones multiplexadas cuando se define entrue
.
Las sesiones multiplexadas se admiten en todos los tipos de transacciones.
Las bibliotecas de cliente rotan las sesiones multiplexadas cada 7 días para evitar enviar transacciones en sesiones obsoletas.
Las sesiones multiplexadas están habilitadas de forma predeterminada en algunas bibliotecas de cliente. En el resto de los casos, debes usar variables de entorno para habilitarlas. Para obtener más información, consulta Habilitar sesiones multiplexadas.
Cuestiones importantes
Si intentas confirmar un cuerpo de transacción de lectura o escritura vacío, o una transacción en la que se ha producido un error en todas las consultas o instrucciones DML, hay un par de situaciones que debes tener en cuenta con las sesiones multiplexadas. Las sesiones multiplexadas requieren que incluyas un token de pre-confirmación generado por el servidor en cada solicitud de confirmación. En las transacciones que contengan consultas o DML, debe haber al menos una consulta o transacción DML anterior correcta para que el servidor envíe un token válido a la biblioteca cliente. Si no se han realizado consultas ni transacciones DML correctamente, la biblioteca cliente añade SELECT 1
de forma implícita antes de una confirmación.
En el caso de una transacción de lectura o escritura en una sesión multiplexada que solo tenga mutaciones, si una de las mutaciones es para una tabla o una columna que NO existe en el esquema, el cliente podría devolver un error INVALID_ARGUMENT
en lugar de un error NOT_FOUND
.
Habilitar sesiones multiplexadas
Las sesiones multiplexadas están habilitadas de forma predeterminada en las siguientes bibliotecas de cliente:
- Java en la versión 6.98.0 y posteriores.
- Ve a la versión 1.85.0 o a una posterior.
- Python en la versión 3.57.0 y posteriores.
Para usar sesiones multiplexadas en aplicaciones de cliente de Node o en versiones anteriores de las bibliotecas de cliente de Java y Go, primero debes definir una variable de entorno para habilitarlas.
Para habilitar las sesiones multiplexadas, asigna el valor TRUE
a la variable de entorno GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS
. Esta marca también habilita la compatibilidad con sesiones multiplexadas para las transacciones de ReadOnly
.
export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS=TRUE
Para habilitar la compatibilidad con operaciones particionadas en sesiones multiplexadas, asigna el valor TRUE
a la GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_PARTITIONED_OPS
variable de entorno.
export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_PARTITIONED_OPS=TRUE
Para habilitar la compatibilidad con transacciones de lectura y escritura en sesiones multiplexadas, asigna el valor GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW
a la variable de entorno TRUE
.
export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW=True
Debes definir GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS
como TRUE
para poder admitir una transacción en una sesión multiplexada.
Ver el tráfico de sesiones normales y multiplexadas
OpenTelemetry tiene el filtro is_multiplexed
para mostrar el tráfico de sesiones multiplexadas. Si asignas el valor true to view multiplexed sessions
and
false` a este filtro, se mostrarán las sesiones normales.
- Configura OpenTelemetry para Spanner siguiendo los procedimientos de la sección Antes de empezar de OpenTelemetry para Spanner.
Ve a Explorador de métricas.
En el menú desplegable Métrica, filtre por
generic
.Haz clic en Tarea genérica y ve a Spanner > Spanner/num_acquired_sessions.
En el campo Filtrar, elija una de las siguientes opciones:
a.
is_multiplexed = false
para ver las sesiones periódicas. b.is_multiplexed = true
para ver las sesiones multiplexadas.En la siguiente imagen se muestra la opción Filtrar con las sesiones multiplexadas seleccionadas.
Para obtener más información sobre cómo usar OpenTelemetry con Spanner, consulta los artículos Aprovechar OpenTelemetry para democratizar la observabilidad de Spanner y Examinar la latencia de un componente de Spanner con OpenTelemetry.
Solucionar problemas
Entre los errores habituales relacionados con las sesiones que puede encontrar tu aplicación se incluyen los siguientes:
Session not found
RESOURCE_EXHAUSTED
Para obtener más información, consulta Errores de sesión.