SpringBoot中5種服務可用性保障技術分享
1. 熔斷器模式(Circuit Breaker)
基本原理
熔斷器模式借鑒了電路熔斷器的概念,當檢測到系統(tǒng)中某個服務或組件頻繁失敗時,自動"斷開"對該服務的調用,防止級聯(lián)故障,同時為故障服務提供恢復時間。熔斷器有三種狀態(tài):
- 關閉狀態(tài):正常執(zhí)行操作,同時監(jiān)控失敗率
- 開啟狀態(tài):拒絕訪問,直接返回錯誤或執(zhí)行降級邏輯
- 半開狀態(tài):嘗試恢復,允許有限的請求通過以測試服務是否恢復
SpringBoot實現(xiàn)與集成
在SpringBoot中,我們可以使用Resilience4j實現(xiàn)熔斷器模式,它是Hystrix的輕量級替代方案,專為Java 8和函數(shù)式編程設計。
首先添加依賴:
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
然后在application.yml中配置熔斷器參數(shù):
resilience4j:
circuitbreaker:
instances:
orderService:
registerHealthIndicator: true
slidingWindowSize: 10
minimumNumberOfCalls: 5
permittedNumberOfCallsInHalfOpenState: 3
automaticTransitionFromOpenToHalfOpenEnabled: true
waitDurationInOpenState: 5s
failureRateThreshold: 50
eventConsumerBufferSize: 10
使用熔斷器的示例代碼:
@Service
public class OrderService {
private final PaymentServiceClient paymentServiceClient;
public OrderService(PaymentServiceClient paymentServiceClient) {
this.paymentServiceClient = paymentServiceClient;
}
@CircuitBreaker(name = "orderService", fallbackMethod = "processOrderFallback")
public OrderResponse processOrder(OrderRequest orderRequest) {
// 正常的訂單處理邏輯,包括調用支付服務
PaymentResponse paymentResponse = paymentServiceClient.processPayment(orderRequest.getPaymentDetails());
return new OrderResponse(orderRequest.getOrderId(), "PROCESSED", paymentResponse.getTransactionId());
}
// 降級方法,在熔斷器觸發(fā)時執(zhí)行
public OrderResponse processOrderFallback(OrderRequest orderRequest, Exception e) {
log.error("Circuit breaker triggered for order: {}. Error: {}", orderRequest.getOrderId(), e.getMessage());
// 返回降級響應,可能是從本地緩存獲取,或使用默認值
return new OrderResponse(orderRequest.getOrderId(), "PENDING", null);
}
}
最佳實踐
- 適當?shù)拇翱诖笮?/strong>:設置合理的
slidingWindowSize,太小可能導致熔斷器過于敏感,太大則反應遲鈍。 - 合理的閾值:根據業(yè)務需求設置
failureRateThreshold,一般建議在50%-60%之間。 - 監(jiān)控熔斷器狀態(tài):集成Spring Boot Actuator監(jiān)控熔斷器狀態(tài):
management:
endpoints:
web:
exposure:
include: health,circuitbreakers
health:
circuitbreakers:
enabled: true
- 細粒度熔斷:為不同的服務依賴配置不同的熔斷器實例,避免一個服務故障影響多個業(yè)務流程。
- 測試熔斷行為:通過混沌測試驗證熔斷器在故障情況下的行為是否符合預期。
2. 限流技術(Rate Limiting)
基本原理
限流用于控制系統(tǒng)的請求處理速率,防止系統(tǒng)過載。常見的限流算法包括:
- 令牌桶:以固定速率向桶中添加令牌,請求需要消耗令牌才能被處理。
- 漏桶:請求以固定速率處理,超出部分排隊或拒絕。
- 計數(shù)器:在固定時間窗口內限制請求數(shù)量。
SpringBoot實現(xiàn)與集成
在SpringBoot中,我們可以使用Bucket4j實現(xiàn)API限流,這是一個基于令牌桶算法的Java限流庫。
添加依賴:
<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<artifactId>bucket4j-core</artifactId>
<version>4.10.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
配置緩存和限流:
@Configuration
public class RateLimitingConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("rateLimit");
cacheManager.setCaffeine(Caffeine.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS)
.maximumSize(1000));
return cacheManager;
}
@Bean
public Bucket4jCacheConfiguration bucket4jCacheConfiguration() {
return new Bucket4jCacheConfiguration(cacheManager(), "rateLimit");
}
}
實現(xiàn)限流攔截器:
@Component
public class RateLimitingInterceptor implements HandlerInterceptor {
private final Cache<String, Bucket> cache;
public RateLimitingInterceptor() {
this.cache = Caffeine.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS)
.maximumSize(1000)
.build();
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String apiKey = request.getHeader("X-API-KEY");
if (apiKey == null || apiKey.isEmpty()) {
response.sendError(HttpStatus.BAD_REQUEST.value(), "Missing API key");
return false;
}
Bucket bucket = cache.get(apiKey, key -> createNewBucket());
ConsumptionProbe probe = bucket.tryConsumeAndReturnRemaining(1);
if (probe.isConsumed()) {
response.addHeader("X-Rate-Limit-Remaining", String.valueOf(probe.getRemainingTokens()));
return true;
} else {
long waitForRefill = probe.getNanosToWaitForRefill() / 1_000_000_000;
response.addHeader("X-Rate-Limit-Retry-After-Seconds", String.valueOf(waitForRefill));
response.sendError(HttpStatus.TOO_MANY_REQUESTS.value(), "Rate limit exceeded");
return false;
}
}
private Bucket createNewBucket() {
BucketConfiguration config = Bucket4j.configurationBuilder()
.addLimit(Bandwidth.classic(100, Refill.intervally(100, Duration.ofMinutes(1))))
.addLimit(Bandwidth.classic(1000, Refill.intervally(1000, Duration.ofHours(1))))
.build();
return Bucket4j.builder().withConfiguration(config).build();
}
}
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private RateLimitingInterceptor rateLimitingInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(rateLimitingInterceptor)
.addPathPatterns("/api/**");
}
}
在Spring Cloud Gateway中實現(xiàn)限流:
spring:
cloud:
gateway:
routes:
- id: order-service
uri: lb://order-service
predicates:
- Path=/orders/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
redis-rate-limiter.requestedTokens: 1
key-resolver: "#{@userKeyResolver}"
@Configuration
public class GatewayConfig {
@Bean
public KeyResolver userKeyResolver() {
return exchange -> {
String userId = exchange.getRequest().getHeaders().getFirst("User-Id");
if (userId == null) {
userId = "anonymous";
}
return Mono.just(userId);
};
}
}
最佳實踐
- 分級限流:基于不同用戶類型或API重要性設置不同的限流閾值。
- 應用多級限流:例如,同時應用用戶級、IP級和全局級限流。
- 限流響應:在限流觸發(fā)時返回合適的HTTP狀態(tài)碼(通常是429)和明確的錯誤信息,包括重試建議。
- 監(jiān)控限流指標:收集限流指標,用于分析和調整限流策略。
- 優(yōu)雅降級:當達到限流閾值時,考慮提供降級服務而非完全拒絕。
3. 服務降級與容錯處理
基本原理
服務降級是一種在系統(tǒng)高負載或部分服務不可用時,通過提供有限但可接受的服務來維持系統(tǒng)整體可用性的策略。容錯處理則是指系統(tǒng)能夠檢測并處理錯誤,同時繼續(xù)正常運行的能力。
SpringBoot實現(xiàn)與集成
在SpringBoot中,服務降級可以通過多種方式實現(xiàn),包括與熔斷器結合、使用異步回退,以及實現(xiàn)超時控制。
使用Resilience4j的Fallback實現(xiàn)服務降級:
@Service
public class ProductService {
private final ProductRepository productRepository;
private final ProductCacheService productCacheService;
@Autowired
public ProductService(ProductRepository productRepository, ProductCacheService productCacheService) {
this.productRepository = productRepository;
this.productCacheService = productCacheService;
}
@CircuitBreaker(name = "productService", fallbackMethod = "getProductDetailsFallback")
@Bulkhead(name = "productService", fallbackMethod = "getProductDetailsFallback")
@TimeLimiter(name = "productService", fallbackMethod = "getProductDetailsFallback")
public CompletableFuture<ProductDetails> getProductDetails(String productId) {
return CompletableFuture.supplyAsync(() -> {
// 正常的產品詳情獲取邏輯
Product product = productRepository.findById(productId)
.orElseThrow(() -> new ProductNotFoundException(productId));
// 獲取實時庫存和價格信息
InventoryInfo inventory = inventoryService.getInventory(productId);
PricingInfo pricing = pricingService.getCurrentPrice(productId);
return new ProductDetails(product, inventory, pricing);
});
}
// 降級方法,提供基本產品信息和緩存的庫存和價格
public CompletableFuture<ProductDetails> getProductDetailsFallback(String productId, Exception e) {
log.warn("Fallback for product {}. Reason: {}", productId, e.getMessage());
return CompletableFuture.supplyAsync(() -> {
// 從緩存獲取基本產品信息
Product product = productCacheService.getProductFromCache(productId)
.orElse(new Product(productId, "Unknown Product", "No details available"));
// 使用默認的庫存和價格信息
InventoryInfo inventory = new InventoryInfo(productId, 0, false);
PricingInfo pricing = new PricingInfo(productId, 0.0, false);
return new ProductDetails(product, inventory, pricing, true);
});
}
}
配置超時和服務隔離:
resilience4j:
timelimiter:
instances:
productService:
timeoutDuration: 2s
cancelRunningFuture: true
bulkhead:
instances:
productService:
maxConcurrentCalls: 20
maxWaitDuration: 500ms
實現(xiàn)優(yōu)雅降級策略的過濾器:
@Component
public class GracefulDegradationFilter extends OncePerRequestFilter {
private final HealthCheckService healthCheckService;
@Autowired
public GracefulDegradationFilter(HealthCheckService healthCheckService) {
this.healthCheckService = healthCheckService;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String path = request.getRequestURI();
// 檢查系統(tǒng)健康狀態(tài)
SystemHealth health = healthCheckService.getCurrentHealth();
if (health.isHighLoad() && isNonCriticalPath(path)) {
// 在高負載下降級非關鍵路徑請求
sendDegradedResponse(response, "Service temporarily operating at reduced capacity");
return;
} else if (health.isInMaintenance() && !isAdminPath(path)) {
// 在維護模式下只允許管理請求
sendMaintenanceResponse(response);
return;
} else if (health.hasFailedDependencies() && dependsOnFailedServices(path, health.getFailedServices())) {
// 如果請求依賴的服務不可用,返回降級響應
sendDependencyFailureResponse(response, health.getFailedServices());
return;
}
// 正常處理請求
filterChain.doFilter(request, response);
}
private boolean isNonCriticalPath(String path) {
// 判斷請求是否是非關鍵路徑
return path.startsWith("/api/recommendations") ||
path.startsWith("/api/analytics") ||
path.startsWith("/api/marketing");
}
private boolean isAdminPath(String path) {
return path.startsWith("/admin") || path.startsWith("/management");
}
private boolean dependsOnFailedServices(String path, List<String> failedServices) {
// 檢查請求是否依賴失敗的服務
Map<String, List<String>> serviceDependencies = new HashMap<>();
serviceDependencies.put("/api/orders", Arrays.asList("payment-service", "inventory-service"));
serviceDependencies.put("/api/payments", Arrays.asList("payment-service"));
// ... 其他路徑與服務的依賴關系
String matchingPath = findMatchingPath(path, serviceDependencies.keySet());
if (matchingPath != null) {
List<String> dependencies = serviceDependencies.get(matchingPath);
return dependencies.stream().anyMatch(failedServices::contains);
}
return false;
}
private String findMatchingPath(String requestPath, Set<String> configuredPaths) {
// 查找請求路徑匹配的配置路徑
return configuredPaths.stream()
.filter(requestPath::startsWith)
.findFirst()
.orElse(null);
}
private void sendDegradedResponse(HttpServletResponse response, String message) throws IOException {
response.setStatus(HttpStatus.SERVICE_UNAVAILABLE.value());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
Map<String, Object> responseBody = new HashMap<>();
responseBody.put("status", "degraded");
responseBody.put("message", message);
responseBody.put("retry_after", 30); // 建議30秒后重試
response.getWriter().write(new ObjectMapper().writeValueAsString(responseBody));
}
// 其他響應處理方法...
}
最佳實踐
- 分級降級策略:針對不同的故障場景和服務重要性制定分級降級策略。
- 靜態(tài)降級:預先準備好靜態(tài)資源或緩存數(shù)據,在服務不可用時使用。
- 功能降級:暫時關閉非核心功能,保證核心業(yè)務正常。
- 特定用戶群體降級:在高負載情況下,優(yōu)先保證VIP用戶的體驗。
- 服務隔離:使用Bulkhead模式隔離不同服務的資源,防止一個服務的問題影響其他服務。
- 超時控制:設置合理的超時時間,防止長時間等待影響用戶體驗。
4. 重試機制(Retry)
基本原理
重試機制用于處理暫時性故障,通過自動重新嘗試失敗的操作來提高系統(tǒng)的彈性。對于網絡抖動、數(shù)據庫臨時不可用等場景尤其有效。
SpringBoot實現(xiàn)與集成
SpringBoot中可以使用Spring Retry庫實現(xiàn)重試功能。
添加依賴:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
啟用重試功能:
@SpringBootApplication
@EnableRetry
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
使用聲明式重試:
@Service
public class RemoteServiceClient {
private final RestTemplate restTemplate;
@Autowired
public RemoteServiceClient(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Retryable(
value = {ResourceAccessException.class, HttpServerErrorException.class},
maxAttempts = 3,
backoff = @Backoff(delay = 1000, multiplier = 2)
)
public ResponseEntity<OrderData> getOrderDetails(String orderId) {
log.info("Attempting to fetch order details for {}", orderId);
return restTemplate.getForEntity("/api/orders/" + orderId, OrderData.class);
}
@Recover
public ResponseEntity<OrderData> recoverGetOrderDetails(Exception e, String orderId) {
log.error("All retries failed for order {}. Last error: {}", orderId, e.getMessage());
// 返回緩存數(shù)據或默認響應
return ResponseEntity.ok(new OrderData(orderId, "UNKNOWN", new Date(), Collections.emptyList()));
}
}
使用編程式重試:
@Service
public class PaymentService {
private final RetryTemplate retryTemplate;
@Autowired
public PaymentService(RetryTemplate retryTemplate) {
this.retryTemplate = retryTemplate;
}
public PaymentResult processPayment(PaymentRequest paymentRequest) {
return retryTemplate.execute(context -> {
// 獲取當前重試次數(shù)
int retryCount = context.getRetryCount();
log.info("Processing payment attempt {} for order {}",
retryCount + 1, paymentRequest.getOrderId());
try {
// 執(zhí)行支付處理
return paymentGateway.submitPayment(paymentRequest);
} catch (PaymentGatewayException e) {
// 分析異常并決定是否重試
if (e.isRetryable()) {
log.warn("Retryable payment error: {}. Will retry.", e.getMessage());
throw e; // 拋出異常以觸發(fā)重試
} else {
log.error("Non-retryable payment error: {}", e.getMessage());
throw new NonRetryableException("Payment failed with non-retryable error", e);
}
}
}, context -> {
// 恢復策略
log.error("All payment retries failed for order {}", paymentRequest.getOrderId());
// 返回失敗結果并記錄需要后續(xù)處理
return PaymentResult.failed(paymentRequest.getOrderId(), "Maximum retries exceeded");
});
}
}
@Configuration
public class RetryConfig {
@Bean
public RetryTemplate retryTemplate() {
RetryTemplate retryTemplate = new RetryTemplate();
// 設置重試策略
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(3);
// 設置退避策略
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(1000); // 1秒
backOffPolicy.setMultiplier(2.0); // 每次失敗后等待時間翻倍
backOffPolicy.setMaxInterval(10000); // 最長等待10秒
retryTemplate.setRetryPolicy(retryPolicy);
retryTemplate.setBackOffPolicy(backOffPolicy);
return retryTemplate;
}
}
結合Resilience4j的重試功能:
resilience4j.retry:
instances:
paymentService:
maxRetryAttempts: 3
waitDuration: 1s
enableExponentialBackoff: true
exponentialBackoffMultiplier: 2
retryExceptions:
- org.springframework.web.client.ResourceAccessException
- com.example.service.exception.TemporaryServiceException
@Service
public class PaymentServiceWithResilience4j {
private final PaymentGateway paymentGateway;
@Autowired
public PaymentServiceWithResilience4j(PaymentGateway paymentGateway) {
this.paymentGateway = paymentGateway;
}
@Retry(name = "paymentService", fallbackMethod = "processPaymentFallback")
public PaymentResult processPayment(PaymentRequest request) {
return paymentGateway.submitPayment(request);
}
public PaymentResult processPaymentFallback(PaymentRequest request, Exception e) {
log.error("Payment processing failed after retries for order: {}", request.getOrderId());
return PaymentResult.failed(request.getOrderId(), "Payment processing temporarily unavailable");
}
}
最佳實踐
- 區(qū)分暫時性和永久性故障:只對暫時性故障進行重試,對永久性故障立即失敗。
- 指數(shù)退避:使用指數(shù)退避策略,避免重試風暴。
- 合理的重試次數(shù):設置適當?shù)淖畲笾卦嚧螖?shù),通常3-5次。
- 重試后監(jiān)控:記錄重試次數(shù)和結果,幫助識別問題服務。
- 冪等操作:確保被重試的操作是冪等的,以避免重復處理導致的問題。
- 設置超時:每次重試都應該有合理的超時時間。
- 與熔斷器結合:將重試機制與熔斷器結合使用,當故障持續(xù)存在時快速失敗。
5. 健康檢查與監(jiān)控(Health Checks and Monitoring)
基本原理
健康檢查和監(jiān)控是保障服務可用性的基礎設施,用于實時了解系統(tǒng)狀態(tài),及早發(fā)現(xiàn)并解決問題。通過系統(tǒng)指標收集、健康狀態(tài)檢查和警報機制,可以提前預防或快速解決服務故障。
SpringBoot實現(xiàn)與集成
SpringBoot Actuator提供了豐富的監(jiān)控和管理功能,可以輕松集成到應用中。
添加依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
配置Actuator端點:
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus,loggers,env
endpoint:
health:
show-details: always
group:
readiness:
include: db,redis,rabbit,diskSpace
health:
circuitbreakers:
enabled: true
ratelimiters:
enabled: true
metrics:
export:
prometheus:
enabled: true
enable:
jvm: true
system: true
process: true
http: true
自定義健康檢查器:
@Component
public class ExternalServiceHealthIndicator implements HealthIndicator {
private final RestTemplate restTemplate;
@Autowired
public ExternalServiceHealthIndicator(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public Health health() {
try {
// 檢查外部服務健康狀態(tài)
ResponseEntity<Map> response = restTemplate.getForEntity("https://api.external-service.com/health", Map.class);
if (response.getStatusCode().is2xxSuccessful()) {
return Health.up()
.withDetail("status", response.getBody().get("status"))
.withDetail("version", response.getBody().get("version"))
.build();
} else {
return Health.down()
.withDetail("statusCode", response.getStatusCodeValue())
.withDetail("reason", "Unexpected status code")
.build();
}
} catch (Exception e) {
return Health.down()
.withDetail("error", e.getMessage())
.build();
}
}
}
配置應用就緒探針和活性探針:
@Configuration
public class HealthCheckConfig {
@Bean
public HealthContributorRegistry healthContributorRegistry(
ApplicationAvailabilityBean availabilityBean) {
HealthContributorRegistry registry = new DefaultHealthContributorRegistry();
// 添加應用啟動完成的就緒檢查
registry.registerContributor("readiness", new ApplicationAvailabilityHealthIndicator(
availabilityBean, ApplicationAvailabilityBean.LivenessState.CORRECT));
// 添加應用正在運行的活性檢查
registry.registerContributor("liveness", new ApplicationAvailabilityHealthIndicator(
availabilityBean, ApplicationAvailabilityBean.ReadinessState.ACCEPTING_TRAFFIC));
return registry;
}
}
自定義指標收集:
@Component
public class OrderMetrics {
private final MeterRegistry meterRegistry;
private final Counter orderCounter;
private final DistributionSummary orderAmountSummary;
private final Timer orderProcessingTimer;
public OrderMetrics(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
this.orderCounter = Counter.builder("orders.created")
.description("Number of orders created")
.tag("application", "order-service")
.register(meterRegistry);
this.orderAmountSummary = DistributionSummary.builder("orders.amount")
.description("Order amount distribution")
.tag("application", "order-service")
.publishPercentiles(0.5, 0.95, 0.99)
.register(meterRegistry);
this.orderProcessingTimer = Timer.builder("orders.processing.time")
.description("Order processing time")
.tag("application", "order-service")
.publishPercentiles(0.5, 0.95, 0.99)
.register(meterRegistry);
}
public void recordOrderCreated(String orderType) {
orderCounter.increment();
meterRegistry.counter("orders.created.by.type", "type", orderType).increment();
}
public void recordOrderAmount(double amount) {
orderAmountSummary.record(amount);
}
public Timer.Sample startOrderProcessing() {
return Timer.start(meterRegistry);
}
public void endOrderProcessing(Timer.Sample sample) {
sample.stop(orderProcessingTimer);
}
}
@Service
public class OrderServiceWithMetrics {
private final OrderRepository orderRepository;
private final OrderMetrics orderMetrics;
@Autowired
public OrderServiceWithMetrics(OrderRepository orderRepository, OrderMetrics orderMetrics) {
this.orderRepository = orderRepository;
this.orderMetrics = orderMetrics;
}
public Order createOrder(OrderRequest request) {
Timer.Sample timer = orderMetrics.startOrderProcessing();
try {
Order order = new Order();
// 處理訂單
order.setItems(request.getItems());
order.setTotalAmount(calculateTotalAmount(request.getItems()));
order.setType(request.getType());
Order savedOrder = orderRepository.save(order);
// 記錄指標
orderMetrics.recordOrderCreated(order.getType());
orderMetrics.recordOrderAmount(order.getTotalAmount());
return savedOrder;
} finally {
orderMetrics.endOrderProcessing(timer);
}
}
private double calculateTotalAmount(List<OrderItem> items) {
// 計算總金額
return items.stream()
.mapToDouble(item -> item.getPrice() * item.getQuantity())
.sum();
}
}
集成Grafana和Prometheus監(jiān)控:
# docker-compose.yml
version: '3.8'
services:
app:
image: my-spring-boot-app:latest
ports:
- "8080:8080"
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana:latest
depends_on:
- prometheus
ports:
- "3000:3000"
volumes:
- grafana-storage:/var/lib/grafana
volumes:
grafana-storage:
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'spring-boot-app'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['app:8080']
最佳實踐
- 多層次健康檢查:實現(xiàn)淺層和深層健康檢查,前者快速響應,后者全面檢查。
- 關鍵業(yè)務指標監(jiān)控:監(jiān)控關鍵業(yè)務指標,如訂單數(shù)量、轉化率等。
- 系統(tǒng)資源監(jiān)控:監(jiān)控CPU、內存、磁盤、網絡等系統(tǒng)資源。
- 設置合理的警報閾值:基于業(yè)務重要性和系統(tǒng)特性設置警報閾值。
- 關聯(lián)分析:將不同服務的指標關聯(lián)起來,便于問題根因分析。
- 日志與指標結合:將日志和指標結合起來,提供更完整的系統(tǒng)視圖。
- 預測性監(jiān)控:使用趨勢分析預測潛在問題,如磁盤空間預測用盡時間。
總結
本文介紹了SpringBoot中5種核心的服務可用性保障技術:熔斷器模式、限流技術、服務降級與容錯處理、重試機制以及健康檢查與監(jiān)控。這些技術不是孤立的,而是相互配合、協(xié)同工作,共同構建起應用的防御體系。
以上就是SpringBoot中5種服務可用性保障技術分享的詳細內容,更多關于SpringBoot服務可用性保障技術的資料請關注腳本之家其它相關文章!
相關文章
SpringBoot事件發(fā)布與監(jiān)聽超詳細講解
今天去官網查看spring boot資料時,在特性中看見了系統(tǒng)的事件及監(jiān)聽章節(jié),所以下面這篇文章主要給大家介紹了關于SpringBoot事件發(fā)布和監(jiān)聽的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-11-11
Java SE使用數(shù)組實現(xiàn)高速數(shù)字轉換功能
隨著大數(shù)據時代的到來,數(shù)字轉換功能變得越來越重要,在Java開發(fā)中,數(shù)字轉換功能也是經常用到的,下面我們就來學習一下如何使用Java SE數(shù)組實現(xiàn)高速的數(shù)字轉換功能吧2023-11-11
Java通過notify和wait實現(xiàn)線程間的通信功能
在軟件開發(fā)中,線程是實現(xiàn)并發(fā)執(zhí)行的重要手段,然而,線程之間的協(xié)作與通信卻是開發(fā)者必須重點考慮的挑戰(zhàn)之一,Java作為一種廣泛應用于多線程編程的語言,本文將深入探討Java中通過notify和wait實現(xiàn)線程間通信的機制,需要的朋友可以參考下2024-06-06
基于Java創(chuàng)建XML(無中文亂碼)過程解析
這篇文章主要介紹了基于Java創(chuàng)建XML(無中文亂碼)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-10-10
SpringBoot使用Thymeleaf自定義標簽的實例代碼
這篇文章主要介紹了SpringBoot使用Thymeleaf自定義標簽的實例代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09

