Profile Groups & Production Patterns — gom profile, validate, blue/green
Profile groups (Boot 2.4+) gom nhiều profile thành một nhóm logic để kích hoạt bằng một tên. Bài này đào sâu cơ chế groups, multi-document YAML, mô phỏng inheritance qua include, và pattern production: secret management, blue/green canary, validate active profile khi startup.
TL;DR: Profile groups (spring.profiles.group) giải quyết bài toán "activate 5 profile rời mỗi deploy" bằng cách gom chúng dưới một tên logic: production = prod + prod-db + prod-cache + prod-tracing. Kích hoạt production, Boot tự include cả nhóm. Multi-document YAML (--- + on-profile) cho phép nhiều profile document trong một file. Inheritance mô phỏng qua spring.profiles.include hoặc thứ tự active. Production có 3 safeguard quan trọng: không hardcode secret (dùng env var ${VAR}), validate active profile khi startup (ApplicationReadyEvent), và blue/green canary qua pod env var. Bài này là tiếp nối trực tiếp của Profile — activation cơ bản: đã biết profile là gì, bài này đào sâu cách tổ chức và vận hành.
1. Vấn đề groups giải quyết
1.1 Anti-pattern: activate 5 profile rời
Không có groups, production deploy trông như này:
# Khi deploy production — 5 profile phai active
SPRING_PROFILES_ACTIVE=prod,prod-db,prod-cache,prod-tracing,prod-monitoring
Hệ quả thực tế khi làm theo cách này:
- Dễ bỏ sót: operator quên
prod-tracing→ không có observability. - Khó review: README có nhiều dòng
SPRING_PROFILES_ACTIVEdài, không nhất quán giữa team. - Brittle: thêm profile mới (
prod-audit) → phải update mọi nơi đã hardcode chuỗi 5 profile.
1.2 Cơ chế groups
Profile groups (Boot 2.4+) là mapping trong config: group-name -> [profile1, profile2, ...]. Khi Boot thấy group-name trong danh sách active, nó expand thành toàn bộ profile của group đó trước khi tiến hành load config và register bean.
flowchart LR
Activate["SPRING_PROFILES_ACTIVE=production"]
Expand["Boot expand group:<br/>production -> prod, prod-db,<br/>prod-cache, prod-tracing"]
Load["Load 4 application-*.yml<br/>Register @Profile bean cho ca 4"]
Run["App chay voi 4 profile active"]
Activate --> Expand --> Load --> RunKhai báo group trong application.yml:
spring:
profiles:
group:
production: prod, prod-db, prod-cache, prod-tracing
staging: staging, staging-db, staging-cache
development: dev, dev-db
Activate production:
java -jar app.jar --spring.profiles.active=production
Boot tự include 4 profile con. File config tách theo concern:
application-prod.yml # Spring common prod config
application-prod-db.yml # DataSource, connection pool
application-prod-cache.yml # Redis config
application-prod-tracing.yml # Micrometer, Zipkin, sampling
Mỗi file nhỏ, single concern, dễ review. Khi application-prod.yml phình to 200 dòng, group là cách clean.
Groups tốt hơn vì chỉ một nơi định nghĩa thành phần của deployment profile. Thêm concern mới (vd prod-audit) chỉ cần thêm vào group definition — không sửa Kubernetes manifest, không sửa README, không sửa CI pipeline.
1.3 Group lồng và multi-group
Group có thể bao gồm group khác không? Không trực tiếp — Boot không resolve group transitive. Nhưng profile con có thể dùng spring.profiles.include để kéo thêm profile:
# application-prod.yml — prod tự include prod-base
spring:
profiles:
include: prod-base, prod-monitoring
Activate prod → Boot include prod-base và prod-monitoring theo. Cách này mô phỏng hierachy profile.
Multi-group cho phép deploy vào nhiều region từ một codebase:
spring:
profiles:
group:
asia-east: prod-base, prod-asia-east, prod-monitoring
eu-west: prod-base, prod-eu-west, prod-monitoring
us-east: prod-base, prod-us-east, prod-monitoring
3 region — mỗi region kéo prod-base (DataSource pool, JPA config) và region-specific (DB URL, S3 endpoint). K8s manifest chỉ cần:
env:
- name: SPRING_PROFILES_ACTIVE
value: "asia-east" # hoac eu-west, us-east
2. Multi-document YAML
2.1 Cú pháp và cơ chế
Multi-document YAML (Boot 2.4+) đặt nhiều document trong một file, ngăn cách bằng ---. Mỗi document có thể gắn với profile qua spring.config.activate.on-profile:
# application.yml — single file, 3 document
spring:
application:
name: order-service
datasource:
hikari:
maximum-pool-size: 10 # default
---
spring:
config:
activate:
on-profile: dev
datasource:
url: jdbc:postgresql://localhost:5432/dev
logging:
level:
com.olhub: DEBUG
---
spring:
config:
activate:
on-profile: prod
datasource:
url: ${PROD_DB_URL}
hikari:
maximum-pool-size: 50 # override default
logging:
level:
com.olhub: INFO
Cơ chế Boot xử lý multi-document:
- Document 1 (không có
on-profile): apply làm base cho mọi profile. - Mỗi document sau: Boot kiểm tra
on-profile— nếu match active profile thì merge với base, ghi đè key trùng. - Thứ tự merge theo vị trí document trong file — document sau override document trước.
2.2 on-profile hỗ trợ expression
on-profile nhận cùng expression syntax với @Profile:
---
spring:
config:
activate:
on-profile: "prod & monitoring" # chi apply khi ca 2 profile active
management:
endpoints:
web:
exposure:
include: health,metrics,prometheus
2.3 Khi nào dùng multi-document vs separate files
| Tình huống | Approach |
|---|---|
| File ngắn (dưới 100 dòng), 2-3 profile | Multi-document — một file, thấy tổng quan dễ |
| File dài, 5+ profile, nhiều team chỉnh | Separate files — ít merge conflict |
| Dùng profile groups | Separate files — group reference file riêng |
| Quick prototype | Multi-document — không tạo nhiều file |
Multi-document YAML dùng spring.config.activate.on-profile là cú pháp Boot 2.4+. Boot 2.3 trở về dùng spring.profiles (deprecated): spring: profiles: dev. Nếu upgrade từ Boot 2.3, cần migrate sang cú pháp mới.
3. Mô phỏng inheritance
Boot không có cơ chế "profile A extends profile B" trực tiếp. Có 2 pattern mô phỏng:
3.1 Common base + override qua thứ tự active
application.yml # base cho moi profile
application-prod-base.yml # base prod (DataSource pool, JPA)
application-prod.yml # prod-specific override
application-prod-canary.yml # canary deployment override
# Active theo thu tu: base, prod-base, prod, prod-canary
SPRING_PROFILES_ACTIVE=prod-base,prod,prod-canary
Boot merge theo thứ tự — profile sau ghi đè profile trước. prod-canary có thể override một số property của prod (vd sampling.probability: 1.0 để trace mọi request trong canary pod).
3.2 spring.profiles.include — dependency tường minh
# application-prod.yml
spring:
profiles:
include: prod-base, prod-monitoring
datasource:
url: ${PROD_DB_URL}
Activate prod → Boot tự include prod-base và prod-monitoring. Đây là cách viết explicit dependency giữa profile — người đọc file thấy ngay "prod cần prod-base và prod-monitoring".
Khác biệt với group:
| Group | Include | |
|---|---|---|
| Định nghĩa ở | application.yml base | File profile con (application-prod.yml) |
| Ai quyết include | Người vận hành (operator) khi set active | Author của profile |
| Flexibility | Operator customize group | Fixed bởi author |
4. Production patterns
4.1 Secret management — không hardcode credential
Anti-pattern: credential nằm trong YAML commit lên Git:
# application-prod.yml — NGUY HIEM
spring:
datasource:
password: prod-secret-123 # hardcode, lo secret khi repo bi access
Ngay cả private repo cũng có rủi ro: repo bị clone, contributor rogue, log CI lộ. Pattern an toàn là tham chiếu env var:
# application-prod.yml — an toan
spring:
datasource:
url: ${PROD_DB_URL} # tu env var, mandatory
username: ${PROD_DB_USER}
password: ${DB_PASSWORD} # fail-fast neu missing (khong co default)
Khi Spring không tìm thấy biến env ${PROD_DB_URL} và không có giá trị default, app từ chối khởi động với IllegalArgumentException: Could not resolve placeholder. Đây là fail-fast có chủ đích.
Kubernetes Secret mount vào pod:
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secrets
key: db-password
- name: PROD_DB_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: db-url
Với HashiCorp Vault, thêm spring-cloud-starter-vault-config — Boot tự fetch secret từ Vault path khi khởi động:
spring:
cloud:
vault:
host: vault.internal
token: ${VAULT_TOKEN}
kv:
enabled: true
backend: secret
default-context: order-service
4.2 Validate active profile tại startup — fail-fast
Typo trong profile name là silent bug: SPRING_PROFILES_ACTIVE=prdo khiến Boot chạy với 0 profile active — không load application-prod.yml, không register bean prod. App khởi động thành công nhưng dùng sai config.
Pattern phòng thủ: validate tại ApplicationReadyEvent — sau khi container fully started, trước khi accept traffic:
@Component
public class StartupValidator {
@EventListener(ApplicationReadyEvent.class)
public void validate(ApplicationReadyEvent event) {
Environment env = event.getApplicationContext().getEnvironment();
String[] active = env.getActiveProfiles();
// Phai co it nhat 1 trong cac profile hop le
Profiles allowed = Profiles.of("dev", "test", "staging", "prod");
if (!env.acceptsProfiles(allowed)) {
throw new IllegalStateException(
"Active profiles must include one of: dev/test/staging/prod. Got: " +
Arrays.toString(active)
);
}
// Neu prod, validate critical property
if (env.acceptsProfiles(Profiles.of("prod"))) {
requireProperty(env, "spring.datasource.url");
requireProperty(env, "spring.datasource.password");
}
}
private void requireProperty(Environment env, String key) {
if (!StringUtils.hasText(env.getProperty(key))) {
throw new IllegalStateException("Missing required property: " + key);
}
}
}
Tại sao dùng ApplicationReadyEvent chứ không phải @PostConstruct hay ContextRefreshedEvent? Vì ApplicationReadyEvent fire sau khi toàn bộ container đã refresh xong và bean lifecycle hoàn tất — đây là điểm chắc chắn nhất. @PostConstruct chạy trong pha tạo bean — lúc đó có thể chưa đủ context.
Ngoài validator thủ công, Spring Boot Actuator cung cấp /actuator/env để debug runtime — liệt kê active profile và mọi property source. Không cần restart để kiểm tra cấu hình đang chạy.
4.3 Blue/green và canary deployment
Blue/green deployment chạy 2 phiên bản app song song và chuyển traffic sang phiên bản mới. Profile giúp phân biệt config giữa 2 phiên bản:
# application-prod-v2.yml — override config cho phien ban moi
spring:
datasource:
hikari:
maximum-pool-size: 60 # tang pool cho v2
management:
tracing:
sampling:
probability: 1.0 # trace 100% request o canary de debug
Kubernetes: 2 Deployment chia traffic:
# Deployment chinh (blue) - 90% pod
spec:
replicas: 9
template:
spec:
containers:
- name: app
env:
- name: SPRING_PROFILES_ACTIVE
value: "production" # group: prod + prod-db + prod-cache + prod-tracing
# Deployment canary (green) - 10% pod
spec:
replicas: 1
template:
spec:
containers:
- name: app
env:
- name: SPRING_PROFILES_ACTIVE
value: "production,prod-v2" # them prod-v2 override
Canary pod active 5 profile: prod, prod-db, prod-cache, prod-tracing (từ group production) và prod-v2 (trực tiếp). application-prod-v2.yml merge sau, override key cần thiết. Khi canary ổn định, dần tăng replicas canary và giảm main.
4.4 Failure runbook
Mode 1 — Profile typo, silent fallback:
- Triệu chứng: startup log hiện
No active profile set, falling back to 1 default profile. - Diagnose:
/actuator/envcheckspring.profiles.active. - Remediate:
StartupValidator(section 4.2) bắt được ngay lúc deploy.
Mode 2 — Profile conflict: 2 profile define cùng key:
- Triệu chứng: config X có 2 giá trị khác nhau giữa 2 profile đều active.
- Diagnose:
/actuator/configpropsliệt kê property source ưu tiên. - Remediate: thứ tự profile trong
spring.profiles.activecó chủ đích — profile sau ghi đè trước. Document priority rõ ràng trong README.
Mode 3 — Secret rotate, app vẫn dùng credential cũ:
- Nguyên nhân: K8s Secret update không trigger pod restart.
- Remediate: rolling restart pod sau khi rotate secret. Spring Cloud Config có
@RefreshScopecho runtime refresh không restart.
5. Pitfall
❌ Nhầm 1 — Tưởng group resolve transitive:
spring:
profiles:
group:
production: prod, prod-db
full-prod: production, prod-tracing # SAI
Boot không expand production khi xử lý group full-prod — nó treat production như tên profile literal, không phải group. Kết quả full-prod active 2 profile: production (literal string, không có file application-production.yml) và prod-tracing.
Cách đúng: liệt kê đầy đủ trong group:
spring:
profiles:
group:
full-prod: prod, prod-db, prod-tracing
❌ Nhầm 2 — Secret trong YAML commit lên Git:
# application-prod.yml
spring:
datasource:
password: actual-password # git history ghi nho mai mai
Xóa khỏi file không đủ — git log vẫn giữ. Dùng ${ENV_VAR} reference và rotate secret sau.
❌ Nhầm 3 — Không validate profile, bug ngầm production:
App active wrong profile → dùng config dev trong prod (pool size thấp, log level DEBUG, DB localhost). Silent bug cho đến khi hết connection hoặc lộ data qua verbose log.
Luôn có StartupValidator tối thiểu check profile name hợp lệ.
❌ Nhầm 4 — on-profile cú pháp Boot 2.3 lẫn Boot 2.4:
# Boot 2.3 syntax — deprecated
---
spring:
profiles: dev # deprecated
datasource:
url: jdbc:postgresql://localhost/dev
# Boot 2.4+ syntax — dung
---
spring:
config:
activate:
on-profile: dev
datasource:
url: jdbc:postgresql://localhost/dev
Lẫn lộn cú pháp → Boot 2.4+ log warning "spring.profiles is no longer supported in document-specific sections" và có thể không apply document.
6. Cơ chế bên dưới — cách Boot expand group
Khi Spring Boot khởi động, ProfilesParser (trong spring-boot module) xử lý spring.profiles.group trước khi Environment được finalize. Thứ tự:
- Boot đọc
spring.profiles.activetừ env var / JVM property /application.yml. - Với mỗi profile name trong danh sách active, Boot tra
spring.profiles.groupmap — nếu có mapping thì thêm (không replace) các profile con vào danh sách active. - Step 2 lặp lại cho các profile mới vừa thêm vào (nhưng không transitive cho group khác).
- Sau khi expand xong, Boot load
application-{profile}.ymlcho toàn bộ active profiles theo thứ tự ưu tiên.
Điểm quan trọng: expansion thêm vào, không thay thế. Sau expand production, active profile là [production, prod, prod-db, prod-cache, prod-tracing] — tên group production vẫn còn trong danh sách. Boot cũng thử load application-production.yml (thường không tồn tại, bỏ qua).
flowchart TB
Input["active = [production]"]
Lookup["Tra group map:<br/>production -> prod, prod-db,<br/>prod-cache, prod-tracing"]
Expand["active = [production, prod,<br/>prod-db, prod-cache, prod-tracing]"]
LoadYAML["Load application.yml<br/>application-prod.yml<br/>application-prod-db.yml<br/>application-prod-cache.yml<br/>application-prod-tracing.yml"]
Merge["Merge theo thu tu uu tien"]
BeanFilter["Register @Profile bean<br/>co profile match"]
Input --> Lookup --> Expand --> LoadYAML --> Merge --> BeanFilter7. Liên hệ các bài khác
- Profile — activation, @Profile trên bean, expression: bài trước giải thích profile là gì và cơ chế activation cơ bản. Bài này xây trên nền đó với groups và production patterns.
- Logging — SLF4J, log levels, config: module 06 bao gồm logging — profile thường dùng để set log level khác nhau theo môi trường (
DEBUGcho dev,INFOcho prod). Hiểu profile groups trước khi config logging per-profile. - Spring Boot AutoConfiguration — cơ chế bên dưới:
@ConditionalOnProfilelà một trong các@Conditionalautoconfiguration dùng để chỉ apply@Configurationclass khi profile match — liên hệ trực tiếp với@Profiletrong bài này. - Bean lifecycle phases:
ApplicationReadyEvent(dùng trongStartupValidator) fire ở pha cuối lifecycle — hiểu lifecycle giúp chọn đúng event listener point.
Tóm tắt
- Profile groups (
spring.profiles.group): gom nhiều profile thành một tên logic. Activate tên group → Boot expand thành danh sách đầy đủ. Giải quyết bài toán activate 5 profile rời và tránh bỏ sót profile khi deploy. - Multi-document YAML (
---+spring.config.activate.on-profile): nhiều profile document trong một file. Document đầu là base; document sau merge + override khi profile match. Phù hợp cho file ngắn, 2-3 profile; dùng separate files khi file dài hoặc nhiều team chỉnh. - Inheritance mô phỏng qua
spring.profiles.include(explicit dependency trong file profile) hoặc thứ tự cascade activation. - Secret management: không hardcode trong YAML. Dùng
${ENV_VAR}reference — app fail-fast nếu biến thiếu. Mount K8s Secret vào pod env var. - Startup validation:
@EventListener(ApplicationReadyEvent.class)kiểm tra profile hợp lệ + critical property — bắt typo profile và thiếu config tại deploy time, không phải runtime. - Blue/green canary: 2 K8s Deployment khác nhau ở
SPRING_PROFILES_ACTIVE— canary pod thêm profile override config. Profile group tách biệt concern rõ ràng. - Groups không transitive: Boot không expand group lồng trong group khác.
Tự kiểm tra
Q1Tại sao dùng profile groups thay vì liệt kê thẳng SPRING_PROFILES_ACTIVE=prod,prod-db,prod-cache,prod-tracing? Khi nào groups không đủ?▸
SPRING_PROFILES_ACTIVE=prod,prod-db,prod-cache,prod-tracing? Khi nào groups không đủ?Lý do dùng groups:
- Single source of truth: định nghĩa "production cần những profile nào" ở một chỗ trong
application.yml. Thêm profile mới chỉ sửa group definition, không sửa Kubernetes manifest / README / CI pipeline. - Tránh bỏ sót: chuỗi 5 profile dài dễ thiếu 1 khi copy-paste. Group đảm bảo tất cả được include tự động.
- Readable: operator thấy
productionhiểu ngay "đây là full production stack" — không cần nhớ 5 tên profile con.
Khi groups không đủ:
- Groups không transitive — Boot không expand group lồng trong group khác. Nếu cần hierachy phức tạp, dùng
spring.profiles.includetrong file profile con. - Groups định nghĩa tĩnh trong YAML. Nếu cần customize thành phần group theo runtime (vd chọn region dynamically), cần programmatic activation.
- Group chỉ là expansion shorthand — không thay thế được profile expression
prod & monitoringtrên@Profilebean.
Q2Cho đoạn YAML dưới đây — Boot merge document 1 và document 2 ra sao khi prod active? Giá trị cuối của hikari.maximum-pool-size là bao nhiêu?
Document 1: datasource.hikari.maximum-pool-size: 10 (no profile). Document 2: datasource.hikari.maximum-pool-size: 50 (on-profile: prod).▸
prod active? Giá trị cuối của hikari.maximum-pool-size là bao nhiêu?Document 1:
datasource.hikari.maximum-pool-size: 10 (no profile). Document 2: datasource.hikari.maximum-pool-size: 50 (on-profile: prod).Giá trị cuối là 50.
Cơ chế Boot xử lý multi-document YAML:
- Document 1 (không có
on-profile): apply làm base cho mọi profile.maximum-pool-size= 10. - Document 2 (
on-profile: prod): profileprodactive → document này được merge vào. Keymaximum-pool-sizetrùng → document sau ghi đè document trước. - Kết quả cuối:
maximum-pool-size= 50.
Nếu profile dev active thay vì prod, document 2 bị bỏ qua → giá trị giữ nguyên 10 từ base.
Đây chính là cách dùng multi-document để override default: document đầu là default safe, document sau là môi trường cụ thể. Pattern common: pool nhỏ cho dev, pool lớn cho prod; log level DEBUG cho dev, INFO cho prod.
Q3Tại sao cần StartupValidator validate active profile tại ApplicationReadyEvent? Tại sao không đủ nếu chỉ kiểm tra log?▸
StartupValidator validate active profile tại ApplicationReadyEvent? Tại sao không đủ nếu chỉ kiểm tra log?Lý do cần validator:
Typo profile name (vd prdo thay vì prod) khiến Boot chạy với 0 profile active — không load application-prod.yml, không register bean prod. App khởi động thành công nhưng dùng config sai. Không có lỗi nào xuất hiện ngay lập tức.
Silent failure này nguy hiểm hơn hard crash vì:
- App dùng config dev trong prod (pool size nhỏ, DB localhost → down, log DEBUG → verbose).
- Health check thấy app alive → không alert.
- Bug chỉ lộ khi tải thật hoặc khi operator kiểm tra log thủ công.
Tại sao không đủ nếu chỉ kiểm tra log:
Log startup ghi "No active profile set" nhưng operator phải chủ động đọc log mỗi deploy — không scalable, dễ bỏ qua trong deploy pipeline bận. Validator fail-fast: app từ chối khởi động → pod không readiness, K8s rollout dừng ngay, deployment fail rõ ràng thay vì silent.
Tại sao ApplicationReadyEvent chứ không phải @PostConstruct:
ApplicationReadyEvent fire sau khi toàn bộ container refresh xong — điểm chắc chắn nhất mọi bean đã được tạo. @PostConstruct chạy trong pha tạo bean, lúc đó Environment đã có nhưng không phải điểm "officially ready". Dùng ApplicationReadyEvent đảm bảo app thực sự sẵn sàng trước khi reject nếu config sai.
Q4Bạn cần deploy app ở 3 region: asia-east, eu-west, us-east. Mỗi region có DB URL riêng; common config (security, JPA pool) giống nhau. Thiết kế profile layout dùng groups thế nào?▸
asia-east, eu-west, us-east. Mỗi region có DB URL riêng; common config (security, JPA pool) giống nhau. Thiết kế profile layout dùng groups thế nào?Layout dùng groups + base profile:
# application.yml
spring:
profiles:
group:
asia-east: prod-base, prod-asia-east
eu-west: prod-base, prod-eu-west
us-east: prod-base, prod-us-east# application-prod-base.yml — common cho moi region
spring:
datasource:
hikari:
maximum-pool-size: 50
jpa:
hibernate:
ddl-auto: validate
logging:
level:
com.olhub: INFO# application-prod-asia-east.yml — region-specific
spring:
datasource:
url: ${ASIA_EAST_DB_URL}
cloud:
aws:
s3:
endpoint: https://s3.ap-southeast-1.amazonaws.comK8s manifest per region chỉ cần:
env:
- name: SPRING_PROFILES_ACTIVE
value: "asia-east" # hoac eu-west, us-eastLợi ích layout này:
- DRY: JPA pool, log level sống trong
prod-base.yml— thay đổi một lần apply cho 3 region. - Isolation: DB URL region-specific trong file riêng — sửa asia-east không chạm eu-west.
- Thêm region mới: tạo
prod-ap-south.yml+ thêm groupap-south: prod-base, prod-ap-south. Không duplicate base config.
Anti-pattern cần tránh: 3 file application-asia-east.yml, application-eu-west.yml, application-us-east.yml mỗi file 150 dòng duplicate 80% → cập nhật common rule phải sửa 3 file → dễ inconsistent.
Q5Blue/green deployment dùng 2 K8s Deployment: order-service (9 replica, production group) và order-service-canary (1 replica, production,prod-v2). Tại sao canary pod active 5 profile, không phải 2? Cơ chế nào giải thích?▸
order-service (9 replica, production group) và order-service-canary (1 replica, production,prod-v2). Tại sao canary pod active 5 profile, không phải 2? Cơ chế nào giải thích?Canary pod active 5 profile vì group expansion:
- Input:
SPRING_PROFILES_ACTIVE=production,prod-v2— 2 tên. - Boot tra group map:
production→[prod, prod-db, prod-cache, prod-tracing]. - Boot thêm 4 profile con vào danh sách active (không replace).
- Kết quả:
[production, prod-v2, prod, prod-db, prod-cache, prod-tracing]— 6 entry (tên groupproductionvẫn còn, nhưng không có fileapplication-production.ymlnên bỏ qua). - Boot load:
application-prod.yml,application-prod-db.yml,application-prod-cache.yml,application-prod-tracing.yml,application-prod-v2.yml. application-prod-v2.ymlmerge sau cùng → ghi đè các key override (pool size, sampling rate).
Main pod (group production) active 4 profile con: prod + prod-db + prod-cache + prod-tracing. Canary active thêm prod-v2 → override một số config (vd trace 100% request, pool size lớn hơn).
Điểm cốt lõi: expansion là additive, không replace. Profile prod-v2 được merge sau toàn bộ group — đảm bảo override có hiệu lực. Đây là lý do canary pattern hoạt động: base config giống main pod, chỉ override cần thiết.
Bài tiếp theo: Logging — SLF4J, levels, config
Bài này có giúp bạn hiểu bản chất không?
Hỏi đáp về bài này
Chưa có câu hỏi
Có gì chưa rõ trong bài? Đặt câu hỏi đầu tiên — câu trả lời từ cộng đồng giúp bạn (và người sau).
Đặt câu hỏi đầu tiên