<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Arquitectura - RandomBitsOnFire</title>
	<atom:link href="https://randombitsonfire.com/category/arquitectura/feed/" rel="self" type="application/rss+xml" />
	<link>https://randombitsonfire.com</link>
	<description>Home</description>
	<lastBuildDate>Thu, 05 Mar 2026 09:04:37 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://randombitsonfire.com/wp-content/uploads/2024/08/cropped-favicon512x512-32x32.png</url>
	<title>Arquitectura - RandomBitsOnFire</title>
	<link>https://randombitsonfire.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>PHP y PHP-FPM con Apache: diferencias</title>
		<link>https://randombitsonfire.com/programacion/back/php-y-php-fpm-con-apache-diferencias/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=php-y-php-fpm-con-apache-diferencias</link>
					<comments>https://randombitsonfire.com/programacion/back/php-y-php-fpm-con-apache-diferencias/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Mon, 09 Mar 2026 11:00:00 +0000</pubDate>
				<category><![CDATA[Arquitectura]]></category>
		<category><![CDATA[Back]]></category>
		<category><![CDATA[Programacion]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[FPM]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Servidores]]></category>
		<category><![CDATA[Web]]></category>
		<guid isPermaLink="false">https://randombitsonfire.com/?p=144</guid>

					<description><![CDATA[<p>Si estás desarrollando aplicaciones web con PHP, seguramente te habrás encontrado con distintos métodos para ejecutar el código: mod_php, PHP-FPM, y cómo Apache los maneja. Vamos a desglosarlo. 1. PHP tradicional con Apache (mod_php) 2. PHP-FPM (FastCGI Process Manager) Requiere monitoreo de los pools de procesos para evitar saturación. Qué es: PHP-FPM es un gestor [&#8230;]</p>
<p>The post <a href="https://randombitsonfire.com/programacion/back/php-y-php-fpm-con-apache-diferencias/">PHP y PHP-FPM con Apache: diferencias</a> first appeared on <a href="https://randombitsonfire.com">RandomBitsOnFire</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Si estás desarrollando aplicaciones web con <strong>PHP</strong>, seguramente te habrás encontrado con distintos métodos para ejecutar el código: <strong>mod_php</strong>, <strong>PHP-FPM</strong>, y cómo Apache los maneja. Vamos a desglosarlo.</p>



<h3 class="wp-block-heading">1. PHP tradicional con Apache (mod_php)</h3>



<ul class="wp-block-list">
<li><strong>Qué es:</strong> <code>mod_php</code> es un módulo de Apache que permite ejecutar código PHP directamente dentro del proceso del servidor web.</li>



<li><strong>Cómo funciona:</strong> Apache carga el intérprete de PHP como parte de sus procesos. Cada petición HTTP que requiere PHP es procesada dentro del mismo proceso de Apache.</li>



<li><strong>Ventajas:</strong>
<ul class="wp-block-list">
<li>Simplicidad: fácil de configurar.</li>



<li>Integración directa: PHP puede acceder a variables de Apache y módulos internos.</li>
</ul>
</li>



<li><strong>Desventajas:</strong>
<ul class="wp-block-list">
<li>Cada proceso de Apache carga PHP completo, lo que aumenta el consumo de memoria.</li>



<li>No es tan eficiente en entornos con muchas conexiones concurrentes.</li>
</ul>
</li>
</ul>



<figure class="wp-block-image aligncenter size-full"><img fetchpriority="high" decoding="async" width="459" height="292" src="https://randombitsonfire.com/wp-content/uploads/2026/02/image-1.png" alt="" class="wp-image-218" srcset="https://randombitsonfire.com/wp-content/uploads/2026/02/image-1.png 459w, https://randombitsonfire.com/wp-content/uploads/2026/02/image-1-300x191.png 300w" sizes="(max-width: 459px) 100vw, 459px" /></figure>



<h3 class="wp-block-heading">2. PHP-FPM (FastCGI Process Manager)</h3>



<p>Requiere monitoreo de los pools de procesos para evitar saturación.</p>



<p><strong>Qué es:</strong> PHP-FPM es un gestor de procesos FastCGI para PHP. Funciona como un servicio independiente que Apache llama para ejecutar scripts PHP.</p>



<p><strong>Cómo funciona:</strong></p>



<p>Apache recibe la petición HTTP.</p>



<p>Si es un archivo PHP, Apache lo redirige a PHP-FPM mediante <strong>FastCGI</strong> (usualmente usando <code>mod_proxy_fcgi</code>). <strong>En versiones de Linux Alpine se encuentra incluido en el mod_proxy</strong>.</p>



<p>PHP-FPM procesa el script y devuelve la respuesta a Apache.</p>



<p><strong>Ventajas:</strong></p>



<p>Manejo eficiente de procesos: PHP-FPM mantiene pools de procesos listos para servir solicitudes.</p>



<p>Mejor rendimiento en sitios con alta concurrencia.</p>



<p>Permite ejecutar diferentes versiones de PHP para distintos sitios.</p>



<p>Mejor aislamiento de procesos y control de recursos.</p>



<p><strong>Desventajas:</strong></p>



<p>Configuración más compleja.</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="562" height="319" src="https://randombitsonfire.com/wp-content/uploads/2026/02/image-2.png" alt="" class="wp-image-219" srcset="https://randombitsonfire.com/wp-content/uploads/2026/02/image-2.png 562w, https://randombitsonfire.com/wp-content/uploads/2026/02/image-2-300x170.png 300w" sizes="(max-width: 562px) 100vw, 562px" /></figure>



<h3 class="wp-block-heading">3. Cómo Apache gestiona PHP con FPM</h3>



<p>Apache ya no ejecuta PHP directamente. Usa <strong>mod_proxy_fcgi</strong> o <strong>mod_fastcgi</strong> para comunicarse con PHP-FPM:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:clamp(12px, .75rem, 18px);font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:clamp(16px, 1rem, 24px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;FilesMatch .php$>
    SetHandler "proxy:unix:/run/php/php8.1-fpm.sock|fcgi://localhost/"
&lt;/FilesMatch></textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF">FilesMatch </span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">php$</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    SetHandler </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">proxy:unix:/run/php/php8.1-fpm.sock|fcgi://localhost/</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #81A1C1">&lt;/</span><span style="color: #D8DEE9FF">FilesMatch</span><span style="color: #81A1C1">&gt;</span></span></code></pre></div>



<ul class="wp-block-list">
<li><code>SetHandler</code> indica que las peticiones PHP se deben enviar a PHP-FPM.</li>



<li>PHP-FPM escucha en un <strong>socket Unix</strong> o <strong>puerto TCP</strong> y devuelve la salida ya procesada.</li>



<li>Apache sigue manejando la conexión HTTP, logging, seguridad y otras funcionalidades, pero la ejecución de PHP queda delegada.</li>
</ul>



<h3 class="wp-block-heading">4. Resumen de diferencias</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Característica</th><th>mod_php (tradicional)</th><th>PHP-FPM (FastCGI)</th></tr></thead><tbody><tr><td>Ejecución</td><td>Dentro de Apache</td><td>Servicio externo</td></tr><tr><td>Rendimiento</td><td>Bueno en bajo tráfico</td><td>Mejor en alto tráfico</td></tr><tr><td>Memoria</td><td>Alta</td><td>Optimizada</td></tr><tr><td>Multiples versiones</td><td>Difícil</td><td>Fácil</td></tr><tr><td>Aislamiento</td><td>Bajo</td><td>Alto</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">5. Conclusión</h3>



<ul class="wp-block-list">
<li><strong>mod_php</strong> es más simple y suficiente para sitios pequeños o entornos de desarrollo.</li>



<li><strong>PHP-FPM</strong> es más eficiente, flexible y escalable, ideal para producción y sitios con alta carga.</li>



<li>Apache gestiona la parte HTTP y delega la ejecución de PHP a PHP-FPM, optimizando recursos y manteniendo la seguridad y control.</li>
</ul>



<h3 class="wp-block-heading">5. Exclusividad de PHP-FPM y orden de ejecución con Apache</h3>



<p>Cuando usamos <strong>PHP-FPM</strong>, Apache ya <strong>no ejecuta PHP directamente</strong>. Esto implica dos cosas importantes:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Nombre en paquete</th><th>Qué incluye</th></tr></thead><tbody><tr><td>php-apache</td><td>PHP + mod_php</td></tr><tr><td>php-fpm</td><td>PHP + FPM</td></tr></tbody></table></figure>



<h4 class="wp-block-heading">1&#xfe0f;&#x20e3; Exclusividad de PHP-FPM</h4>



<ul class="wp-block-list">
<li><strong>Solo puede haber un intérprete activo por socket o puerto</strong>.</li>



<li>PHP-FPM actúa como un <strong>servicio independiente</strong>, gestionando un <strong>pool de procesos</strong> que reciben solicitudes de PHP de Apache (o Nginx).</li>



<li>Si tienes múltiples instancias de PHP-FPM escuchando en el mismo socket, habrá conflictos.</li>



<li>Por eso se habla de <strong>“exclusividad”</strong>: cada pool de PHP-FPM se asigna a un <strong>sitio o versión de PHP</strong> y Apache lo llama a través del socket/puerto definido.</li>
</ul>



<h2 class="wp-block-heading">6. Ejecución del servidor</h2>



<h3 class="wp-block-heading">1&#xfe0f;&#x20e3; Arranque con <strong>mod_php (php-apache)</strong> en Alpine</h3>



<p>En Alpine, normalmente instalas el paquete <code>php-apache2</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:clamp(12px, .75rem, 18px);font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:clamp(16px, 1rem, 24px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly># Instalar Apache + mod_php
apk add apache2 php8-apache2

# Iniciar Apache (que ya carga PHP internamente)
httpd -D</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #8FBCBB">Instalar</span><span style="color: #D8DEE9FF"> Apache </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> mod_php</span></span>
<span class="line"><span style="color: #D8DEE9FF">apk add apache2 php8</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">apache2</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #8FBCBB">Iniciar</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Apache</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">que ya carga </span><span style="color: #8FBCBB">PHP</span><span style="color: #D8DEE9FF"> internamente</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">httpd </span><span style="color: #81A1C1">-</span><span style="color: #8FBCBB">D</span></span></code></pre></div>



<ul class="wp-block-list">
<li><strong>Nota:</strong> No hay servicio PHP externo, todo corre dentro de Apache.</li>
</ul>



<h3 class="wp-block-heading">2&#xfe0f;&#x20e3; Arranque con <strong>PHP-FPM + Apache</strong> en Alpine</h3>



<p>Instalas PHP-FPM y Apache, y configuras Apache para usar FastCGI:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:clamp(12px, .75rem, 18px);font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:clamp(16px, 1rem, 24px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly># Instalar PHP-FPM y Apache
apk add php8-fpm php8-opcache apache2

# Hablitar modulo proxy o proxy_fcgi segun se necesite
...
# Agregar configuracion proxy a FCGI
...

# Iniciar FPM 
php-fpm8 

# Iniciar Apache 
httpd -D
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #8FBCBB">Instalar</span><span style="color: #D8DEE9FF"> PHP</span><span style="color: #81A1C1">-</span><span style="color: #8FBCBB">FPM</span><span style="color: #D8DEE9FF"> y </span><span style="color: #8FBCBB">Apache</span></span>
<span class="line"><span style="color: #D8DEE9FF">apk add php8</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">fpm php8</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">opcache apache2</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #8FBCBB">Hablitar</span><span style="color: #D8DEE9FF"> modulo proxy o proxy_fcgi segun se necesite</span></span>
<span class="line"><span style="color: #ECEFF4">...</span></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #8FBCBB">Agregar</span><span style="color: #D8DEE9FF"> configuracion proxy a </span><span style="color: #8FBCBB">FCGI</span></span>
<span class="line"><span style="color: #ECEFF4">...</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #8FBCBB">Iniciar</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">FPM</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">php</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">fpm8 </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #8FBCBB">Iniciar</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Apache</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">httpd </span><span style="color: #81A1C1">-</span><span style="color: #8FBCBB">D</span></span>
<span class="line"></span></code></pre></div><p>The post <a href="https://randombitsonfire.com/programacion/back/php-y-php-fpm-con-apache-diferencias/">PHP y PHP-FPM con Apache: diferencias</a> first appeared on <a href="https://randombitsonfire.com">RandomBitsOnFire</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://randombitsonfire.com/programacion/back/php-y-php-fpm-con-apache-diferencias/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Conexiones Real Time: Server Sent Events</title>
		<link>https://randombitsonfire.com/programacion/back/conexiones-real-time-server-sent-events/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=conexiones-real-time-server-sent-events</link>
					<comments>https://randombitsonfire.com/programacion/back/conexiones-real-time-server-sent-events/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Sun, 01 Mar 2026 11:00:00 +0000</pubDate>
				<category><![CDATA[Arquitectura]]></category>
		<category><![CDATA[Back]]></category>
		<category><![CDATA[Programacion]]></category>
		<category><![CDATA[Conexiones]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Server Sent Events]]></category>
		<category><![CDATA[Servidores]]></category>
		<guid isPermaLink="false">https://randombitsonfire.com/?p=58</guid>

					<description><![CDATA[<p>Los Server Sent Events (SSE) son una tecnología basada en HTTP que permite al servidor enviar datos al cliente de forma unidireccional y en tiempo real. A diferencia del modelo tradicional request/response, donde el cliente debe preguntar constantemente por nuevos datos (polling), con SSE el servidor mantiene la conexión abierta y envía información automáticamente cuando [&#8230;]</p>
<p>The post <a href="https://randombitsonfire.com/programacion/back/conexiones-real-time-server-sent-events/">Conexiones Real Time: Server Sent Events</a> first appeared on <a href="https://randombitsonfire.com">RandomBitsOnFire</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Los <strong>Server Sent Events (SSE)</strong> son una tecnología basada en HTTP que permite al servidor enviar datos al cliente de forma unidireccional y en tiempo real. A diferencia del modelo tradicional request/response, donde el cliente debe preguntar constantemente por nuevos datos (polling), con SSE el servidor mantiene la conexión abierta y envía información automáticamente cuando está disponible.</p>



<p>SSE está soportado de forma nativa por los navegadores modernos mediante la API <code>EventSource</code>, lo que lo convierte en una solución sencilla y eficiente para:</p>



<ul class="wp-block-list">
<li>Notificaciones en tiempo real</li>



<li>Actualización de dashboards</li>



<li>Logs en streaming</li>



<li>Sistemas de monitorización</li>



<li>Chats unidireccionales</li>
</ul>



<p>La comunicación se realiza sobre HTTP estándar con el tipo de contenido:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:clamp(12px, .75rem, 18px);font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:clamp(16px, 1rem, 24px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>text/event-stream</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">text</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">event</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">stream</span></span></code></pre></div>



<p>Cada evento sigue un formato simple:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:clamp(12px, .75rem, 18px);font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:clamp(16px, 1rem, 24px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>event: nombreEvento
data: contenido
id: 1</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">event</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> nombreEvento</span></span>
<span class="line"><span style="color: #D8DEE9FF">data</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> contenido</span></span>
<span class="line"><span style="color: #D8DEE9FF">id</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span></span></code></pre></div>



<h2 class="wp-block-heading">Alternativas: WebSockets</h2>



<p>La alternativa más conocida a SSE es <strong>WebSockets</strong>, una tecnología que permite comunicación bidireccional full-duplex entre cliente y servidor sobre una única conexión TCP persistente.</p>



<h3 class="wp-block-heading">Diferencias conceptuales</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th class="has-text-align-center" data-align="center">Característica</th><th class="has-text-align-center" data-align="center">SSE</th><th class="has-text-align-center" data-align="center">WebSockets</th></tr></thead><tbody><tr><td class="has-text-align-center" data-align="center">Dirección</td><td class="has-text-align-center" data-align="center">Unidireccional (Servidor → Cliente)</td><td class="has-text-align-center" data-align="center">Bidireccional</td></tr><tr><td class="has-text-align-center" data-align="center">Protocolo</td><td class="has-text-align-center" data-align="center">HTTP estándar</td><td class="has-text-align-center" data-align="center">ws / wss</td></tr><tr><td class="has-text-align-center" data-align="center">Reconexión automática</td><td class="has-text-align-center" data-align="center">Sí (nativa)</td><td class="has-text-align-center" data-align="center">No (manual)</td></tr><tr><td class="has-text-align-center" data-align="center">Complejidad</td><td class="has-text-align-center" data-align="center">Baja</td><td class="has-text-align-center" data-align="center">Media/Alta</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Tabla comparativa: Ventajas y Desventajas</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Tecnología</th><th>Ventajas</th><th>Desventajas</th></tr></thead><tbody><tr><td><strong>SSE</strong></td><td>Simple de implementar. Basado en HTTP. Reconexión automática. Ideal para notificaciones</td><td>Solo unidireccional. No soporta binarios nativamente. Limitado en algunos proxies antiguos</td></tr><tr><td><strong>WebSockets</strong></td><td>Comunicación bidireccional. Mayor flexibilidad. Soporte binario</td><td>Mayor complejidad. Gestión manual de reconexión. No siempre compatible con infraestructuras legacy.</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Implementación clásica con Spring Boot 3</h2>



<p>En Spring Boot 3, la forma tradicional de implementar SSE es mediante <code>SseEmitter</code></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:clamp(12px, .75rem, 18px);font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:clamp(16px, 1rem, 24px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;dependency>
    &lt;groupId>org.springframework.boot&lt;/groupId>
    &lt;artifactId>spring-boot-starter-web&lt;/artifactId>
&lt;/dependency></textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">&lt;dependency&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;groupId&gt;</span><span style="color: #D8DEE9FF">org.springframework.boot</span><span style="color: #81A1C1">&lt;/groupId&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;artifactId&gt;</span><span style="color: #D8DEE9FF">spring-boot-starter-web</span><span style="color: #81A1C1">&lt;/artifactId&gt;</span></span>
<span class="line"><span style="color: #81A1C1">&lt;/dependency&gt;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:clamp(12px, .75rem, 18px);font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:clamp(16px, 1rem, 24px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>/** Service **/
public class SSEService {
        
	private Map&lt;String, SseEmitter> emitters = new ConcurrentHashMap&lt;>();
	public SseEmitter subscribe(String userId) {
        SseEmitter emitter = emitters
            .computeIfAbsent(userId, k -> new SseEmitter(0L));

        emitter.onCompletion(() -> {
        	log.info("Connection COMPLETED on USER: "+ userId);
        	remove(userId);});
        emitter.onTimeout(() -> {
        	log.info("Connection TIMEOUT on USER: "+ userId);
        	remove(userId);});
        emitter.onError(e -> {
        	log.info("Connection ERROR on USER: "+ userId);
        	remove(userId);});
        
        objs.computeIfAbsent(userId, k -> obj);

        return emitter;
    }
    public void remove(String userId) {
    	SseEmitter sse = emitters.get(userId);
        if (sse != null) {
        	log.info("CLEAN CONNECTION AND REMOVE FILTER on USER: "+ userId);
        	emitters.remove(userId);
        }
    }
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">/** Service **/</span></span>
<span class="line"><span style="color: #81A1C1">public</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">class</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">SSEService</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">private</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Map</span><span style="color: #ECEFF4">&lt;</span><span style="color: #8FBCBB">String</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">SseEmitter</span><span style="color: #ECEFF4">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">emitters</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">ConcurrentHashMap</span><span style="color: #ECEFF4">&lt;&gt;()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">public</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">SseEmitter</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">subscribe</span><span style="color: #ECEFF4">(</span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">userId</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">SseEmitter</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">emitter</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> emitters</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">computeIfAbsent</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">userId</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> k </span><span style="color: #8FBCBB">-&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">SseEmitter</span><span style="color: #ECEFF4">(</span><span style="color: #B48EAD">0L</span><span style="color: #ECEFF4">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">emitter</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">onCompletion</span><span style="color: #ECEFF4">(()</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">-&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        	</span><span style="color: #D8DEE9">log</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">info</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Connection COMPLETED on USER: </span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> userId</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        	</span><span style="color: #88C0D0">remove</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">userId</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span><span style="color: #ECEFF4">})</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">emitter</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">onTimeout</span><span style="color: #ECEFF4">(()</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">-&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        	</span><span style="color: #D8DEE9">log</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">info</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Connection TIMEOUT on USER: </span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> userId</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        	</span><span style="color: #88C0D0">remove</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">userId</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span><span style="color: #ECEFF4">})</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">emitter</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">onError</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">e </span><span style="color: #8FBCBB">-&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        	</span><span style="color: #D8DEE9">log</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">info</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Connection ERROR on USER: </span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> userId</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        	</span><span style="color: #88C0D0">remove</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">userId</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span><span style="color: #ECEFF4">})</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">objs</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">computeIfAbsent</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">userId</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> k </span><span style="color: #8FBCBB">-&gt;</span><span style="color: #D8DEE9FF"> obj</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> emitter</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">public</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">remove</span><span style="color: #ECEFF4">(</span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">userId</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    	</span><span style="color: #8FBCBB">SseEmitter</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sse</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">emitters</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">get</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">userId</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">sse </span><span style="color: #81A1C1">!=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">null</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        	</span><span style="color: #D8DEE9">log</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">info</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">CLEAN CONNECTION AND REMOVE FILTER on USER: </span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> userId</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        	</span><span style="color: #D8DEE9">emitters</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">remove</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">userId</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:clamp(12px, .75rem, 18px);font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:clamp(16px, 1rem, 24px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>/* Controller */
public class Controller {
        
	@Autowired
	private SSEService sseService;
	@GetMapping(path = "/subscribe", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
	public SseEmitter subscribe(@RequestParam("userID") String userId) {
		log.debug("Call to SSE Subscribe");
		return service.subscribe(userId);
	}
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">/* Controller */</span></span>
<span class="line"><span style="color: #81A1C1">public</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">class</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Controller</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #ECEFF4">@</span><span style="color: #D08770">Autowired</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">private</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">SSEService</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sseService</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #ECEFF4">@</span><span style="color: #D08770">GetMapping</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">path</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/subscribe</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">produces</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MediaType</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">TEXT_EVENT_STREAM_VALUE</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">public</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">SseEmitter</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">subscribe</span><span style="color: #ECEFF4">(@</span><span style="color: #D08770">RequestParam</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">userID</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">userId</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #D8DEE9">log</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">debug</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Call to SSE Subscribe</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">service</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">subscribe</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">userId</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<h3 class="wp-block-heading">Características clave</h3>



<ul class="wp-block-list">
<li>Spring mantiene la conexión abierta</li>



<li>El navegador reconecta automáticamente si se pierde</li>



<li>Se puede personalizar timeout y gestión de errores</li>
</ul>



<h1 class="wp-block-heading">Avanzado</h1>



<h2 class="wp-block-heading">Programación Reactiva</h2>



<p>En aplicaciones modernas, especialmente con alta concurrencia, el modelo bloqueante tradicional no es óptimo. Aquí entra la <strong>programación reactiva</strong>, basada en:</p>



<ul class="wp-block-list">
<li>Streams asíncronos</li>



<li>Backpressure</li>



<li>No bloqueo de hilos</li>
</ul>



<p>Spring ofrece soporte mediante <strong>Project Reactor</strong>, usando tipos como:</p>



<ul class="wp-block-list">
<li><code>Flux&lt;T&gt;</code></li>



<li><code>Mono&lt;T&gt;</code></li>
</ul>



<p>Para SSE, <code>Flux</code> es perfecto porque representa una secuencia de datos potencialmente infinita.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Uso con Spring WebFlux</h2>



<p>Para entornos altamente concurrentes o arquitecturas basadas en microservicios, WebFlux es la opción recomendada.</p>



<h3 class="wp-block-heading">Dependencia</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:clamp(12px, .75rem, 18px);font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:clamp(16px, 1rem, 24px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;dependency>
    &lt;groupId>org.springframework.boot&lt;/groupId>
    &lt;artifactId>spring-boot-starter-webflux&lt;/artifactId>
&lt;/dependency></textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF">dependency</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF">groupId</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9">org</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">springframework</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">boot</span><span style="color: #81A1C1">&lt;/</span><span style="color: #D8DEE9FF">groupId</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF">artifactId</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">spring</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">boot</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">starter</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">webflux</span><span style="color: #81A1C1">&lt;/</span><span style="color: #D8DEE9FF">artifactId</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #81A1C1">&lt;/</span><span style="color: #D8DEE9FF">dependency</span><span style="color: #81A1C1">&gt;</span></span></code></pre></div>



<h3 class="wp-block-heading">Implementación con Flux</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:clamp(12px, .75rem, 18px);font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:clamp(16px, 1rem, 24px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>/* Service */
@Service
public class SseService {

    private final Map&lt;String, Sinks.Many&lt;String>> sinks = new ConcurrentHashMap&lt;>();

    public Sinks.Many&lt;String> createSink(String clientId) {
        return sinks.computeIfAbsent(clientId,
                id -> Sinks.many().multicast().onBackpressureBuffer());
    }

    public void publish(String clientId, String message) {
        Sinks.Many&lt;String> sink = sinks.get(clientId);
        if (sink != null) {
            sink.tryEmitNext(message);
        }
    }

    public Flux&lt;ServerSentEvent&lt;String>> subscribe(String clientId) {
        Sinks.Many&lt;String> sink = createSink(clientId);

        Flux&lt;ServerSentEvent&lt;String>> flux = sink.asFlux()
                .map(data -> ServerSentEvent.builder(data).build());

        // heartbeat to keep connections alive
        Flux&lt;ServerSentEvent&lt;String>> heartbeat = Flux.interval(Duration.ofSeconds(15))
                .map(i -> ServerSentEvent.&lt;String>builder().comment("heartbeat").build());

        return Flux.merge(flux, heartbeat)
                .doOnCancel(() -> sinks.remove(clientId));
    }
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">/* Service */</span></span>
<span class="line"><span style="color: #ECEFF4">@</span><span style="color: #D08770">Service</span></span>
<span class="line"><span style="color: #81A1C1">public</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">class</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">SseService</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">private</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">final</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Map</span><span style="color: #ECEFF4">&lt;</span><span style="color: #8FBCBB">String</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Sinks</span><span style="color: #ECEFF4">.</span><span style="color: #8FBCBB">Many</span><span style="color: #ECEFF4">&lt;</span><span style="color: #8FBCBB">String</span><span style="color: #ECEFF4">&gt;&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sinks</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">ConcurrentHashMap</span><span style="color: #ECEFF4">&lt;&gt;()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">public</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Sinks</span><span style="color: #ECEFF4">.</span><span style="color: #8FBCBB">Many</span><span style="color: #ECEFF4">&lt;</span><span style="color: #8FBCBB">String</span><span style="color: #ECEFF4">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">createSink</span><span style="color: #ECEFF4">(</span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">clientId</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sinks</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">computeIfAbsent</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">clientId</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                id </span><span style="color: #8FBCBB">-&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Sinks</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">many</span><span style="color: #ECEFF4">().</span><span style="color: #88C0D0">multicast</span><span style="color: #ECEFF4">().</span><span style="color: #88C0D0">onBackpressureBuffer</span><span style="color: #ECEFF4">())</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">public</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">publish</span><span style="color: #ECEFF4">(</span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">clientId</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">message</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">Sinks</span><span style="color: #ECEFF4">.</span><span style="color: #8FBCBB">Many</span><span style="color: #ECEFF4">&lt;</span><span style="color: #8FBCBB">String</span><span style="color: #ECEFF4">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sink</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sinks</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">get</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">clientId</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">sink </span><span style="color: #81A1C1">!=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">null</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">sink</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">tryEmitNext</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">message</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">public</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Flux</span><span style="color: #ECEFF4">&lt;</span><span style="color: #8FBCBB">ServerSentEvent</span><span style="color: #ECEFF4">&lt;</span><span style="color: #8FBCBB">String</span><span style="color: #ECEFF4">&gt;&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">subscribe</span><span style="color: #ECEFF4">(</span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">clientId</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">Sinks</span><span style="color: #ECEFF4">.</span><span style="color: #8FBCBB">Many</span><span style="color: #ECEFF4">&lt;</span><span style="color: #8FBCBB">String</span><span style="color: #ECEFF4">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sink</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">createSink</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">clientId</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">Flux</span><span style="color: #ECEFF4">&lt;</span><span style="color: #8FBCBB">ServerSentEvent</span><span style="color: #ECEFF4">&lt;</span><span style="color: #8FBCBB">String</span><span style="color: #ECEFF4">&gt;&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">flux</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sink</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">asFlux</span><span style="color: #ECEFF4">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">map</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">data </span><span style="color: #8FBCBB">-&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ServerSentEvent</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">builder</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">data</span><span style="color: #ECEFF4">).</span><span style="color: #88C0D0">build</span><span style="color: #ECEFF4">())</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// heartbeat to keep connections alive</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">Flux</span><span style="color: #ECEFF4">&lt;</span><span style="color: #8FBCBB">ServerSentEvent</span><span style="color: #ECEFF4">&lt;</span><span style="color: #8FBCBB">String</span><span style="color: #ECEFF4">&gt;&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">heartbeat</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Flux</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">interval</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">Duration</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">ofSeconds</span><span style="color: #ECEFF4">(</span><span style="color: #B48EAD">15</span><span style="color: #ECEFF4">))</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">map</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">i </span><span style="color: #8FBCBB">-&gt;</span><span style="color: #D8DEE9FF"> ServerSentEvent</span><span style="color: #ECEFF4">.</span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF">String</span><span style="color: #81A1C1">&gt;</span><span style="color: #88C0D0">builder</span><span style="color: #ECEFF4">().</span><span style="color: #88C0D0">comment</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">heartbeat</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">).</span><span style="color: #88C0D0">build</span><span style="color: #ECEFF4">())</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Flux</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">merge</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">flux</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> heartbeat</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">doOnCancel</span><span style="color: #ECEFF4">(()</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">-&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sinks</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">remove</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">clientId</span><span style="color: #ECEFF4">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:clamp(12px, .75rem, 18px);font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:clamp(16px, 1rem, 24px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>/* CONTROLLER */
@RestController
@RequestMapping("/sse")
public class SseController {
    @Autowire
    SseService sseService;

    @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux&lt;ServerSentEvent&lt;String>> stream(@QueryParam String userId) {
        return sseService.subscribe(userId)
    }
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">/* CONTROLLER */</span></span>
<span class="line"><span style="color: #ECEFF4">@</span><span style="color: #D08770">RestController</span></span>
<span class="line"><span style="color: #ECEFF4">@</span><span style="color: #D08770">RequestMapping</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/sse</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #81A1C1">public</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">class</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">SseController</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">@</span><span style="color: #D08770">Autowire</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">SseService</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sseService</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">@</span><span style="color: #D08770">GetMapping</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">value</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/stream</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">produces</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MediaType</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">TEXT_EVENT_STREAM_VALUE</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">public</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Flux</span><span style="color: #ECEFF4">&lt;</span><span style="color: #8FBCBB">ServerSentEvent</span><span style="color: #ECEFF4">&lt;</span><span style="color: #8FBCBB">String</span><span style="color: #ECEFF4">&gt;&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">stream</span><span style="color: #ECEFF4">(@</span><span style="color: #D08770">QueryParam</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">userId</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sseService</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">subscribe</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">userId</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<p>Esto es lo que sucede:</p>



<ol class="wp-block-list">
<li>Cada cliente obtiene su propio receptor (un publicador reactivo).</li>



<li>Cuando el servidor llama a publish(clientId, message), ese mensaje se envía a todos los suscriptores.</li>



<li>Los latidos garantizan que los proxies no interrumpan la conexión.</li>



<li>Cuando un cliente se desconecta, el receptor se limpia.</li>
</ol>



<h3 class="wp-block-heading">Ventajas del enfoque reactivo</h3>



<ul class="wp-block-list">
<li>No bloquea hilos</li>



<li>Escala mejor con muchas conexiones abiertas</li>



<li>Integración natural con bases de datos reactivas</li>



<li>Soporte de backpressure</li>
</ul>



<h1 class="wp-block-heading">Conclusión</h1>



<p>Los <strong>Server-Sent Events</strong> son una solución elegante y eficiente para escenarios donde el servidor necesita enviar información en tiempo real al cliente sin requerir comunicación bidireccional.</p>



<ul class="wp-block-list">
<li>Si necesitas simplicidad → <strong>SSE clásico con Spring MVC</strong></li>



<li>Si necesitas alta concurrencia y escalabilidad → <strong>SSE con WebFlux</strong></li>



<li>Si necesitas bidireccionalidad → <strong>WebSockets</strong></li>
</ul>



<p>En arquitecturas modernas basadas en microservicios y sistemas event-driven, SSE sigue siendo una herramienta extremadamente útil, especialmente cuando se combina con programación reactiva.</p>



<h2 class="wp-block-heading">A lo mejor te interesa</h2>



<p><a href="https://www.pubnub.com/guides/http-streaming/">What is HTTP Streaming and How Does it Work?</a></p>



<p><a href="https://github.com/stomp-js/stompjs">stomp-js/stompjs: Javascript and Typescript Stomp client for Web browsers and node.js apps</a></p>



<p><a href="https://developer.mozilla.org/es/docs/Web/API/WebSockets_API">WebSockets &#8211; API web | MDN</a></p>



<p><a href="https://randombitsonfire.com/arquitectura/stack-para-testing-swarm-jmeter/" title="Stack para Testing (Swarm+ jMeter)">Stack para Testing (Swarm + jMeter)</a></p>



<p><a href="https://medium.com/@chillBroh/real-time-applications-with-server-sent-events-sse-in-spring-boot-186cdeffb42f">Real-Time Applications with Server-Sent Events (SSE) in Spring Boot | by Ishara Madusanka | Medium</a></p><p>The post <a href="https://randombitsonfire.com/programacion/back/conexiones-real-time-server-sent-events/">Conexiones Real Time: Server Sent Events</a> first appeared on <a href="https://randombitsonfire.com">RandomBitsOnFire</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://randombitsonfire.com/programacion/back/conexiones-real-time-server-sent-events/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Stack para Testing (Swarm+ jMeter)</title>
		<link>https://randombitsonfire.com/arquitectura/stack-para-testing-swarm-jmeter/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=stack-para-testing-swarm-jmeter</link>
					<comments>https://randombitsonfire.com/arquitectura/stack-para-testing-swarm-jmeter/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 20 Feb 2026 01:54:32 +0000</pubDate>
				<category><![CDATA[Arquitectura]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[jMeter]]></category>
		<category><![CDATA[Swarm]]></category>
		<guid isPermaLink="false">https://randombitsonfire.com/?p=128</guid>

					<description><![CDATA[<p>Introducción Es común que cuando se diseña una arquitectura de aplicaciones no baste con el desarrollo de Tests Unitarios o Tests de Integraciones, y se pase a un nivel superior, llamando se así Pruebas de Rendimiento (Performance Testing). Pruebas de rendimiento Las Pruebas de Rendimiento son una técnica de testing que consiste en someter un [&#8230;]</p>
<p>The post <a href="https://randombitsonfire.com/arquitectura/stack-para-testing-swarm-jmeter/">Stack para Testing (Swarm+ jMeter)</a> first appeared on <a href="https://randombitsonfire.com">RandomBitsOnFire</a>.</p>]]></description>
										<content:encoded><![CDATA[<h2 class="wp-block-heading">Introducción</h2>



<p>Es común que cuando se diseña una arquitectura de aplicaciones no baste con el desarrollo de Tests Unitarios o Tests de Integraciones, y se pase a un nivel superior, llamando se así <strong>Pruebas de Rendimiento</strong> (Performance Testing). </p>



<h3 class="wp-block-heading">Pruebas de rendimiento</h3>



<p>Las <strong>Pruebas de Rendimiento</strong> son una técnica de testing que consiste en someter un sistema a un volumen de peticiones controlado para analizar cómo se comporta bajo condiciones reales o esperadas de uso.</p>



<p>No se trata solo de “ver si aguanta”, sino de entender:</p>



<ul class="wp-block-list">
<li>Cuándo empieza a degradarse el rendimiento</li>



<li>Cómo responde el sistema cuando crece el tráfico</li>



<li>Dónde están los cuellos de botella</li>
</ul>



<p>Suelen a tender a las siguientes modalidades en base a la pregunta que se quiere contestar:</p>



<ul class="wp-block-list">
<li><strong>Load testing</strong> → tráfico esperado normal</li>



<li><strong>Stress testing</strong> → llevar el sistema al límite</li>



<li><strong>Spike testing</strong> → picos bruscos de tráfico</li>



<li><strong>Soak testing</strong> → carga sostenida durante mucho tiempo</li>
</ul>



<h3 class="wp-block-heading">Optimización tras las pruebas</h3>



<p>Una vez identificados los límites, el siguiente paso consiste en aplicar mejoras. Entre las más habituales encontramos:</p>



<ul class="wp-block-list">
<li>Aumento de memoria o CPU</li>



<li>Ajustes de configuración (fine tuning)</li>



<li>Pools de conexiones</li>



<li>Pools de threads</li>
</ul>



<p>En consecuencia, estas optimizaciones permiten escalar el sistema de forma controlada y eficiente.</p>



<h2 class="wp-block-heading">Testing Tools</h2>



<p>Un entorno de pruebas controlado no es un lujo, es una necesidad.</p>



<p>La combinación de:</p>



<ul class="wp-block-list">
<li><a href="https://docs.docker.com/engine/swarm/" title="Docker Swarm">Docker Swarm</a> (orquestación): Permite tener varias instancias de un contenedor y ver como se comporta en casos de balanceos</li>



<li><a href="https://prometheus.io/" title="">Prometheus </a>(métricas)</li>



<li><a href="https://grafana.com/" title="">Grafana </a>(visualización)</li>



<li><a href="https://spring.io/projects/spring-boot" title="">Spring Boot</a> + <a href="https://micrometer.io/" title="">Micrometer </a>(instrumentación)</li>



<li><a href="https://jmeter.apache.org/" title="">jMeter</a></li>
</ul>



<p>De este modo, se obtiene un ecosistema completo de observabilidad en local, muy cercano a producción y completamente reproducible.</p>



<p>Esto se traduce en <strong>menos errores, despliegues más seguros y sistemas más robustos</strong>.</p>



<p>Para ello encontré el siguiente stack que me vino de lujo para la monitorización de los diferentes micros, para ejecutar en entornos locales de prueba (y un buen maquinón xD):</p>



<p><a href="https://github.com/stefanprodan/swarmprom">https://github.com/stefanprodan/swarmprom</a></p>



<p><a href="https://dockerswarm.rocks/swarmprom">https://dockerswarm.rocks/swarmprom</a></p>



<p>Este stack integra Prometheus, Grafana y múltiples exporters listos para usar.</p>



<p>No obstante, en mi caso decidí simplificarlo ligeramente, eliminando componentes como el alerting o la integración con Slack, ya que no eran necesarios en un entorno local.</p>



<p>También quité Treffic y utilice accesos directo por localhost y sus respectivas apertura de puertos.</p>



<h2 class="wp-block-heading">jMeter</h2>



<p>Por otro lado, la generación de carga es una pieza clave. Para ello, utilicé Apache JMeter, una herramienta ampliamente utilizada en pruebas de rendimiento.</p>



<p>Sin embargo, jMeter suele venir bastante limitado de serie. Por esta razón, es recomendable ampliar sus capacidades mediante plugins.</p>



<p>En particular, una colección muy útil incluye:</p>



<ul class="wp-block-list">
<li>3 Basic Graphs</li>



<li>5 Additional Graphs</li>



<li>Composite Timeline Graph</li>



<li>Custom Thread Groups</li>



<li>Parallel Controller &amp; Sampler</li>
</ul>



<p>Gracias a estos plugins, es posible obtener una visión mucho más completa del comportamiento del sistema.</p>



<h2 class="wp-block-heading">Resultados de Testing</h2>



<p>Finalmente, el resultado es un conjunto de métricas y estadísticas que, aunque mejorables, ofrecen una base sólida para analizar la robustez de la solución planteada.</p>



<p>A partir de aquí, además, se pueden empezar a explotar métricas clave, detectar patrones de comportamiento y tomar decisiones informadas para mejorar el sistema.</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><img decoding="async" width="512" height="205" data-id="132" src="https://randombitsonfire.com/wp-content/uploads/2026/02/theeshold.png" alt="testing Custom Thread Groups" class="wp-image-132" srcset="https://randombitsonfire.com/wp-content/uploads/2026/02/theeshold.png 512w, https://randombitsonfire.com/wp-content/uploads/2026/02/theeshold-300x120.png 300w" sizes="(max-width: 512px) 100vw, 512px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="512" height="198" data-id="134" src="https://randombitsonfire.com/wp-content/uploads/2026/02/responseTimes.png" alt="testing 5 Additional Graphs" class="wp-image-134" srcset="https://randombitsonfire.com/wp-content/uploads/2026/02/responseTimes.png 512w, https://randombitsonfire.com/wp-content/uploads/2026/02/responseTimes-300x116.png 300w" sizes="auto, (max-width: 512px) 100vw, 512px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="512" height="187" data-id="133" src="https://randombitsonfire.com/wp-content/uploads/2026/02/httpcodes.png" alt="testing 5 Additional Graphs" class="wp-image-133" srcset="https://randombitsonfire.com/wp-content/uploads/2026/02/httpcodes.png 512w, https://randombitsonfire.com/wp-content/uploads/2026/02/httpcodes-300x110.png 300w" sizes="auto, (max-width: 512px) 100vw, 512px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="512" height="79" data-id="136" src="https://randombitsonfire.com/wp-content/uploads/2026/02/cpu.png" alt="Testing grafana CPU Service" class="wp-image-136" srcset="https://randombitsonfire.com/wp-content/uploads/2026/02/cpu.png 512w, https://randombitsonfire.com/wp-content/uploads/2026/02/cpu-300x46.png 300w" sizes="auto, (max-width: 512px) 100vw, 512px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="512" height="102" data-id="135" src="https://randombitsonfire.com/wp-content/uploads/2026/02/mem.png" alt="Testing grafana Memory Service" class="wp-image-135" srcset="https://randombitsonfire.com/wp-content/uploads/2026/02/mem.png 512w, https://randombitsonfire.com/wp-content/uploads/2026/02/mem-300x60.png 300w" sizes="auto, (max-width: 512px) 100vw, 512px" /></figure>
</figure>



<p class="has-text-align-right">Saludos and Happy Codding!!</p>



<p></p><p>The post <a href="https://randombitsonfire.com/arquitectura/stack-para-testing-swarm-jmeter/">Stack para Testing (Swarm+ jMeter)</a> first appeared on <a href="https://randombitsonfire.com">RandomBitsOnFire</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://randombitsonfire.com/arquitectura/stack-para-testing-swarm-jmeter/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
