Apache Pulsar es una plataforma de mensajería y streaming distribuida que combina colas de trabajo y registros de eventos en un mismo sistema. Separa el servicio de mensajes (brokers) del almacenamiento (Apache BookKeeper) y organiza los topics en tenants y namespaces, lo que facilita darle servicio a varios equipos o clientes con un único clúster. En este tutorial instalarás Pulsar 4 en modo standalone en Ubuntu 24.04, lo ejecutarás como servicio de systemd y usarás pulsar-admin y pulsar-client para crear tus primeros topics, publicar y consumir mensajes.
El modo standalone ejecuta el broker, BookKeeper y el almacén de metadatos en un solo proceso Java. Es ideal para desarrollo, pruebas y cargas pequeñas, pero no ofrece alta disponibilidad.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS de 64 bits, por ejemplo un VPS de CubePath, con al menos 4 GB de RAM y 2 vCPU.
- Unos 10 GB libres en disco para los datos de BookKeeper.
- Un usuario no root con privilegios
sudo. - UFW activo con el acceso SSH permitido.
Pulsar frente a Kafka en pocas líneas
Si vienes de Kafka, estas son las diferencias que más se notan al empezar:
| Aspecto | Apache Pulsar | Apache Kafka |
|---|---|---|
| Almacenamiento | Separado en BookKeeper, los brokers no guardan estado | En los propios brokers |
| Multi-tenant | Nativo: tenant, namespace y topic | Sin jerarquía, se simula con prefijos y ACL |
| Modelos de consumo | Exclusive, Failover, Shared y Key_Shared | Grupos de consumidores por partición |
| Colas de trabajo | Sí, con suscripciones Shared y ack por mensaje | Limitado al número de particiones |
| Retención | Configurable por namespace, con almacenamiento por niveles | Configurable por topic |
Paso 1: Instalar Java 21
Pulsar 4 necesita Java 21. Instala el runtime de OpenJDK sin interfaz gráfica:
sudo apt update
sudo apt install openjdk-21-jre-headless
Comprueba la versión:
java -version
openjdk version "21.0.8" 2025-07-15
OpenJDK Runtime Environment (build 21.0.8+9-Ubuntu-0ubuntu124.04.1)
OpenJDK 64-Bit Server VM (build 21.0.8+9-Ubuntu-0ubuntu124.04.1, mixed mode, sharing)
Paso 2: Descargar Pulsar
Crea un usuario de sistema sin shell para ejecutar Pulsar:
sudo useradd --system --home-dir /opt/pulsar --shell /usr/sbin/nologin pulsar
Descarga la distribución binaria y su suma SHA-512 desde el archivo de Apache. Esta guía usa la versión 4.2.4; consulta la última en la página de descargas de Pulsar y ajusta la variable si es necesario:
PULSAR_VERSION=4.2.4
cd /tmp
curl -fLO "https://archive.apache.org/dist/pulsar/pulsar-${PULSAR_VERSION}/apache-pulsar-${PULSAR_VERSION}-bin.tar.gz"
curl -fLO "https://archive.apache.org/dist/pulsar/pulsar-${PULSAR_VERSION}/apache-pulsar-${PULSAR_VERSION}-bin.tar.gz.sha512"
Verifica la integridad del archivo:
sha512sum -c "apache-pulsar-${PULSAR_VERSION}-bin.tar.gz.sha512"
./apache-pulsar-4.2.4-bin.tar.gz: OK
Descomprímelo en /opt/pulsar y asigna la propiedad al usuario pulsar:
sudo mkdir -p /opt/pulsar
sudo tar -xzf "apache-pulsar-${PULSAR_VERSION}-bin.tar.gz" -C /opt/pulsar --strip-components=1
sudo chown -R pulsar:pulsar /opt/pulsar
Comprueba el contenido con ls /opt/pulsar. Deben aparecer, entre otros, los directorios bin (herramientas como pulsar, pulsar-admin y pulsar-client), conf (configuración) y lib (las bibliotecas Java).
Paso 3: Crear el servicio de systemd
Pulsar incluye bin/pulsar-daemon, pero un servicio de systemd arranca con el sistema, se reinicia si falla y envía la salida al journal. Crea la unidad:
sudo nano /etc/systemd/system/pulsar.service
[Unit]
Description=Apache Pulsar standalone
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=pulsar
Group=pulsar
WorkingDirectory=/opt/pulsar
Environment="PULSAR_MEM=-Xms1g -Xmx1g -XX:MaxDirectMemorySize=2g"
ExecStart=/opt/pulsar/bin/pulsar standalone
Restart=on-failure
RestartSec=10
TimeoutStopSec=60
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
La variable PULSAR_MEM sustituye la configuración de memoria por defecto de conf/pulsar_env.sh (2 GB de heap y hasta 4 GB de memoria directa), que es excesiva para un servidor de 4 GB. Si tienes 8 GB o más, puedes quitar esa línea.
Recarga systemd y arranca el servicio:
sudo systemctl daemon-reload
sudo systemctl enable --now pulsar
El primer arranque tarda entre 30 y 60 segundos, porque inicializa los metadatos, BookKeeper y el namespace public/default. Sigue el progreso en el journal:
sudo journalctl -u pulsar -f
Pulsa Ctrl+C cuando dejen de aparecer mensajes de arranque. Comprueba que el broker responde en su API de administración:
curl -s http://localhost:8080/admin/v2/clusters
["standalone"]
Y que escucha en sus dos puertos: 6650 para el protocolo binario de los clientes y 8080 para la API HTTP de administración:
sudo ss -tlnp | grep -E ':(6650|8080)\s'
ImportantePulsar standalone escucha en todas las interfaces y no tiene autenticación activada. No abras los puertos 6650 ni 8080 en UFW. Si necesitas acceso desde otra máquina, permítelo solo desde su IP, por ejemplo
sudo ufw allow from 10.0.0.20 to any port 6650 proto tcp.
Para no escribir la ruta completa en cada comando, añade bin al PATH de tu sesión:
export PATH="/opt/pulsar/bin:$PATH"
Verifica el estado del broker:
pulsar-admin brokers healthcheck
ok
Paso 4: Crear un tenant y un namespace
Pulsar organiza los topics en tres niveles: tenant (un equipo o cliente), namespace (una aplicación, con sus propias políticas) y topic. Crea un tenant acme autorizado en el clúster standalone:
pulsar-admin tenants create acme --allowed-clusters standalone
Crea un namespace para la aplicación de pedidos:
pulsar-admin namespaces create acme/pedidos
Por defecto, Pulsar borra los mensajes en cuanto todas las suscripciones los han confirmado. Configura una retención de 7 días o 10 GB para poder releerlos:
pulsar-admin namespaces set-retention acme/pedidos --time 7d --size 10G
Comprueba el resultado:
pulsar-admin namespaces list acme
pulsar-admin namespaces get-retention acme/pedidos
acme/pedidos
{
"retentionTimeInMinutes" : 10080,
"retentionSizeInMB" : 10240
}
Paso 5: Crear un topic particionado
Un topic particionado reparte la carga entre varias particiones internas, que en un clúster real se distribuyen entre brokers. Crea uno con 3 particiones:
pulsar-admin topics create-partitioned-topic persistent://acme/pedidos/eventos --partitions 3
Lista los topics particionados del namespace:
pulsar-admin topics list-partitioned-topics acme/pedidos
persistent://acme/pedidos/eventos
El prefijo persistent:// indica que los mensajes se escriben en BookKeeper antes de confirmarse al productor. Los topics non-persistent:// son más rápidos pero pierden los mensajes si el broker se reinicia.
Paso 6: Publicar y consumir mensajes
Abre una segunda sesión SSH, añade de nuevo /opt/pulsar/bin al PATH y arranca un consumidor con una suscripción Shared, en la que varios consumidores se reparten los mensajes como en una cola de trabajo. -n 0 hace que consuma indefinidamente:
pulsar-client consume persistent://acme/pedidos/eventos \
-s procesador -t Shared -p Earliest -n 0
En la primera sesión, publica diez mensajes separados por comas:
pulsar-client produce persistent://acme/pedidos/eventos \
--messages "$(seq -s, -f 'pedido-%g' 1 10)"
... 10 messages successfully produced
El consumidor los muestra al instante:
----- got message -----
key:[null], properties:[], content:pedido-1
----- got message -----
key:[null], properties:[], content:pedido-2
...
Si arrancas un segundo consumidor con la misma suscripción procesador, los siguientes mensajes se repartirán entre ambos. Con -t Exclusive (el valor por defecto) solo se admite un consumidor por suscripción, y con -t Failover hay uno activo y los demás esperan como reserva.
Consulta las estadísticas del topic para ver productores, suscripciones y mensajes pendientes:
pulsar-admin topics partitioned-stats persistent://acme/pedidos/eventos
En la salida JSON, msgInCounter indica los mensajes recibidos y, dentro de subscriptions.procesador, msgBacklog los que quedan por consumir.
Paso 7: Conectarse desde una aplicación Python
Las aplicaciones usan las librerías cliente oficiales. Este ejemplo publica un mensaje con el cliente de Python:
sudo apt install python3-venv
python3 -m venv ~/pulsar-venv
~/pulsar-venv/bin/pip install pulsar-client
nano ~/productor.py
import pulsar
client = pulsar.Client("pulsar://localhost:6650")
producer = client.create_producer("persistent://acme/pedidos/eventos")
msg_id = producer.send("pedido-desde-python".encode("utf-8"))
print(f"Publicado con id {msg_id}")
client.close()
~/pulsar-venv/bin/python ~/productor.py
El consumidor que dejaste abierto en el paso anterior recibirá pedido-desde-python.
Solución de problemas
- El servicio se reinicia en bucle: revisa
sudo journalctl -u pulsar -n 100 --no-pager. Si apareceUnsupportedClassVersionError, no se está usando Java 21; compruebajava -versionysudo update-alternatives --config java. java.lang.OutOfMemoryErroro el proceso muere por OOM: el servidor no tiene memoria suficiente para los valores dePULSAR_MEM. Redúcelos o amplía la RAM.Address already in useal arrancar: otro servicio usa el puerto 8080 o 6650. Localízalo consudo ss -tlnp | grep -E ':(6650|8080)\s'.Tenant does not existoNamespace does not exist: el nombre del topic debe seguir el formatopersistent://tenant/namespace/topic. Los nombres cortos comomi-topicse resuelven apublic/default.
Conclusión
Tienes Apache Pulsar 4 en modo standalone funcionando como servicio en Ubuntu 24.04, con un tenant y un namespace con retención, un topic particionado y productores y consumidores de prueba. Como siguientes pasos, puedes activar la autenticación por token JWT en conf/standalone.conf, explorar Pulsar Functions para procesar mensajes sin desplegar servicios aparte, o planificar un clúster de producción con brokers, bookies y almacén de metadatos en servidores separados.
