Categoría: Sin categoría

  • PHP-FPM: flujo de solicitudes, dimensionado y ajustes clave

    PHP-FPM: flujo de solicitudes, dimensionado y ajustes clave

    Resumen: Esta guía técnica explica cómo fluye una solicitud en PHP-FPM, qué ajustes impactan la latencia y una regla práctica para dimensionar pm.max_children por memoria.

    Incluye una configuración de ejemplo, comprobaciones operativas y pasos para validar cambios con pruebas de carga.

    Introducción

    PHP-FPM (FastCGI Process Manager) administra pools de procesos PHP. Cada worker atiende una solicitud a la vez; la concurrencia total de un pool es el número de children activos.

    Si faltan workers el resto de solicitudes se encolan en el socket o generan 502/504 cuando el backlog se desborda. El dimensionado correcto y unas pocas opciones clave evitan timeouts y picos de latencia.

    Prerrequisitos

    Acceso de administrador al host para editar la configuración de PHP-FPM y Nginx, ejecutar comandos de medición (ps, curl) y ejecutar pruebas de carga desde clientes de prueba.

    Permisos para leer/crear archivos de slowlog y exponer pm.status_path y ping.path de forma segura (por ejemplo, accesible sólo desde localhost o una red de gestión).

    Desarrollo

    En esta sección describo el procedimiento recomendado: exponer métricas, medir memoria por worker, calcular pm.max_children y ajustar tiempos y backlog.

    Procedimiento

    1. Exponer estado y slow logs.
    2. Medir RSS por worker bajo carga realista.
    3. Calcular pm.max_children por presupuesto de memoria.
    4. Ajustar pm.start_servers y los spares para mantener workers calientes.
    5. Hacer pruebas de carga y iterar.

    Detalles y comandos útiles para cada paso.

    [app]
    user = www-data
    group = www-data
    listen = /run/php/php-fpm-app.sock
    listen.owner = www-data
    listen.group = www-data
    listen.mode = 0660
    listen.backlog = 1024
    
    pm = dynamic
    pm.max_children = 32
    pm.start_servers = 8
    pm.min_spare_servers = 8
    pm.max_spare_servers = 16
    pm.process_idle_timeout = 20s
    pm.max_requests = 2000
    
    request_terminate_timeout = 30s
    request_slowlog_timeout = 2s
    slowlog = /var/log/php-fpm/app.slow.log
    
    pm.status_path = /status
    ping.path = /ping
    ping.response = pong
    Lenguaje del código: TOML, también INI (ini)

    Añade una ubicación en Nginx para exponer /status y /ping (restringe acceso):

    location ~ ^/(status|ping)$ {
        allow 127.0.0.1;
        deny all;
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php-fpm-app.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
    Lenguaje del código: Nginx (nginx)

    Comandos para comprobar estado y medir memoria por worker:

    curl -s http://127.0.0.1/status?full
    
    # listar RSS de procesos php-fpm (ajusta el comando según tu sistema)
    ps -o pid,rss,cmd -C php-fpm | head -n 60
    Lenguaje del código: Bash (bash)

    Regla práctica para calcular pm.max_children:

    max_children = floor(pool_memory_budget_mb / per_child_rss_mb). Empieza 10–20% por debajo del valor teórico para dejar cabeza.

    import http from 'k6/http';
    import { check } from 'k6';
    export const options = {
      scenarios: {
        steady: {
          executor: 'constant-arrival-rate',
          rate: 200,
          timeUnit: '1s',
          duration: '5m',
          preAllocatedVUs: 200,
          maxVUs: 1000,
        },
      },
      thresholds: {
        http_req_failed: ['rate<0.01'],
        http_req_duration: ['p(95)<200'],
      },
    };
    export default function () {
      const res = http.get(`${__ENV.BASE_URL}/calc?x=1&y=2`);
      check(res, {
        'status is 200': r => r.status === 200,
        'json has result': r => r.json('result') !== undefined,
      });
    }
    Lenguaje del código: JavaScript (javascript)

    Ejemplos

    Mini caso: VM con 8 GB RAM, 2 GB reservados para sistema y servicios; 6 GB dedicados al pool. Muestras de RSS muestran mediana 120 MB por child.

    Cálculo: floor(6000 / 120) = 50 → empezar con pm.max_children = 44 para dejar margen por fragmentación y OPcache.

    Configuración de spares para absorber ráfagas en modo dynamic:

    pm.start_servers = 12
    pm.min_spare_servers = 12
    pm.max_spare_servers = 24
    pm.max_requests = 1500
    Lenguaje del código: TOML, también INI (ini)

    Validación: ejecutar carga sostenida y observar pm.status (idle, active, queue). Si la cola supera pm.max_children/4 durante >1 minuto, aumentar max_children si la memoria lo permite o optimizar endpoints lentos.

    Checklist

    • pm.status_path y ping.path habilitados y protegidos.
    • request_slowlog_timeout = 1–2s para APIs; ruta de slowlog disponible.
    • pm = dynamic y pm.max_children calculado por memoria.
    • pm.max_requests en 1,000–3,000 según fuga observada.
    • Alineación de request_terminate_timeout y timeouts de Nginx.
    • OPcache con >20% de espacio libre en picos.
    • listen.backlog ≥ 512 y límites de descriptors por encima del pico.
    • Pools separados para admin/cron/colas si aplica.

    Conclusión

    PHP-FPM es medible: dimensiona por memoria, mantén workers calientes para ráfagas, activa slow logs y expón métricas. Valida con pruebas de carga y observa p95, cola y uso de memoria antes de escalar.

    Si el patrón de trabajo no encaja (trabajos largos, streaming, altísima concurrencia ligera), considera arquitecturas alternativas en lugar de forzar más children.

  • 7 herramientas open-source para backend que deberías probar en 2025

    7 herramientas open-source para backend que deberías probar en 2025

    Este artículo técnico presenta siete herramientas open-source útiles para desarrolladores backend en 2025. Incluye una descripción breve de cada herramienta, ejemplos prácticos y una checklist para evaluar cuál adoptar.

    Introducción

    En 2025 hay un fuerte movimiento hacia herramientas open-source que aceleran el desarrollo backend: frameworks, plataformas BaaS y ORMs que reducen fricción operacional y mejoran la productividad.

    Este artículo resume siete proyectos destacados, con foco en su propósito y casos de uso técnico, sin entrar en comparativas de versiones o compatibilidades.

    Prerrequisitos

    No se requieren detalles de instalación específicos aquí; como prerrequisitos generales recomendamos experiencia con desarrollo backend, control de versiones y un entorno local para pruebas. Algunas herramientas en la lista admiten despliegue self-hosted según la descripción base.

    Desarrollo

    Procedimiento

    A continuación se listan las siete herramientas con notas técnicas resumidas extraídas del texto base.

    • Nitric — Framework multi-lenguaje para aplicaciones cloud. Soporta definición de infraestructura como código e incluye emulación local de servicios cloud para pruebas.
    • Encore — Framework orientado a desarrollo type-safe que combina lógica y infraestructura, con generación de herramientas y enfoque en microservicios.
    • Appwrite — Backend-as-a-Service self-hosted que integra autenticación, base de datos y funciones serverless en un único producto.
    • Manifest — Micro-backend definido en un único archivo YAML que incluye panel de administración, pensado para setups rápidos.
    • Nhost — Alternativa tipo Firebase con API GraphQL y base de datos PostgreSQL; incluye seguridad basada en roles.
    • Supabase — Plataforma basada en Postgres con soporte realtime; disponible gestionada o self-hosted según la referencia.
    • Prisma — ORM orientado a desarrolladores con consultas type-safe y flujo schema-first; soporta múltiples bases de datos.

    La selección de una herramienta depende del objetivo: evitar vendor lock-in, acelerar prototipos, o disponer de control total del stack. Más abajo hay ejemplos prácticos para experimentar con algunos patrones comunes.

    Ejemplos

    Incluyo ejemplos mínimos para probar ideas frecuentes: un archivo Manifest de ejemplo, un esquema Prisma básico y una consulta GraphQL representativa para backends tipo Nhost/Supabase.

    Ejemplo: archivo manifest.yml (micro-backend de una entidad simple)

    name: users-service
    routes:
      - path: /users
        method: GET
        handler: listUsers
    models:
      User:
        id: int
        name: string
        email: string
    Lenguaje del código: YAML (yaml)

    Ejemplo: esquema Prisma mínimo (schema.prisma)

    datasource db {
      provider = "postgresql"
      url      = env("DATABASE_URL")
    }
    
    model User {
      id    Int    @id @default(autoincrement())
      name  String
      email String @unique
    }
    Lenguaje del código: texto plano (plaintext)

    Ejemplo: consulta GraphQL típica para obtener usuarios (para backends GraphQL como Nhost)

    {
      users {
        id
        name
        email
      }
    }
    Lenguaje del código: texto plano (plaintext)

    Checklist

    1. Clarificar objetivos: prototipo rápido, control self-hosted o escalado a producción.
    2. Evaluar requisitos de datos: necesidad de SQL (Postgres) o flexibilidad multi-DB.
    3. Decidir sobre vendor lock-in: elegir herramientas cloud-agnostic si es prioritario.
    4. Comprobar necesidades de realtime o GraphQL si la app las requiere.
    5. Planificar pruebas locales: priorizar proyectos que ofrecen emulación local para CI y desarrollo.

    Conclusión

    Las siete herramientas cubren distintos niveles del stack backend: desde frameworks cloud-agnostic a plataformas BaaS y ORMs. Para elegir, prioriza requisitos técnicos y ritmo de entrega.

    Si quieres explorar una herramienta concreta en profundidad, indica cuál y prepararé una guía de inicio con comandos y ejemplos más detallados.

  • Logging contextual en PHP: reemplaza var_dump() por Monolog

    Logging contextual en PHP: reemplaza var_dump() por Monolog

    Resumen: Deja de usar var_dump() en tus aplicaciones PHP. Implementa logging contextual para obtener registros estructurados, trazas y mejor diagnóstico.

    Este artículo explica por qué el logging contextual es superior, qué herramientas usar y cómo instrumentar Monolog con ejemplos prácticos.

    Introducción

    var_dump() muestra datos, pero no el contexto ni la intención detrás de un evento. En aplicaciones modernas eso crea ruido y dificulta el diagnóstico.

    El objetivo del logging contextual es convertir cada registro en una unidad de información accionable: quién, qué, dónde y bajo qué condiciones.

    Prerrequisitos

    Asumo que puedes instalar paquetes con Composer. Necesitarás Monolog y acceso a la capa donde se almacenan o envían los logs (archivos, agregadores, etc.).

    Desarrollo

    Procedimiento

    1. Crear y configurar un Logger central.
    2. Añadir handlers y processors que inyecten contexto (ID de correlación, ubicación, introspección).
    3. Emitir logs estructurados (preferible JSON) con campos relevantes.

    Ejemplo mínimo de configuración con Monolog (stream handler y processors):

    <?php
    use Monolog\Logger;
    use Monolog\Handler\StreamHandler;
    use Monolog\Processor\UidProcessor;
    use Monolog\Processor\IntrospectionProcessor;
    
    // Create logger
    $logger = new Logger('app');
    $logger->pushHandler(new StreamHandler(__DIR__.'/logs/app.log', Logger::DEBUG));
    $logger->pushProcessor(new UidProcessor());
    $logger->pushProcessor(new IntrospectionProcessor());
    
    // Contextual log
    $logger->info('User action', [
        'user_id' => 213,
        'action' => 'update_order',
        'environment' => getenv('APP_ENV'),
    ]);
    Lenguaje del código: PHP (php)

    Con esta configuración obtendrás registros con identificador único y referencia de pila, lo que facilita agrupar eventos y localizar código.

    Ejemplos

    Ejemplo de log estructurado en JSON (concepto):

    {
      "timestamp": "2025-10-12T12:34:56Z",
      "level": "info",
      "message": "User action",
      "context": {
        "user_id": 213,
        "action": "update_order",
        "environment": "staging",
        "correlation_id": "5f8e3b7a"
      }
    }
    Lenguaje del código: JSON / JSON con comentarios (json)

    Comportamientos recomendados a implementar:

    • Añadir correlation IDs en cabeceras y logs para trazar flujos distribuidos.
    • Emitir campos de negocio (user_id, tenant, region) en cada evento relevante.
    • Usar niveles dinámicos y enviar alertas según impacto.
    export APP_ENV=staging
    tail -f logs/app.log | jq .
    Lenguaje del código: Bash (bash)

    Checklist

    • Eliminar var_dump() y print_r() del código en producción.
    • Registrar contexto mínimo: user_id, request_id/correlation_id, environment.
    • Enviar logs estructurados a un agregador o almacenarlos en formato JSON.
    • Configurar niveles y alertas basadas en impacto.

    Conclusión

    Pasar de var_dump() a logging contextual reduce ruido, acelera el diagnóstico y permite analizar el comportamiento de la aplicación en producción.

    Empieza por instrumentar Monolog, añadir processors relevantes y normalizar la salida en JSON para integrarla con tus herramientas de observabilidad.