소개: 지능형 배포 및 확장
모듈형 모노리스의 주요 장점 중 하나는 배포의 단순성: 단일 아티팩트, 단일 CI/CD 파이프라인, 모니터링할 단일 프로세스. 하지만 단순함 그것은 제한을 의미하지 않습니다. 올바른 전략을 사용하면 모듈식 모놀리스를 다음과 같이 배포할 수 있습니다. 다운타임 없음, 지능적으로 확장하고 동일한 정교함으로 관리 운영 비용의 일부만으로 마이크로서비스 아키텍처를 구현합니다.
이 문서에서는 모듈식 모놀리스에 대한 고급 배포 전략을 살펴보겠습니다. 블루-그린 배포, 배포와 릴리스를 분리하는 기능 플래그, 기반 자동 확장 메트릭, 모듈을 독립형 마이크로서비스로 추출할 시기를 결정하는 기준.
이 기사에서 배울 내용
- 다운타임 없는 업데이트를 위한 블루-그린 배포
- 기능 플래그: 기능 릴리스에서 배포를 분리합니다.
- Kubernetes HPA 및 사용자 정의 지표를 사용한 자동 크기 조정
- 상황별 확장: 모듈당 리소스 최적화
- 데이터베이스 확장: 읽기 전용 복제본, 연결 풀링, 샤딩
- 모듈을 마이크로서비스로 추출하는 경우
- 모듈식 모놀리스를 위한 Kubernetes 구성 예시
모놀리식 배포: 한 번 구축하여 어디에나 배포
모듈식 모놀리스의 배치는 원칙을 따릅니다. "한 번 구축하면 어디에나 배포 가능": 단일 아티팩트(JAR, Docker 이미지)가 한 번 빌드되어 모든 환경에 배포됩니다. (스테이징, 프로덕션, DR). 이는 환경 간의 불일치 위험을 제거하고 단순화합니다. CI/CD 파이프라인을 대폭 확장합니다.
# Pipeline CI/CD per modular monolith
# Un singolo artefatto per tutti gli ambienti
# .github/workflows/deploy.yml
name: Build and Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build application
run: ./gradlew build
- name: Build Docker image
run: |
docker build -t ecommerce-app:$GITHUB_SHA .
- name: Push to registry
run: |
docker push registry.example.com/ecommerce-app:$GITHUB_SHA
deploy-staging:
needs: build
runs-on: ubuntu-latest
steps:
- name: Deploy to staging
run: |
kubectl set image deployment/ecommerce \
app=registry.example.com/ecommerce-app:$GITHUB_SHA \
--namespace staging
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment: production # richiede approvazione manuale
steps:
- name: Deploy to production
run: |
kubectl set image deployment/ecommerce \
app=registry.example.com/ecommerce-app:$GITHUB_SHA \
--namespace production
블루-그린 배포: 가동 중지 시간 없음
Il 청록색 배포 두 개의 동일한 환경을 유지합니다. 파란색 (활성, 트래픽 제공) e 녹색 (비활성, 다음 릴리스 준비) 배포는 유휴 환경에서 이루어지며 트래픽 전환은 전체 환경에서 즉각적으로 이루어집니다. 로드 밸런서 또는 Kubernetes 서비스 변경.
장점
- 다운타임 없음: 스위치가 즉각적으로 이루어지며 사용자가 방해를 받지 않습니다.
- 즉시 롤백: 문제가 발생하면 이전 환경으로 돌아가면 됩니다.
- 스위치 전 검증: 전환 전 그린 환경에서 새로운 배포를 테스트할 수 있습니다.
# Kubernetes: Blue-Green deployment con Service switch
# Blue deployment (attualmente attivo)
apiVersion: apps/v1
kind: Deployment
metadata:
name: ecommerce-blue
labels:
app: ecommerce
version: blue
spec:
replicas: 4
selector:
matchLabels:
app: ecommerce
version: blue
template:
metadata:
labels:
app: ecommerce
version: blue
spec:
containers:
- name: app
image: registry.example.com/ecommerce-app:v1.2.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
---
# Service che punta al deployment attivo
apiVersion: v1
kind: Service
metadata:
name: ecommerce-service
spec:
selector:
app: ecommerce
version: blue # Cambia in "green" per lo switch
ports:
- port: 80
targetPort: 8080
기능 플래그: 배포 및 릴리스 분리
I 기능 플래그 코드를 활성화하지 않고도 프로덕션 환경에 코드를 배포할 수 있습니다. 즉시. 특정 목적을 위해 기능을 점진적으로 활성화할 수 있습니다(카나리아 릴리스). 사용자(베타 테스트) 또는 특정 지역용. 이것은 순간을 완전히 분리합니다 의 배포 (프로덕션 코드) 당시부터 풀어 주다 (사용자에게 표시되는 기능).
// Feature Flags con Spring Boot e Unleash
@Service
class OrderServiceImpl implements OrderModuleApi {
private final FeatureFlagService featureFlags;
@Override
public OrderDto createOrder(CreateOrderCommand cmd) {
Order order = Order.create(cmd);
// Feature flag: nuovo sistema di pricing
if (featureFlags.isEnabled("new-pricing-engine")) {
order.applyNewPricing(pricingEngine.calculate(cmd));
} else {
order.applyLegacyPricing(cmd.getItems());
}
// Feature flag: notifica push (graduale)
if (featureFlags.isEnabled("push-notifications",
cmd.getUserId())) {
notificationModule.sendPush(order);
}
orderRepository.save(order);
return order.toDto();
}
}
// Configurazione Feature Flags con Unleash
@Configuration
class FeatureFlagConfig {
@Bean
public Unleash unleash() {
return new DefaultUnleash(
UnleashConfig.builder()
.appName("ecommerce-app")
.instanceId("instance-1")
.unleashAPI("http://unleash:4242/api")
.build()
);
}
}
Kubernetes HPA를 통한 자동 확장
Il 수평형 포드 자동 확장 처리(HPA) Kubernetes는 자동으로 숫자를 확장합니다. CPU, 메모리 또는 사용자 정의 측정항목을 기반으로 하는 Pod의 수입니다. 모듈식 모노리스의 경우 HPA 전체 애플리케이션을 균일하게 확장합니다. 다음을 기반으로 사용자 정의 측정항목을 구성할 수 있습니다. 분당 주문 수와 같은 비즈니스별 지표.
# HPA per il modular monolith
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ecommerce-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ecommerce-app
minReplicas: 3
maxReplicas: 12
metrics:
# Scala basato su CPU
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
# Scala basato su metriche custom
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "1000"
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Pods
value: 2
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 1
periodSeconds: 120
데이터베이스 확장
모듈식 모놀리스에서는 데이터베이스가 컴퓨팅 전에 병목 현상을 일으키는 경우가 많습니다. 여기 있습니다 데이터베이스 확장 전략:
답글 읽기
구성 답글 읽기 데이터베이스의 읽기 쿼리를 다음으로 라우팅합니다. 답글. 쓰기 작업은 기본으로 이동합니다. 이는 특히 다음과 같은 경우에 효과적입니다. 읽기 모델이 전용 복제본에 있을 수 있는 CQRS 패턴.
연결 풀링
다음과 같은 연결 풀러를 사용하십시오. PgBouncer 연결을 효율적으로 관리하기 위해 데이터베이스에. 모놀리스 인스턴스가 많아지면 데이터베이스 연결 수가 늘어날 수 있습니다. 빨리. PgBouncer는 효과적인 데이터베이스 연결 수를 줄입니다.
모듈별 샤딩
특정 모듈의 데이터 볼륨이 다른 모듈보다 훨씬 큰 경우 해당 테이블을 이동할 수 있습니다. 전용 데이터베이스에서. 이는 마이크로서비스로 추출하기 위한 중간 단계입니다.
모듈을 마이크로서비스로 추출해야 하는 경우
모듈형 단일체는 반드시 영원히 단일체로 남아있을 필요는 없습니다. 데이터가 이를 정당화하면 모듈을 독립적인 마이크로서비스로 추출할 수 있습니다. 다음은 결정적인 기준:
정량적 기준
- 10배 스케일링: 모듈에는 다른 모듈보다 10배 더 많은 리소스가 필요합니다.
- 배포 빈도: 모듈에는 5배 더 자주 릴리스가 필요합니다.
- SLA 대기 시간: 모듈의 대기 시간 SLA가 다릅니다(예: 중요한 API의 경우 10ms 미만).
- 팀 규모: 5명 이상의 개발자가 모듈 전용으로 작업
품질 기준
- 기술 스택: 모듈은 다른 언어나 런타임의 이점을 누릴 수 있습니다.
- 장애 격리: 모듈의 버그로 인해 전체 시스템이 충돌할 수 있습니다.
- 규정 준수: 모듈은 특정 보안 또는 규정 준수 요구 사항에 따라 데이터를 관리합니다.
- 캐싱: 모듈은 나머지 모듈과 매우 다른 캐싱 패턴을 가지고 있습니다.
추출에 대한 경험 법칙
다음이 나올 때까지 모듈을 마이크로서비스로 추출하지 마세요. 최소 3개의 양적 기준 만족하다. 조기 추출로 인해 이점 없이 분산된 복잡성이 발생합니다. 비례. 기억하세요: 모듈형 모노리스는 쉽게 추출할 수 있도록 설계되었습니다. 필요할 때, 강요하지 마세요.
Kubernetes 설정 완료
다음은 모듈식 모놀리스 배포를 위한 참조 Kubernetes 구성입니다. 프로덕션에서는 상태 확인, 리소스 제한, 선호도 규칙을 사용합니다.
# Deployment completo per modular monolith
apiVersion: apps/v1
kind: Deployment
metadata:
name: ecommerce-app
labels:
app: ecommerce
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: ecommerce
template:
metadata:
labels:
app: ecommerce
spec:
containers:
- name: app
image: registry.example.com/ecommerce-app:latest
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "production"
- name: JAVA_OPTS
value: "-Xms512m -Xmx2g -XX:+UseG1GC"
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "1000m"
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 60
periodSeconds: 30
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: ecommerce
모니터링 및 관찰 가능성
모듈형 모노리스의 중요한 장점은 모니터링이 간편하다는 것입니다. 싱글로 프로세스, 측정항목이 중앙 집중화되고, 로그가 통합되고, 추적이 로컬로 이루어집니다.
- 측정항목: Prometheus로 메트릭을 내보내기 위한 Spring Boot Actuator + 마이크로미터
- 통나무: 모듈 간 흐름을 추적하기 위한 상관 관계 ID가 포함된 구조화된 로깅
- 건강검진: 개별 건강 상태를 확인하기 위한 각 모듈의 엔드포인트
- 대시보드: 집계된 지표와 모듈별 지표를 보는 Grafana
다음 기사
다음 기사에서는 이에 대해 다루겠습니다. 단계별 마이그레이션 단일체에서 모듈식 단일체에 대한 유산: Strangler Fig 패턴, 경계 식별, 물리적 모듈 추출, 이벤트 마이그레이션 및 현실적인 타임라인 사례 연구와 지표를 활용하세요.







