SoFunction
Updated on 2025-04-05

Spring Cloud Consul Code Project to Implement Election Mechanism

1.What is Spring Cloud Consul?

Spring Cloud ConsulIt is a pair provided by Spring CloudHashiCorp Consulsupport. It is a service mesh-based tool for enabling service registration, discovery, configuration management, and health checks. Main functions include:

  • Service registration and discovery: Through Consul's service registration function, Spring Cloud Consul can realize dynamic registration and discovery of microservices, simplifying communication between services.
  • Distributed configuration management: Provides management of distributed configuration through Consul's Key/Value storage mechanism.
  • Health check: Supports health checks for service instances to ensure that only healthy instances are available for call from other services.
  • Election and distributed lock: Supports distributed locking and leadership elections through Consul's conversation mechanism.

Spring Cloud Consul's election mechanism

Spring Cloud Consul's election mechanism is based onConsul session (Session)andKey/Value StoreImplement distributed leadership elections.

How it works:

  • Session creation
    • The service instance creates a session to Consul, which is a temporary, instance-bound object.
    • The session comes with TTL (Survival Time), which requires regular renewal and remains active.
  • Get Lock
    • By setting the value of a Key to the current session ID, the service attempts to acquire the lock of that Key.
    • Consul uses CAS (Compare and Swap) operations to ensure that only one service instance can successfully acquire the lock.
  • Locked successfully
    • A service instance that successfully acquires the lock is considered a leader.
    • Other instances will periodically attempt to acquire the lock, but can only wait for the current lock to be released or timed out.
  • Lock release or invalid
    • If the leader instance fails to renew the session in time (such as a downtime or a network outage), Consul releases the lock associated with the session, and other instances can compete to become new leaders.

2. Environment construction

run Consul Agent

docker run -d --name=dev-consul -p 8500:8500 consul

web ui

http://localhost:8500

3. Code Engineering

Experimental objectives

  • Use the session mechanism and key-value store provided by Consul to implement itDistributed leadership elections
  • pass@InboundChannelAdapterand@ServiceActivatorRealize periodic inspection of leadership identity and perform leadership tasks.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="/POM/4.0.0"
         xmlns:xsi="http:///2001/XMLSchema-instance"
         xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.">
    <parent>
        <artifactId>springcloud-demo</artifactId>
        <groupId></groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>LeaderElection</artifactId>

    <properties>
        <>17</>
        <>17</>
    </properties>
    <dependencies>

        <dependency>
            <groupId></groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId></groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId></groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Spring Cloud Starter Consul Discovery -->
        <dependency>
            <groupId></groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId></groupId>
            <artifactId>spring-integration-core</artifactId>
        </dependency>

    </dependencies>

</project>

package ;

import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;

@Configuration
public class LeaderElectionConfig {

    private static final String LEADER_KEY = "service/leader";
    private static final String CONSUL_URL = "http://localhost:8500";
    private String sessionId;


    @Bean
    @InboundChannelAdapter(value = "leaderChannel", poller = @Poller(fixedDelay = "5000"))
    public MessageSource<String> leaderMessageSource() {
        return () -> {
            // Implement logic to check if this instance is the leader
            boolean isLeader = checkLeadership();
            return (isLeader ? "I am the leader" : "I am not the leader").build();
        };
    }

    @Bean
    @ServiceActivator(inputChannel = "leaderChannel")
    public MessageHandler leaderMessageHandler() {
        return new MessageHandler() {
            @Override
            public void handleMessage(Message<?> message) throws MessagingException {
                (());
                // Implement logic to perform leader-specific tasks
            }
        };
    }


    private final RestTemplate restTemplate = new RestTemplate();

    public LeaderElectionConfig() {
         = createSession();
    }

    private String createSession() {
        String url = CONSUL_URL + "/v1/session/create";
        HttpHeaders headers = new HttpHeaders();
        HttpEntity<String> entity = new HttpEntity<>("{\"Name\": \"leader-election-session\"}", headers);
        //ResponseEntity<String> response = (url, entity, );
        //  PUT
        ResponseEntity<String> response = (url, , entity, );
        // Extract session ID from response
        return ().split("\"")[3]; // This is a simple way to extract the session ID
    }

    public boolean checkLeadership() {
        String url = CONSUL_URL + "/v1/kv/" + LEADER_KEY + "?acquire=" + sessionId;
        HttpHeaders headers = new HttpHeaders();
        HttpEntity<String> entity = new HttpEntity<>(headers);
        ResponseEntity<Boolean> response = (url, , entity, );
        return (());
    }
    public void releaseLeadership() {
        String url = CONSUL_URL + "/v1/kv/" + LEADER_KEY + "?release=" + sessionId;
        HttpHeaders headers = new HttpHeaders();
        HttpEntity<String> entity = new HttpEntity<>(headers);
        ResponseEntity<Boolean> response = (url, , entity, );
        if ((())) {
            ("Released leadership successfully");
        } else {
            ("Failed to release leadership");
        }
    }
    @PreDestroy
    public void onExit() {
        releaseLeadership();
    }
}

Code explanation

  • initialization
    • Passed at startupcreateSession()Register a session with Consul.
  • Periodic tasks
    • Pass every 5 secondscheckLeadership()Check the leadership identity.
    • If you are a leader, perform specific tasks (such as printing logs, executing business logic).
  • Free up resources
    • When the application is closed,releaseLeadership()Release the lock.

package ;

import ;
import ;
import ;
import ;

@SpringBootApplication
@EnableDiscoveryClient
@EnableIntegration
public class LeaderElectionApplication {

    public static void main(String[] args) {
        (, args);
    }
}

Configuration File

node1

=8081
=true
=true
=leader-election-example
=localhost
=8500
-id=${}:${.instance_id:${}}

node2

=8082
=true
=true
=leader-election-example
=localhost
=8500
-id=${}:${.instance_id:${}}

The above are just some key codes.

4. Test

Start node1

java -jar  --=node1

Start node2 node

java -jar  --=node2

Observe the logs through the console, only one of them can be selected as the host

The above is the detailed content of the code project for Spring Cloud Consul to implement the election mechanism. For more information about the election mechanism of Spring Cloud Consul, please pay attention to my other related articles!