Long Polling vs WebSocket en Java: ¿qué elegir para tiempo real?

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Long Polling vs WebSocket en Java: duelo de tecnologías en tiempo real

\n\n

Imagina: estás desarrollando un chat, un terminal bursátil o un juego en línea en Java. El usuario espera actualizaciones, pero el servidor guarda silencio. ¿Cómo hacer que los datos lleguen al instante? Antes solo había una opción: Long Polling. Hoy en el ring está WebSocket. Pero, ¿quién gana en una pelea real?

\n\n

En este artículo no solo compararemos conceptos. Escribiremos código vivo en Java, veremos el interior de ambas tecnologías y decidiremos qué usar en tu próximo proyecto. ¡Bienvenidos al ring!

\n\n

¿Qué es Long Polling (y por qué no es una «consulta»)?

\n\n

El HTTP clásico es como una carta: envías una solicitud → recibes una respuesta. Si el servidor no tiene nada que decir, devuelve una respuesta vacía. El cliente se ve obligado a preguntar de nuevo cada N segundos. Esto es Short Polling: un camino sin salida.

\n\n

Long Polling funciona de manera más astuta. El cliente envía una solicitud y el servidor… se duerme. Mantiene la conexión abierta hasta que aparece un nuevo evento (o hasta que expire el tiempo de espera). Tan pronto como ocurre el evento, el servidor se despierta y envía la respuesta. El cliente crea inmediatamente una nueva solicitud Long Polling. El ciclo se cierra.

\n\n

Long Polling en Java: implementación simple

\n\n

Imaginemos que escribimos un servidor de notificaciones con Servlet API puro (sin Spring, para que sea más claro). Para Long Polling necesitaremos procesamiento asíncrono (AsyncContext), de lo contrario el servidor bloqueará todos los hilos.

\n\n
import javax.servlet.AsyncContext;\nimport javax.servlet.annotation.WebServlet;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentLinkedQueue;\n\n@WebServlet(urlPatterns = "/long-poll", asyncSupported = true)\npublic class LongPollingServlet extends HttpServlet {\n\n    // Cola para almacenar las conexiones "dormidas"\n    private static final Queue<AsyncContext> WAITING_CLIENTS = new ConcurrentLinkedQueue<>();\n\n    @Override\n    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {\n        AsyncContext asyncContext = req.startAsync();\n        asyncContext.setTimeout(30_000); // Tiempo de espera de 30 segundos\n\n        // Guardamos el contexto\n        WAITING_CLIENTS.add(asyncContext);\n\n        // Si el tiempo de espera expira, devolvemos una respuesta vacía\n        asyncContext.addListener(new javax.servlet.AsyncListener() {\n            public void onTimeout(javax.servlet.AsyncEvent event) {\n                WAITING_CLIENTS.remove(asyncContext);\n                try {\n                    HttpServletResponse response = (HttpServletResponse) event.getAsyncContext().getResponse();\n                    response.getWriter().write("timeout");\n                    response.setStatus(HttpServletResponse.SC_OK);\n                    asyncContext.complete();\n                } catch (IOException e) { e.printStackTrace(); }\n            }\n            // Otros métodos del listener se omiten por brevedad\n        });\n    }\n\n    // Este método se llama cuando aparece un nuevo evento\n    public static void sendEventToClients(String message) {\n        for (AsyncContext ctx : WAITING_CLIENTS) {\n            try {\n                HttpServletResponse response = (HttpServletResponse) ctx.getResponse();\n                response.getWriter().write(message);\n                response.setStatus(HttpServletResponse.SC_OK);\n                ctx.complete();\n                WAITING_CLIENTS.remove(ctx);\n            } catch (IOException e) { e.printStackTrace(); }\n        }\n    }\n}
\n\n

Cómo funciona:

\n
    \n
  • El cliente realiza una solicitud GET a /long-poll.
  • \n
  • El servidor cambia la solicitud a modo asíncrono y se «duerme» (espera).
  • \n
  • Cuando aparece un mensaje (método sendEventToClien
  • \n

Blogs

Book Recommendations