SpringBoot中5種服務(wù)可用性保障技術(shù)分享
1. 熔斷器模式(Circuit Breaker)
基本原理
熔斷器模式借鑒了電路熔斷器的概念,當(dāng)檢測(cè)到系統(tǒng)中某個(gè)服務(wù)或組件頻繁失敗時(shí),自動(dòng)"斷開"對(duì)該服務(wù)的調(diào)用,防止級(jí)聯(lián)故障,同時(shí)為故障服務(wù)提供恢復(fù)時(shí)間。熔斷器有三種狀態(tài):
- 關(guān)閉狀態(tài):正常執(zhí)行操作,同時(shí)監(jiān)控失敗率
- 開啟狀態(tài):拒絕訪問,直接返回錯(cuò)誤或執(zhí)行降級(jí)邏輯
- 半開狀態(tài):嘗試恢復(fù),允許有限的請(qǐng)求通過以測(cè)試服務(wù)是否恢復(fù)
SpringBoot實(shí)現(xiàn)與集成
在SpringBoot中,我們可以使用Resilience4j實(shí)現(xiàn)熔斷器模式,它是Hystrix的輕量級(jí)替代方案,專為Java 8和函數(shù)式編程設(shè)計(jì)。
首先添加依賴:
<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) { // 正常的訂單處理邏輯,包括調(diào)用支付服務(wù) PaymentResponse paymentResponse = paymentServiceClient.processPayment(orderRequest.getPaymentDetails()); return new OrderResponse(orderRequest.getOrderId(), "PROCESSED", paymentResponse.getTransactionId()); } // 降級(jí)方法,在熔斷器觸發(fā)時(shí)執(zhí)行 public OrderResponse processOrderFallback(OrderRequest orderRequest, Exception e) { log.error("Circuit breaker triggered for order: {}. Error: {}", orderRequest.getOrderId(), e.getMessage()); // 返回降級(jí)響應(yīng),可能是從本地緩存獲取,或使用默認(rèn)值 return new OrderResponse(orderRequest.getOrderId(), "PENDING", null); } }
最佳實(shí)踐
- 適當(dāng)?shù)拇翱诖笮?/strong>:設(shè)置合理的
slidingWindowSize
,太小可能導(dǎo)致熔斷器過于敏感,太大則反應(yīng)遲鈍。 - 合理的閾值:根據(jù)業(yè)務(wù)需求設(shè)置
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
- 細(xì)粒度熔斷:為不同的服務(wù)依賴配置不同的熔斷器實(shí)例,避免一個(gè)服務(wù)故障影響多個(gè)業(yè)務(wù)流程。
- 測(cè)試熔斷行為:通過混沌測(cè)試驗(yàn)證熔斷器在故障情況下的行為是否符合預(yù)期。
2. 限流技術(shù)(Rate Limiting)
基本原理
限流用于控制系統(tǒng)的請(qǐng)求處理速率,防止系統(tǒng)過載。常見的限流算法包括:
- 令牌桶:以固定速率向桶中添加令牌,請(qǐng)求需要消耗令牌才能被處理。
- 漏桶:請(qǐng)求以固定速率處理,超出部分排隊(duì)或拒絕。
- 計(jì)數(shù)器:在固定時(shí)間窗口內(nèi)限制請(qǐng)求數(shù)量。
SpringBoot實(shí)現(xiàn)與集成
在SpringBoot中,我們可以使用Bucket4j實(shí)現(xiàn)API限流,這是一個(gè)基于令牌桶算法的Java限流庫(kù)。
添加依賴:
<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"); } }
實(shí)現(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中實(shí)現(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); }; } }
最佳實(shí)踐
- 分級(jí)限流:基于不同用戶類型或API重要性設(shè)置不同的限流閾值。
- 應(yīng)用多級(jí)限流:例如,同時(shí)應(yīng)用用戶級(jí)、IP級(jí)和全局級(jí)限流。
- 限流響應(yīng):在限流觸發(fā)時(shí)返回合適的HTTP狀態(tài)碼(通常是429)和明確的錯(cuò)誤信息,包括重試建議。
- 監(jiān)控限流指標(biāo):收集限流指標(biāo),用于分析和調(diào)整限流策略。
- 優(yōu)雅降級(jí):當(dāng)達(dá)到限流閾值時(shí),考慮提供降級(jí)服務(wù)而非完全拒絕。
3. 服務(wù)降級(jí)與容錯(cuò)處理
基本原理
服務(wù)降級(jí)是一種在系統(tǒng)高負(fù)載或部分服務(wù)不可用時(shí),通過提供有限但可接受的服務(wù)來維持系統(tǒng)整體可用性的策略。容錯(cuò)處理則是指系統(tǒng)能夠檢測(cè)并處理錯(cuò)誤,同時(shí)繼續(xù)正常運(yùn)行的能力。
SpringBoot實(shí)現(xiàn)與集成
在SpringBoot中,服務(wù)降級(jí)可以通過多種方式實(shí)現(xiàn),包括與熔斷器結(jié)合、使用異步回退,以及實(shí)現(xiàn)超時(shí)控制。
使用Resilience4j的Fallback實(shí)現(xiàn)服務(wù)降級(jí):
@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(() -> { // 正常的產(chǎn)品詳情獲取邏輯 Product product = productRepository.findById(productId) .orElseThrow(() -> new ProductNotFoundException(productId)); // 獲取實(shí)時(shí)庫(kù)存和價(jià)格信息 InventoryInfo inventory = inventoryService.getInventory(productId); PricingInfo pricing = pricingService.getCurrentPrice(productId); return new ProductDetails(product, inventory, pricing); }); } // 降級(jí)方法,提供基本產(chǎn)品信息和緩存的庫(kù)存和價(jià)格 public CompletableFuture<ProductDetails> getProductDetailsFallback(String productId, Exception e) { log.warn("Fallback for product {}. Reason: {}", productId, e.getMessage()); return CompletableFuture.supplyAsync(() -> { // 從緩存獲取基本產(chǎn)品信息 Product product = productCacheService.getProductFromCache(productId) .orElse(new Product(productId, "Unknown Product", "No details available")); // 使用默認(rèn)的庫(kù)存和價(jià)格信息 InventoryInfo inventory = new InventoryInfo(productId, 0, false); PricingInfo pricing = new PricingInfo(productId, 0.0, false); return new ProductDetails(product, inventory, pricing, true); }); } }
配置超時(shí)和服務(wù)隔離:
resilience4j: timelimiter: instances: productService: timeoutDuration: 2s cancelRunningFuture: true bulkhead: instances: productService: maxConcurrentCalls: 20 maxWaitDuration: 500ms
實(shí)現(xiàn)優(yōu)雅降級(jí)策略的過濾器:
@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)) { // 在高負(fù)載下降級(jí)非關(guān)鍵路徑請(qǐng)求 sendDegradedResponse(response, "Service temporarily operating at reduced capacity"); return; } else if (health.isInMaintenance() && !isAdminPath(path)) { // 在維護(hù)模式下只允許管理請(qǐng)求 sendMaintenanceResponse(response); return; } else if (health.hasFailedDependencies() && dependsOnFailedServices(path, health.getFailedServices())) { // 如果請(qǐng)求依賴的服務(wù)不可用,返回降級(jí)響應(yīng) sendDependencyFailureResponse(response, health.getFailedServices()); return; } // 正常處理請(qǐng)求 filterChain.doFilter(request, response); } private boolean isNonCriticalPath(String path) { // 判斷請(qǐng)求是否是非關(guān)鍵路徑 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) { // 檢查請(qǐng)求是否依賴失敗的服務(wù) 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")); // ... 其他路徑與服務(wù)的依賴關(guān)系 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) { // 查找請(qǐng)求路徑匹配的配置路徑 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)); } // 其他響應(yīng)處理方法... }
最佳實(shí)踐
- 分級(jí)降級(jí)策略:針對(duì)不同的故障場(chǎng)景和服務(wù)重要性制定分級(jí)降級(jí)策略。
- 靜態(tài)降級(jí):預(yù)先準(zhǔn)備好靜態(tài)資源或緩存數(shù)據(jù),在服務(wù)不可用時(shí)使用。
- 功能降級(jí):暫時(shí)關(guān)閉非核心功能,保證核心業(yè)務(wù)正常。
- 特定用戶群體降級(jí):在高負(fù)載情況下,優(yōu)先保證VIP用戶的體驗(yàn)。
- 服務(wù)隔離:使用Bulkhead模式隔離不同服務(wù)的資源,防止一個(gè)服務(wù)的問題影響其他服務(wù)。
- 超時(shí)控制:設(shè)置合理的超時(shí)時(shí)間,防止長(zhǎng)時(shí)間等待影響用戶體驗(yàn)。
4. 重試機(jī)制(Retry)
基本原理
重試機(jī)制用于處理暫時(shí)性故障,通過自動(dòng)重新嘗試失敗的操作來提高系統(tǒng)的彈性。對(duì)于網(wǎng)絡(luò)抖動(dòng)、數(shù)據(jù)庫(kù)臨時(shí)不可用等場(chǎng)景尤其有效。
SpringBoot實(shí)現(xiàn)與集成
SpringBoot中可以使用Spring Retry庫(kù)實(shí)現(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ù)據(jù)或默認(rèn)響應(yīng) 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 -> { // 獲取當(dāng)前重試次數(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 -> { // 恢復(fù)策略 log.error("All payment retries failed for order {}", paymentRequest.getOrderId()); // 返回失敗結(jié)果并記錄需要后續(xù)處理 return PaymentResult.failed(paymentRequest.getOrderId(), "Maximum retries exceeded"); }); } } @Configuration public class RetryConfig { @Bean public RetryTemplate retryTemplate() { RetryTemplate retryTemplate = new RetryTemplate(); // 設(shè)置重試策略 SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(); retryPolicy.setMaxAttempts(3); // 設(shè)置退避策略 ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy(); backOffPolicy.setInitialInterval(1000); // 1秒 backOffPolicy.setMultiplier(2.0); // 每次失敗后等待時(shí)間翻倍 backOffPolicy.setMaxInterval(10000); // 最長(zhǎng)等待10秒 retryTemplate.setRetryPolicy(retryPolicy); retryTemplate.setBackOffPolicy(backOffPolicy); return retryTemplate; } }
結(jié)合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"); } }
最佳實(shí)踐
- 區(qū)分暫時(shí)性和永久性故障:只對(duì)暫時(shí)性故障進(jìn)行重試,對(duì)永久性故障立即失敗。
- 指數(shù)退避:使用指數(shù)退避策略,避免重試風(fēng)暴。
- 合理的重試次數(shù):設(shè)置適當(dāng)?shù)淖畲笾卦嚧螖?shù),通常3-5次。
- 重試后監(jiān)控:記錄重試次數(shù)和結(jié)果,幫助識(shí)別問題服務(wù)。
- 冪等操作:確保被重試的操作是冪等的,以避免重復(fù)處理導(dǎo)致的問題。
- 設(shè)置超時(shí):每次重試都應(yīng)該有合理的超時(shí)時(shí)間。
- 與熔斷器結(jié)合:將重試機(jī)制與熔斷器結(jié)合使用,當(dāng)故障持續(xù)存在時(shí)快速失敗。
5. 健康檢查與監(jiān)控(Health Checks and Monitoring)
基本原理
健康檢查和監(jiān)控是保障服務(wù)可用性的基礎(chǔ)設(shè)施,用于實(shí)時(shí)了解系統(tǒng)狀態(tài),及早發(fā)現(xiàn)并解決問題。通過系統(tǒng)指標(biāo)收集、健康狀態(tài)檢查和警報(bào)機(jī)制,可以提前預(yù)防或快速解決服務(wù)故障。
SpringBoot實(shí)現(xiàn)與集成
SpringBoot Actuator提供了豐富的監(jiān)控和管理功能,可以輕松集成到應(yīng)用中。
添加依賴:
<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端點(diǎn):
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 { // 檢查外部服務(wù)健康狀態(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(); } } }
配置應(yīng)用就緒探針和活性探針:
@Configuration public class HealthCheckConfig { @Bean public HealthContributorRegistry healthContributorRegistry( ApplicationAvailabilityBean availabilityBean) { HealthContributorRegistry registry = new DefaultHealthContributorRegistry(); // 添加應(yīng)用啟動(dòng)完成的就緒檢查 registry.registerContributor("readiness", new ApplicationAvailabilityHealthIndicator( availabilityBean, ApplicationAvailabilityBean.LivenessState.CORRECT)); // 添加應(yīng)用正在運(yùn)行的活性檢查 registry.registerContributor("liveness", new ApplicationAvailabilityHealthIndicator( availabilityBean, ApplicationAvailabilityBean.ReadinessState.ACCEPTING_TRAFFIC)); return registry; } }
自定義指標(biāo)收集:
@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); // 記錄指標(biāo) orderMetrics.recordOrderCreated(order.getType()); orderMetrics.recordOrderAmount(order.getTotalAmount()); return savedOrder; } finally { orderMetrics.endOrderProcessing(timer); } } private double calculateTotalAmount(List<OrderItem> items) { // 計(jì)算總金額 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']
最佳實(shí)踐
- 多層次健康檢查:實(shí)現(xiàn)淺層和深層健康檢查,前者快速響應(yīng),后者全面檢查。
- 關(guān)鍵業(yè)務(wù)指標(biāo)監(jiān)控:監(jiān)控關(guān)鍵業(yè)務(wù)指標(biāo),如訂單數(shù)量、轉(zhuǎn)化率等。
- 系統(tǒng)資源監(jiān)控:監(jiān)控CPU、內(nèi)存、磁盤、網(wǎng)絡(luò)等系統(tǒng)資源。
- 設(shè)置合理的警報(bào)閾值:基于業(yè)務(wù)重要性和系統(tǒng)特性設(shè)置警報(bào)閾值。
- 關(guān)聯(lián)分析:將不同服務(wù)的指標(biāo)關(guān)聯(lián)起來,便于問題根因分析。
- 日志與指標(biāo)結(jié)合:將日志和指標(biāo)結(jié)合起來,提供更完整的系統(tǒng)視圖。
- 預(yù)測(cè)性監(jiān)控:使用趨勢(shì)分析預(yù)測(cè)潛在問題,如磁盤空間預(yù)測(cè)用盡時(shí)間。
總結(jié)
本文介紹了SpringBoot中5種核心的服務(wù)可用性保障技術(shù):熔斷器模式、限流技術(shù)、服務(wù)降級(jí)與容錯(cuò)處理、重試機(jī)制以及健康檢查與監(jiān)控。這些技術(shù)不是孤立的,而是相互配合、協(xié)同工作,共同構(gòu)建起應(yīng)用的防御體系。
以上就是SpringBoot中5種服務(wù)可用性保障技術(shù)分享的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot服務(wù)可用性保障技術(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java實(shí)現(xiàn)根據(jù)ip地址獲取地理位置
本文給大家匯總介紹了2種分別使用新浪和淘寶接口,實(shí)現(xiàn)根據(jù)IP地址獲取詳細(xì)的地理位置的代碼,非常的實(shí)用,有需要的小伙伴可以參考下。2016-03-03SpringBoot事件發(fā)布與監(jiān)聽超詳細(xì)講解
今天去官網(wǎng)查看spring boot資料時(shí),在特性中看見了系統(tǒng)的事件及監(jiān)聽章節(jié),所以下面這篇文章主要給大家介紹了關(guān)于SpringBoot事件發(fā)布和監(jiān)聽的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-11-11Java SE使用數(shù)組實(shí)現(xiàn)高速數(shù)字轉(zhuǎn)換功能
隨著大數(shù)據(jù)時(shí)代的到來,數(shù)字轉(zhuǎn)換功能變得越來越重要,在Java開發(fā)中,數(shù)字轉(zhuǎn)換功能也是經(jīng)常用到的,下面我們就來學(xué)習(xí)一下如何使用Java SE數(shù)組實(shí)現(xiàn)高速的數(shù)字轉(zhuǎn)換功能吧2023-11-11Java通過notify和wait實(shí)現(xiàn)線程間的通信功能
在軟件開發(fā)中,線程是實(shí)現(xiàn)并發(fā)執(zhí)行的重要手段,然而,線程之間的協(xié)作與通信卻是開發(fā)者必須重點(diǎn)考慮的挑戰(zhàn)之一,Java作為一種廣泛應(yīng)用于多線程編程的語言,本文將深入探討Java中通過notify和wait實(shí)現(xiàn)線程間通信的機(jī)制,需要的朋友可以參考下2024-06-06基于Java創(chuàng)建XML(無中文亂碼)過程解析
這篇文章主要介紹了基于Java創(chuàng)建XML(無中文亂碼)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(3)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你2021-07-07SpringBoot使用Thymeleaf自定義標(biāo)簽的實(shí)例代碼
這篇文章主要介紹了SpringBoot使用Thymeleaf自定義標(biāo)簽的實(shí)例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09