장애 조치는 시스템의 일부에 장애가 발생했을 때, 자동으로 다른 정상적인 시스템이나 서버로 트래픽이나 작업을 전환하는 과정입니다. 이를 통해 서비스의 지속성을 유지하고 사용자에게 최소한의 영향만을 주도록 합니다.
복구는 장애가 발생한 시스템이나 서비스가 정상 상태로 돌아오도록 복구 작업을 수행하는 것을 말합니다. 이는 장애 원인을 해결하고, 시스템을 다시 안정적으로 운영할 수 있도록 하는 과정입니다.
4 무중단 배포(Zero Downtime Deployment)
# application.yml
spring:
cloud:
netflix:
eureka:
client:
service-url:
defaultZone: http://eureka-server:8761/eureka/
// Hystrix 예제
@RestController
public class ExampleController {
@GetMapping("/data")
@HystrixCommand(fallbackMethod = "fallbackData")
public String getData() {
// 외부 서비스 호출 등
return externalService.getData();
}
public String fallbackData() {
return "Fallback response";
}
}
http {
upstream backend {
server backend1.example.com;
server backend2.example.com;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
취업 준비 중인 신입 Java/Spring 백엔드 개발자라면 이론뿐만 아니라 실습을 통해 장애 조치(Failover)와 복구(Recovery)에 대한 이해를 깊게 하는 것이 매우 중요합니다. 다음은 실습을 통해 이러한 개념을 익힐 수 있는 몇 가지 프로젝트와 연습 방법을 제안드립니다.
Spring Boot 애플리케이션 생성:
/hello 엔드포인트가 "Hello, World!"를 반환하도록 설정합니다.@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, World!";
}
}
애플리케이션 빌드 및 Docker 이미지 생성:
Dockerfile을 작성하여 애플리케이션을 컨테이너화합니다.FROM openjdk:17-jdk-alpine
VOLUME /tmp
COPY target/demo-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
mvn clean package
docker build -t my-spring-app .
여러 인스턴스 실행:
docker run -d -p 8081:8080 my-spring-app
docker run -d -p 8082:8080 my-spring-app
Nginx 로드 밸런서 설정:
http {
upstream backend {
server localhost:8081;
server localhost:8082;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
sudo systemctl restart nginx
장애 시나리오 테스트:
docker stop <컨테이너 ID>
/hello 엔드포인트에 접속하여 응답을 확인합니다.Eureka 서버 설정:
spring-cloud-starter-netflix-eureka-server 의존성을 추가합니다.@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
application.yml 설정:server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
server:
enable-self-preservation: false
Eureka 클라이언트 서비스 설정:
spring-cloud-starter-netflix-eureka-client 의존성을 추가합니다.@SpringBootApplication
@EnableEurekaClient
public class ServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
}
}
application.yml 설정:server:
port: 8081
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
Hystrix 설정 및 회로 차단기 적용:
spring-cloud-starter-netflix-hystrix 의존성을 추가합니다.@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
public class ServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
}
}
@RestController
public class ExampleController {
@GetMapping("/data")
@HystrixCommand(fallbackMethod = "fallbackData")
public String getData() {
// 외부 서비스 호출 또는 의도적으로 예외 발생
if (new Random().nextBoolean()) {
throw new RuntimeException("Simulated service failure");
}
return "Successful response";
}
public String fallbackData() {
return "Fallback response";
}
}
장애 시나리오 테스트:
/data 엔드포인트를 여러 번 호출하여 정상 응답과 Fallback 응답이 번갈아 나오는지 확인합니다.Docker 컨테이너 이미지 준비:
Minikube 또는 Kind 설치:
# Minikube 설치 예시
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
minikube start
Kubernetes 배포 파일 작성:
deployment.yml과 service.yml 파일을 작성합니다.# deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-spring-app
spec:
replicas: 2
selector:
matchLabels:
app: my-spring-app
template:
metadata:
labels:
app: my-spring-app
spec:
containers:
- name: my-spring-app
image: my-spring-app:latest
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
# service.yml
apiVersion: v1
kind: Service
metadata:
name: my-spring-app-service
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
selector:
app: my-spring-app
Kubernetes에 배포:
kubectl apply -f deployment.yml
kubectl apply -f service.yml
자가 치유 테스트:
kubectl delete pod <포드 이름>
kubectl get pods 명령어로 새로운 포드가 생성되는지 확인합니다.헬스 체크 엔드포인트 추가:
/health)를 추가합니다.@RestController
public class HealthController {
@GetMapping("/health")
public ResponseEntity<String> health() {
return ResponseEntity.ok("OK");
}
}
클라우드 계정 생성 및 설정:
EC2 인스턴스에 Spring Boot 애플리케이션 배포:
Elastic Load Balancer(ELB) 설정:
Auto Scaling 그룹 구성:
장애 시나리오 테스트:
MySQL 데이터베이스 설정:
Spring Boot 애플리케이션과 데이터베이스 연결:
application.yml 파일에서 데이터베이스 연결 설정을 이중화된 데이터베이스로 구성합니다.spring:
datasource:
url: jdbc:mysql://master-db:3306/mydb
username: user
password: pass
jpa:
hibernate:
ddl-auto: update
백업 및 복원 스크립트 작성:
mysqldump를 사용하여 데이터베이스 백업을 수행하는 스크립트를 작성합니다.# backup.sh
mysqldump -h master-db -u user -p'pass' mydb > backup.sql
mysql 명령어를 사용합니다.mysql -h master-db -u user -p'pass' mydb < backup.sql
장애 시나리오 테스트:
Prometheus 설치 및 설정:
# prometheus.yml
scrape_configs:
- job_name: 'spring-app'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['localhost:8080']
Grafana 설치 및 대시보드 설정:
Alertmanager 설정:
# alertmanager.yml
global:
smtp_smarthost: 'smtp.example.com:587'
smtp_from: 'alert@example.com'
smtp_auth_username: 'user'
smtp_auth_password: 'password'
route:
receiver: 'email'
receivers:
- name: 'email'
email_configs:
- to: 'your-email@example.com'
알림 규칙 작성:
# alert.rules
groups:
- name: spring-app-alerts
rules:
- alert: HighResponseTime
expr: http_server_requests_seconds_sum / http_server_requests_seconds_count > 1
for: 5m
labels:
severity: critical
annotations:
summary: "High response time detected"
description: "The average response time is above 1 second for 5 minutes."
두 개의 배포 환경 구성:
blue와 green 두 개의 배포 환경을 설정합니다.로드 밸런서 설정:
blue와 green 서버를 추가하고 활성 환경을 변경합니다.배포 및 전환 테스트:
green 환경에 배포하고, 로드 밸런서를 통해 트래픽을 green으로 전환합니다.blue로 전환하여 빠르게 롤백합니다.# Nginx 예시
http {
upstream blue {
server localhost:8081;
}
upstream green {
server localhost:8082;
}
server {
listen 80;
location / {
# 현재 활성화된 환경으로 트래픽 전환
proxy_pass http://green; # 또는 http://blue
}
}
}
위의 실습 프로젝트를 통해 장애 조치(Failover)와 복구(Recovery)에 대한 실질적인 경험을 쌓을 수 있습니다. 각 프로젝트는 단계별로 진행하며, 문제를 해결하면서 개념을 보다 깊이 이해할 수 있을 것입니다. 또한, GitHub에 자신의 프로젝트를 올려 포트폴리오로 활용하면 면접 시 큰 도움이 될 것입니다. 꾸준한 실습과 학습을 통해 안정적이고 신뢰할 수 있는 백엔드 시스템을 설계하고 구현하는 능력을 키우시길 바랍니다. 화이팅!