# pulsar-failover-demo
**Repository Path**: mirrors_datastax/pulsar-failover-demo
## Basic Information
- **Project Name**: pulsar-failover-demo
- **Description**: A sample app that demos pulsar cluster failover
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2025-02-28
- **Last Updated**: 2025-12-20
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# pulsar-failover-demo
A sample app that demos [Pulsar](https://pulsar.apache.org/ "Pulsar") dynamic client (Producer/Consumer) traffic routing using a REST based `Provider` app that generates [pulsar-native configuration](https://pulsar.apache.org/docs/3.3.x/client-libraries-cluster-level-failover/#controlled-failover "Controlled failover") to manage which Pulsar cluster the clients should dynamically connect to in real-time. Note, the `Provider` app can be used in two ways
- **Simple Provider**: This Provider allows `Fixed` routing. Only one cluster will be `Active` at any given time, and all other clusters will be set as `Passive`. All clients (Producer/Consumer) will connect to the `Active` cluster
- **Smart Provider**: This Provider allows `Smart and Dynamic` routing.Any Pulsar client (Producer/Consumer) can be mapped to any cluster in real-time based on routing managed by the `Provider`. This is an `Active/Active` setup.
This app has Four components
- A [**Simple Provider** app](https://github.com/datastax/pulsar-failover-demo/blob/main/src/main/java/com/datastax/demo/streaming/provider/ClusterConfigProvider.java ) that works as a simple URL Service Provider as [shown here](https://pulsar.apache.org/docs/3.3.x/client-libraries-cluster-level-failover/#controlled-failover "shown here").
- A [**Smart Provider** app](https://github.com/datastax/pulsar-failover-demo/blob/main/src/main/java/com/datastax/demo/streaming/provider/SmartConfigProvider.java) that is a heavily customized version of the above mentioned Pulsar cluster-level-failover technique to provide smart-routing based on user-defined-configurations that can be dynamically updated.
- A [**Producer** app](https://github.com/datastax/pulsar-failover-demo/blob/main/src/main/java/com/datastax/demo/streaming/producer/ProducerApp.java "**Producer** app") that produce messages at regular intervals. You can start one of more instances of this app.
- A [**Consumer** app](https://github.com/datastax/pulsar-failover-demo/blob/main/src/main/java/com/datastax/demo/streaming/consumer/ConsumerApp.java "**Consumer** app") that consumes messages produced by the above Producer. You can start one of more instances of this app.
> [!NOTE]
> You must start one (and only one) instance of the `Provider` app (either `Simple Provider` or the `Smart Provider`) before starting any clients (i.e. `Producer` or `Consumer`). If you plan on having more than one instance of this app for High-Availability (HA), you must put these instances behind a single HA load-balancer and the Producer and Consumer will need to access it via the load-balancer. You will also need to customize the app further such that all the instances share the same configuration state at any time (e.g. by using a shared DB to persist configuration).
Below is a high-level diagram of the above components and the Pulsar Controlled Failover flow
------------
### Prerequisites
- Java 11
- Apache Maven 3.8.x (to build the app)
- Pulsar 3.x
- Two (or more) Pulsar based Streaming clusters
- One clusters will be the **Primary**, while all the other clusters will be **DR** clusters that can takeover in case of a failover
- For the purpose of this demo, we will use [Astra Streaming](https://www.datastax.com/products/astra-streaming) (SaaS Streaming provider by DataStax) to standup two Pulsar based streaming clusters.
### Building the app
- Update applicable properties of the [application.properties](https://github.com/datastax/pulsar-failover-demo/blob/main/src/main/resources/application.properties) file based on your Pulsar environment and use-case
- From root of this repo, run command `mvn clean package -Passembly`
### Running the app
First start either the **Simple Provider** or the **Smart Provider** app using command
- Simple Provider: `java -cp target/producer_failover-*-jar-with-dependencies.jar com.datastax.demo.streaming.provider.ClusterConfigProvider`
- Smart Provider: `java -cp target/producer_failover-*-jar-with-dependencies.jar com.datastax.demo.streaming.provider.SmartConfigProvider`
Then start the **Producer** app using command `java -cp target/producer_failover-*-jar-with-dependencies.jar com.datastax.demo.streaming.producer.ProducerApp `
Finally start the **Consumer** app using command `java -cp target/producer_failover-*-jar-with-dependencies.jar com.datastax.demo.streaming.consumer.ConsumerApp `
> [!NOTE]
> - You can have as many (one or more) instances of `Producers` and `Consumer`, however you must have only one instance of `Provider`.
> - The command-line params `` and `` are **_only_** applicable when using the `Smart Provider`
> - Consumer requires additional Subscription details command-line params `` consisting of two component which are `:` seperated.
> - Subscription Name: This will be the subscription name that the consumer will attach itself to. **_If the subscription name does not exist, a new subscription will be created._**
> - Subscription Type: Subscription type will determine the characteristics of the subscription and consumer behavior. Below are the details on different types of subscription.
> - `S(Shared)` : A shared subscription allows multiple consumers to consume messages from a single topic in a round-robin fashion.
> - Subscription type Shared is treated as a default by this app. In case of the subscription type is not provided or is invalid/unknown the app will default to Shared subscription type.
> - `E(Exclusive)` : An exclusive subscription describes a basic publish-subscribe (pub-sub) pattern where a single consumer subscribes to a single topic and consumes from it.
> - If a subscription is marked as Exclusive, the system is restricted to a single consumer, request to bring up any additional consumer will result in error.
> - `F(Failover)` : In failover subscriptions, Pulsar designates one primary consumer and multiple standby consumers. If the primary consumer disconnects, the standby consumers begin consuming the subsequent unacknowledged messages.
> - This requires multi consumer setup to achieve primary-standby dynamic.
> - `K(Key shared)` : Key shared subscriptions allow multiple consumers to subscribe to a topic, and provide additional metadata in the form of keys that link messages to specific consumers.
> - For the demo purpose of this app we will not be considering this subscription type.
>>**_For more information on Subscriptions and uses please refer to [Subscription Overview](https://docs.datastax.com/en/astra-streaming/astream-subscriptions.html)_**
### Performing failover using Simple Provider
The above demo app uses two [Astra Streaming](https://www.datastax.com/products/astra-streaming) SaaS clusters (ideally deployed in different regions) with bidirectional replication. [You can configure](https://github.com/datastax/pulsar-failover-demo/blob/main/src/main/resources/application.properties#L2) as many cluster as needed for your use-case. The `Simple Provider` will then allow you to mark any one cluster to be `Active` at anytime. All other cluster will be auto set to `Passive`.
You can find which cluster is currently Primary at anytime by hitting the Provider endpoint at `/getConfig`. If you are running the app locally, it can be accessed [here](http://localhost:8080/getconfig) `http://localhost:8080/getconfig`
To inject a failover, go to Provider endpoint `/setConfig` and pass a JSON request body of `{"cluster-name": "clusterB"}`. Note, the value can be `clusterA` OR `clusterB` based on the cluster you want to failover to. If running locally, you could initiate a failover by posting the above JSON body to [endpoint](http://localhost:8080/setconfig) `http://localhost:8080/setconfig`
------------
### Simple Provider Demo
- Start `Provider`, followed by `Producer` and `Consumer`. Producer and Consumer messages show `clusterA` (useast1) as the primary (see below screenshots)
- On `Provider`, check the current Cluster via a tool like Postname (see below screenshots)
- On `Provider`, now perform failover to `clusterB`
- Now `Producer` and `Consumer` messages should show `clusterB` (useast4) post failover
------------
### Performing dynamic routing using Smart Provider
The above demo app uses two [Astra Streaming](https://www.datastax.com/products/astra-streaming) SaaS clusters (ideally deployed in different regions) with bidirectional replication. [You can configure](https://github.com/datastax/pulsar-failover-demo/blob/main/src/main/resources/application.properties#L2) as many cluster as needed for your use-case. The `Smart Provider` will then allow you to map any group of clients to any cluster as needed. All clusters are always `Active` at all times and any number of clients can be mapped to them.
For more details on how to use the `Smart Provider` for traffic routing, use the provided [REST OpenAPI specification file](https://github.com/datastax/pulsar-failover-demo/blob/main/src/main/resources/provider_api.yaml) and/or the sample [POSTMan Collection](https://github.com/datastax/pulsar-failover-demo/blob/main/src/main/resources/PulsarProvider.postman_collection.json) file.
------------