Qué cambia un Postgres gestionado para Laravel
El Postgres serverless está diseñado y tarifado para cargas de una conexión por petición. Laravel mantiene conexiones de larga vida en sus workers de cola, y ahí están las sorpresas.
Postgres gestionado solía significar un servidor que parcheaba otro. Cada vez más significa una plataforma: almacenamiento separado del cómputo, conexiones intermediadas por un pooler, bases de datos que se ramifican como git, y cómputo que se suspende cuando nadie pregunta.
Todo eso está construido para una carga en la que llega una petición, ejecuta una consulta y se va. Laravel es esa carga en la capa web y lo contrario en todo lo demás.
El desajuste, dicho sin rodeos
Una aplicación Laravel tiene tres tipos de cliente de base de datos y se comportan de forma completamente distinta:
Peticiones web. PHP-FPM, conectar y desconectar por petición. Esto encaja con el modelo serverless exactamente.
Workers de cola. El comando queue:work conecta al arrancar y mantiene esa
conexión toda su vida, esté procesando algo o no. Veinte workers son veinte
conexiones permanentes antes de que llegue un solo visitante.
El planificador. Una entrada de cron ejecutando schedule:run cada minuto,
para siempre.
Los proveedores tarifan y dimensionan alrededor del primero. El segundo es lo
que llena una asignación de conexiones y es la causa más común de un
SQLSTATE[HY000] [1040] Too many connections, un error que desglosamos en
detalle en nuestras páginas de errores en inglés. El tercero es lo que derrota
en silencio el escalado a cero.
El escalado a cero y el planificador
Esto es lo que la gente hace mal primero y es aritmética, no opinión.
El cómputo se suspende tras cierto periodo de inactividad. La orden
schedule:run emite una consulta cada sesenta segundos. Si el umbral de
inactividad es mayor que un minuto, la base de datos no se suspende nunca y
usted está pagando cómputo siempre encendido con características de arranque en
frío encima.
Hay tres respuestas honestas. Aceptarlo y dimensionar para siempre encendido, en cuyo caso una instancia convencional puede salir más barata. Mover el planificador a algo que no toque la base de datos cuando no hay nada pendiente, lo que significa que la definición del calendario tiene que poder leerse sin una consulta. O aceptar arranques en frío en un entorno de pruebas y no en producción, que es donde el escalado a cero de verdad compensa.
Nadie debería descubrir esto por una factura.
Los modos de pooling, que son lo que rompe cosas
Todo Postgres serverless pone un pooler delante. El modo decide qué puede hacer su aplicación.
El pooling por sesión le entrega una conexión real durante toda la vida de su conexión. Todo funciona. También obtiene muchas menos conexiones efectivas, que suele ser el motivo por el que vino.
El pooling por transacción le entrega un backend solo durante una transacción. Esto es lo que da miles de conexiones de cliente sobre unas pocas reales, y elimina todo lo que abarca varias sentencias:
- Las sentencias preparadas en servidor, que PDO usa por defecto. Esta es la que muerde a Laravel en concreto, y el arreglo es una bandera en la cadena de conexión o un ajuste de emulación, no un cambio de código, pero hay que ponerlo a propósito.
- Los bloqueos de aviso, lo que significa que
withoutOverlapping()en un calendario yShouldBeUniqueen un trabajo pueden no comportarse como están escritos si se apoyan en la base de datos. - Las sentencias
SET, así que todo lo que fije una zona horaria o una ruta de búsqueda por conexión deja de aguantar. LISTEN/NOTIFY, y cualquier cursor de larga vida.
La disposición práctica son dos conexiones en config/database.php: el punto
final con pooling para las peticiones web, el directo para las migraciones, los
workers de cola y cualquier cosa que sostenga un bloqueo. Son diez líneas y
evitan la mayor parte de este artículo.
El branching, que es la capacidad genuinamente nueva
Una rama es una base de datos con copia en escritura a escala de producción, creada en segundos. Para Laravel eso aterriza sobre un problema concreto: migraciones que son seguras contra cuarenta filas y bloquean cuatro minutos contra cuatro millones.
Una rama por pull request, las migraciones ejecutadas contra ella en CI, los tiempos registrados. Ahora un cambio de esquema peligroso falla una compilación en vez de un despliegue. Este es el argumento más fuerte a favor de una plataforma frente a una instancia, y vale más que el modelo de precios.
Elegir entre ellas
Una instancia gestionada convencional - RDS, Cloud SQL, el Postgres sencillo de un proveedor - cuando la aplicación tiene una flota estable de workers, cuando quiere recuentos de conexiones predecibles, y cuando la carga operativa que está comprando es el parcheo y no el escalado. Esta sigue siendo la respuesta correcta para la mayoría de las aplicaciones de negocio y no está de moda decirlo.
Postgres serverless con branching cuando la historia de probar migraciones le importa, cuando los entornos son numerosos y efímeros, o cuando el tráfico es de verdad irregular. Presupueste el trabajo de pooling en lugar de suponer que es un cambio en la cadena de conexión.
Una plataforma con auth y almacenamiento incluidos cuando también los va a usar. Si la usa solo como base de datos, está eligiendo un proveedor de Postgres y debería compararlo como tal.
Cualquier cosa compatible con MySQL pero fragmentada solo con la lista de
restricciones leída antes. La integridad referencial, las transacciones que
cruzan shards y ORDER BY sobre una tabla fragmentada son donde el modelo se
transparenta, y las migraciones de Laravel escribirán tan tranquilas DDL que la
plataforma acepta y no impone.
La comprobación que cuesta una tarde
Antes de comprometerse, ejecute lo real: una migración con construcción de índice sobre una tabla de tamaño de producción, su número real de workers conectados a la vez, y un comando programado sosteniendo un bloqueo. Tres medidas, una tarde.
Todos los problemas de este artículo son baratos de encontrar así y caros de encontrar en el segundo mes.
