EC2 2대(이상) 중에 리더를 선출하는 방법은 다음과 같다.

 

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.Instant;
import java.util.Optional;

@Configuration
public class AppConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Bean
    public String instanceId(RestTemplate restTemplate) {
        String instanceId = restTemplate.getForObject("http://169.254.169.254/latest/meta-data/instance-id", String.class);
        System.out.println("Instance ID: " + instanceId);
        return instanceId;
    }
}

@Service
public class LeaderElectionService {
    private static final String LEADER_ID = "current_leader";

    @Autowired
    private LeaderRepository leaderRepository;

    @Autowired
    private String instanceId;

    @Scheduled(fixedRate = 30000)  // 30초마다 실행
    public void electLeader() {
        Instant now = Instant.now();
        Optional<Leader> leader = leaderRepository.findById(LEADER_ID);

        if (leader.isEmpty() || leader.get().getTimestamp().isBefore(now.minusSeconds(60))) {
            Leader newLeader = new Leader();
            newLeader.setId(LEADER_ID);
            newLeader.setInstanceId(instanceId);
            newLeader.setTimestamp(now);
            leaderRepository.save(newLeader);
            System.out.println("Instance " + instanceId + " is the leader.");
        } else if (leader.get().getInstanceId().equals(instanceId)) {
            // 자신이 리더인 경우 주기적으로 timestamp 갱신
            leader.get().setTimestamp(now);
            leaderRepository.save(leader.get());
            System.out.println("Instance " + instanceId + " is still the leader.");
        } else {
            System.out.println("Instance " + instanceId + " is not the leader.");
        }
    }
}

 

리더를 저장하는 mongoDB 컬렉션은 아래와 같이 정의한다.

 

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;

import java.time.Instant;

@Document(collection = "leaderElection")
public class Leader {
    @Id
    private String id;
    private String instanceId;
    @Indexed(expireAfterSeconds = 60)
    private Instant timestamp;

    // getters and setters
}

 

 

 

그리고 main에  @EnableScheduling 이 필요하다.

@SpringBootApplication
@EnableScheduling
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

Posted by yongary
,