手把手教你写 httpclient 框架(九)- 企业级应用实战

前言

在前面的文章中,我们已经通过三个基础案例展示了 Atlas HTTP Client 框架的应用。但在真实的企业级环境中,我们往往面临更复杂的挑战:多环境部署、安全合规、性能监控、故障排查等。本文将通过几个企业级应用场景,展示如何在生产环境中使用我们的框架。

本文将涵盖以下企业级应用场景:

  1. 金融支付系统:高安全性、强一致性要求
  2. 电商促销系统:高并发、秒杀场景
  3. 物联网数据采集:海量设备、实时数据处理
  4. 企业内部API网关:统一接入、权限控制

每个场景都会包含完整的解决方案、最佳实践和生产环境的考虑因素。


场景一:金融支付系统

业务背景

金融支付系统对安全性、可靠性和一致性有极高要求。系统需要与银行、第三方支付平台、风控系统等多个外部服务进行交互,每笔交易都必须确保数据的完整性和安全性。

技术挑战

  1. 安全性:敏感数据加密、请求签名验证
  2. 可靠性:网络异常重试、幂等性保证
  3. 一致性:分布式事务、补偿机制
  4. 合规性:审计日志、操作追踪
  5. 性能:低延迟、高可用

解决方案

1. 项目结构

bash 复制代码
payment-system/
├── src/main/java/
│   ├── com/example/payment/
│   │   ├── PaymentApplication.java
│   │   ├── client/
│   │   │   ├── BankServiceClient.java
│   │   │   ├── ThirdPartyPaymentClient.java
│   │   │   └── RiskControlClient.java
│   │   ├── service/
│   │   │   ├── PaymentService.java
│   │   │   ├── TransactionService.java
│   │   │   └── AuditService.java
│   │   ├── security/
│   │   │   ├── EncryptionInterceptor.java
│   │   │   ├── SignatureInterceptor.java
│   │   │   └── SecurityUtils.java
│   │   ├── model/
│   │   │   ├── PaymentRequest.java
│   │   │   ├── TransactionRecord.java
│   │   │   └── AuditLog.java
│   │   └── config/
│   │       ├── SecurityConfig.java
│   │       └── PaymentConfig.java
│   └── resources/
│       ├── application.yml
│       └── application-prod.yml
└── pom.xml

2. 安全配置

yaml 复制代码
# application-prod.yml
server:
  port: 8443
  ssl:
    enabled: true
    key-store: classpath:keystore.p12
    key-store-password: ${SSL_KEYSTORE_PASSWORD}
    key-store-type: PKCS12

atlas:
  httpclient:
    enabled: true
    default-connect-timeout: 5000
    default-read-timeout: 10000
    logging-enabled: false  # 生产环境关闭详细日志
    metrics-enabled: true
    
    # 安全配置
    clients:
      bankService:
        base-url: https://bank-api.example.com
        connect-timeout: 3000
        read-timeout: 8000
        ssl-verification: true
      thirdPartyPayment:
        base-url: https://payment-gateway.example.com
        connect-timeout: 2000
        read-timeout: 6000
        ssl-verification: true
      riskControl:
        base-url: https://risk-api.internal.com
        connect-timeout: 1000
        read-timeout: 3000

# 支付系统配置
payment:
  security:
    encryption:
      algorithm: AES-256-GCM
      key-rotation-interval: 86400  # 24小时
    signature:
      algorithm: RSA-SHA256
      private-key: ${PAYMENT_PRIVATE_KEY}
      public-key: ${PAYMENT_PUBLIC_KEY}
  
  transaction:
    timeout: 30000  # 30秒超时
    max-retry: 3
    retry-delay: 1000
  
  audit:
    enabled: true
    retention-days: 2555  # 7年保存期
    sensitive-fields:
      - cardNumber
      - cvv
      - accountNumber

# 监控配置
management:
  endpoints:
    web:
      exposure:
        include: health,metrics,prometheus
  endpoint:
    health:
      show-details: always
  metrics:
    export:
      prometheus:
        enabled: true

3. 安全拦截器实现

java 复制代码
// EncryptionInterceptor.java
package com.example.payment.security;

import io.github.nemoob.httpclient.AbstractRequestInterceptor;
import io.github.nemoob.httpclient.RequestContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * 加密拦截器
 * 对敏感数据进行AES-GCM加密
 */
@Component
public class EncryptionInterceptor extends AbstractRequestInterceptor {
    
    @Autowired
    private SecurityUtils securityUtils;
    
    private static final String ENCRYPTION_HEADER = "X-Encrypted-Fields";
    private static final int GCM_IV_LENGTH = 12;
    private static final int GCM_TAG_LENGTH = 16;
    
    @Override
    public void preHandle(RequestContext context) throws Exception {
        Object body = context.getRequest().getBody();
        if (body == null) {
            return;
        }
        
        // 检查是否需要加密
        if (needsEncryption(context)) {
            String encryptedBody = encryptSensitiveData(body.toString());
            context.getRequest().setBody(encryptedBody);
            context.getRequest().getHeaders().put(ENCRYPTION_HEADER, "true");
        }
    }
    
    @Override
    public void postHandle(RequestContext context) throws Exception {
        // 解密响应数据
        if (context.getResponse() != null && isEncryptedResponse(context)) {
            String decryptedBody = decryptResponseData(context.getResponse().getBodyAsString());
            // 这里需要创建新的响应对象,简化处理
        }
    }
    
    /**
     * 加密敏感数据
     */
    private String encryptSensitiveData(String data) throws Exception {
        SecretKeySpec keySpec = securityUtils.getCurrentEncryptionKey();
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        
        // 生成随机IV
        byte[] iv = new byte[GCM_IV_LENGTH];
        new SecureRandom().nextBytes(iv);
        
        GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmSpec);
        
        byte[] encryptedData = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        
        // 组合IV和加密数据
        byte[] encryptedWithIv = new byte[iv.length + encryptedData.length];
        System.arraycopy(iv, 0, encryptedWithIv, 0, iv.length);
        System.arraycopy(encryptedData, 0, encryptedWithIv, iv.length, encryptedData.length);
        
        return Base64.getEncoder().encodeToString(encryptedWithIv);
    }
    
    /**
     * 解密响应数据
     */
    private String decryptResponseData(String encryptedData) throws Exception {
        byte[] encryptedWithIv = Base64.getDecoder().decode(encryptedData);
        
        // 分离IV和加密数据
        byte[] iv = new byte[GCM_IV_LENGTH];
        byte[] encrypted = new byte[encryptedWithIv.length - GCM_IV_LENGTH];
        
        System.arraycopy(encryptedWithIv, 0, iv, 0, GCM_IV_LENGTH);
        System.arraycopy(encryptedWithIv, GCM_IV_LENGTH, encrypted, 0, encrypted.length);
        
        SecretKeySpec keySpec = securityUtils.getCurrentEncryptionKey();
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        
        GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmSpec);
        
        byte[] decryptedData = cipher.doFinal(encrypted);
        return new String(decryptedData, StandardCharsets.UTF_8);
    }
    
    private boolean needsEncryption(RequestContext context) {
        // 检查请求是否包含敏感数据
        String url = context.getRequest().getUrl();
        return url.contains("/payment/") || url.contains("/transfer/");
    }
    
    private boolean isEncryptedResponse(RequestContext context) {
        return "true".equals(context.getResponse().getHeaders().get("X-Encrypted-Response"));
    }
}

// SignatureInterceptor.java
package com.example.payment.security;

import io.github.nemoob.httpclient.AbstractRequestInterceptor;
import io.github.nemoob.httpclient.RequestContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.Base64;
import java.util.Map;
import java.util.TreeMap;

/**
 * 签名拦截器
 * 对请求进行RSA-SHA256数字签名
 */
@Component
public class SignatureInterceptor extends AbstractRequestInterceptor {
    
    @Autowired
    private SecurityUtils securityUtils;
    
    private static final String SIGNATURE_HEADER = "X-Signature";
    private static final String TIMESTAMP_HEADER = "X-Timestamp";
    private static final String NONCE_HEADER = "X-Nonce";
    
    @Override
    public void preHandle(RequestContext context) throws Exception {
        // 生成时间戳和随机数
        long timestamp = System.currentTimeMillis();
        String nonce = securityUtils.generateNonce();
        
        // 添加到请求头
        context.getRequest().getHeaders().put(TIMESTAMP_HEADER, String.valueOf(timestamp));
        context.getRequest().getHeaders().put(NONCE_HEADER, nonce);
        
        // 生成签名
        String signature = generateSignature(context, timestamp, nonce);
        context.getRequest().getHeaders().put(SIGNATURE_HEADER, signature);
    }
    
    /**
     * 生成请求签名
     */
    private String generateSignature(RequestContext context, long timestamp, String nonce) throws Exception {
        // 构建签名字符串
        StringBuilder signatureData = new StringBuilder();
        
        // 添加HTTP方法
        signatureData.append(context.getRequest().getMethod().name()).append("\n");
        
        // 添加URL路径
        signatureData.append(context.getRequest().getUrl()).append("\n");
        
        // 添加时间戳和随机数
        signatureData.append(timestamp).append("\n");
        signatureData.append(nonce).append("\n");
        
        // 添加请求体哈希
        if (context.getRequest().getBody() != null) {
            String bodyHash = calculateSHA256(context.getRequest().getBody().toString());
            signatureData.append(bodyHash).append("\n");
        }
        
        // 添加关键请求头(按字典序排序)
        Map<String, String> sortedHeaders = new TreeMap<>();
        context.getRequest().getHeaders().forEach((key, value) -> {
            if (isSignableHeader(key)) {
                sortedHeaders.put(key.toLowerCase(), value);
            }
        });
        
        sortedHeaders.forEach((key, value) -> 
            signatureData.append(key).append(":").append(value).append("\n")
        );
        
        // 使用私钥签名
        PrivateKey privateKey = securityUtils.getPrivateKey();
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(signatureData.toString().getBytes(StandardCharsets.UTF_8));
        
        byte[] signatureBytes = signature.sign();
        return Base64.getEncoder().encodeToString(signatureBytes);
    }
    
    /**
     * 计算SHA256哈希
     */
    private String calculateSHA256(String data) throws Exception {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(hash);
    }
    
    /**
     * 判断是否是需要签名的请求头
     */
    private boolean isSignableHeader(String headerName) {
        String lowerName = headerName.toLowerCase();
        return lowerName.startsWith("x-") || 
               "content-type".equals(lowerName) || 
               "content-length".equals(lowerName);
    }
}

4. 支付服务客户端

java 复制代码
// BankServiceClient.java
package com.example.payment.client;

import com.example.payment.model.*;
import io.github.nemoob.httpclient.annotation.*;

import java.util.concurrent.CompletableFuture;

/**
 * 银行服务客户端
 * 与银行系统进行交互
 */
@HttpClient("${atlas.httpclient.clients.bankService.base-url}")
@Interceptor({
    EncryptionInterceptor.class,
    SignatureInterceptor.class,
    AuditInterceptor.class,
    IdempotentInterceptor.class
})
public interface BankServiceClient {
    
    /**
     * 账户余额查询
     */
    @GET("/api/v1/accounts/{accountId}/balance")
    @Async(timeout = 8000, retryCount = 2)
    CompletableFuture<BalanceResponse> getAccountBalance(
        @Path("accountId") String accountId,
        @Header("X-Request-Id") String requestId
    );
    
    /**
     * 转账交易
     */
    @POST("/api/v1/transfers")
    @Async(timeout = 10000, retryCount = 1)
    @MethodInterceptor(TransactionInterceptor.class)
    CompletableFuture<TransferResponse> transfer(
        @Body TransferRequest request,
        @Header("X-Request-Id") String requestId,
        @Header("X-Idempotency-Key") String idempotencyKey
    );
    
    /**
     * 交易状态查询
     */
    @GET("/api/v1/transfers/{transferId}/status")
    @Async(timeout = 5000)
    CompletableFuture<TransferStatusResponse> getTransferStatus(
        @Path("transferId") String transferId,
        @Header("X-Request-Id") String requestId
    );
    
    /**
     * 交易撤销
     */
    @POST("/api/v1/transfers/{transferId}/cancel")
    @Async(timeout = 8000)
    @MethodInterceptor(CompensationInterceptor.class)
    CompletableFuture<CancelResponse> cancelTransfer(
        @Path("transferId") String transferId,
        @Body CancelRequest request,
        @Header("X-Request-Id") String requestId
    );
}

// ThirdPartyPaymentClient.java
package com.example.payment.client;

import com.example.payment.model.*;
import io.github.nemoob.httpclient.annotation.*;

import java.util.concurrent.CompletableFuture;

/**
 * 第三方支付客户端
 * 与支付宝、微信等第三方支付平台交互
 */
@HttpClient("${atlas.httpclient.clients.thirdPartyPayment.base-url}")
@Interceptor({
    EncryptionInterceptor.class,
    SignatureInterceptor.class,
    RateLimitInterceptor.class
})
public interface ThirdPartyPaymentClient {
    
    /**
     * 创建支付订单
     */
    @POST("/api/v2/payments")
    @Async(timeout = 6000, retryCount = 2)
    CompletableFuture<PaymentOrderResponse> createPaymentOrder(
        @Body PaymentOrderRequest request,
        @Header("X-Request-Id") String requestId
    );
    
    /**
     * 查询支付状态
     */
    @GET("/api/v2/payments/{orderId}")
    @Async(timeout = 3000)
    CompletableFuture<PaymentStatusResponse> getPaymentStatus(
        @Path("orderId") String orderId,
        @Header("X-Request-Id") String requestId
    );
    
    /**
     * 申请退款
     */
    @POST("/api/v2/refunds")
    @Async(timeout = 8000, retryCount = 1)
    CompletableFuture<RefundResponse> requestRefund(
        @Body RefundRequest request,
        @Header("X-Request-Id") String requestId
    );
}

5. 核心业务服务

java 复制代码
// PaymentService.java
package com.example.payment.service;

import com.example.payment.client.*;
import com.example.payment.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

/**
 * 支付服务
 * 核心支付业务逻辑
 */
@Service
public class PaymentService {
    
    @Autowired
    private BankServiceClient bankServiceClient;
    
    @Autowired
    private ThirdPartyPaymentClient thirdPartyPaymentClient;
    
    @Autowired
    private RiskControlClient riskControlClient;
    
    @Autowired
    private TransactionService transactionService;
    
    @Autowired
    private AuditService auditService;
    
    /**
     * 处理支付请求
     */
    @Transactional
    public CompletableFuture<PaymentResult> processPayment(PaymentRequest request) {
        String requestId = generateRequestId();
        String idempotencyKey = generateIdempotencyKey(request);
        
        return CompletableFuture.supplyAsync(() -> {
            try {
                // 1. 记录审计日志
                auditService.logPaymentStart(request, requestId);
                
                // 2. 风险控制检查
                return riskControlClient.checkRisk(request, requestId)
                    .thenCompose(riskResult -> {
                        if (!riskResult.isPassed()) {
                            throw new PaymentException("Risk control failed: " + riskResult.getReason());
                        }
                        
                        // 3. 根据支付方式选择处理逻辑
                        if (PaymentMethod.BANK_TRANSFER.equals(request.getPaymentMethod())) {
                            return processBankTransfer(request, requestId, idempotencyKey);
                        } else {
                            return processThirdPartyPayment(request, requestId);
                        }
                    })
                    .thenApply(result -> {
                        // 4. 记录交易结果
                        transactionService.recordTransaction(request, result, requestId);
                        auditService.logPaymentComplete(request, result, requestId);
                        return result;
                    })
                    .exceptionally(throwable -> {
                        // 5. 异常处理
                        PaymentResult errorResult = PaymentResult.failed(throwable.getMessage());
                        auditService.logPaymentError(request, throwable, requestId);
                        return errorResult;
                    })
                    .join();
                    
            } catch (Exception e) {
                throw new RuntimeException("Payment processing failed", e);
            }
        });
    }
    
    /**
     * 处理银行转账
     */
    private CompletableFuture<PaymentResult> processBankTransfer(
            PaymentRequest request, String requestId, String idempotencyKey) {
        
        // 1. 检查账户余额
        return bankServiceClient.getAccountBalance(request.getFromAccount(), requestId)
            .thenCompose(balanceResponse -> {
                if (balanceResponse.getBalance().compareTo(request.getAmount()) < 0) {
                    throw new PaymentException("Insufficient balance");
                }
                
                // 2. 执行转账
                TransferRequest transferRequest = new TransferRequest(
                    request.getFromAccount(),
                    request.getToAccount(),
                    request.getAmount(),
                    request.getDescription()
                );
                
                return bankServiceClient.transfer(transferRequest, requestId, idempotencyKey);
            })
            .thenApply(transferResponse -> {
                if (transferResponse.isSuccess()) {
                    return PaymentResult.success(
                        transferResponse.getTransferId(),
                        request.getAmount(),
                        "Bank transfer completed"
                    );
                } else {
                    return PaymentResult.failed(transferResponse.getErrorMessage());
                }
            });
    }
    
    /**
     * 处理第三方支付
     */
    private CompletableFuture<PaymentResult> processThirdPartyPayment(
            PaymentRequest request, String requestId) {
        
        PaymentOrderRequest orderRequest = new PaymentOrderRequest(
            request.getAmount(),
            request.getCurrency(),
            request.getDescription(),
            request.getPaymentMethod(),
            request.getNotifyUrl()
        );
        
        return thirdPartyPaymentClient.createPaymentOrder(orderRequest, requestId)
            .thenApply(orderResponse -> {
                if (orderResponse.isSuccess()) {
                    return PaymentResult.success(
                        orderResponse.getOrderId(),
                        request.getAmount(),
                        "Payment order created"
                    );
                } else {
                    return PaymentResult.failed(orderResponse.getErrorMessage());
                }
            });
    }
    
    /**
     * 查询支付状态
     */
    public CompletableFuture<PaymentStatusResult> getPaymentStatus(String paymentId) {
        String requestId = generateRequestId();
        
        // 先查询银行系统
        return bankServiceClient.getTransferStatus(paymentId, requestId)
            .thenApply(bankStatus -> {
                if (bankStatus != null) {
                    return PaymentStatusResult.fromBankStatus(bankStatus);
                }
                return null;
            })
            .thenCompose(result -> {
                if (result != null) {
                    return CompletableFuture.completedFuture(result);
                }
                
                // 再查询第三方支付
                return thirdPartyPaymentClient.getPaymentStatus(paymentId, requestId)
                    .thenApply(PaymentStatusResult::fromThirdPartyStatus);
            });
    }
    
    /**
     * 生成请求ID
     */
    private String generateRequestId() {
        return "PAY-" + System.currentTimeMillis() + "-" + UUID.randomUUID().toString().substring(0, 8);
    }
    
    /**
     * 生成幂等性键
     */
    private String generateIdempotencyKey(PaymentRequest request) {
        return "IDM-" + request.hashCode() + "-" + System.currentTimeMillis();
    }
}

生产环境最佳实践

1. 安全措施

java 复制代码
// SecurityUtils.java
package com.example.payment.security;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.spec.SecretKeySpec;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class SecurityUtils {
    
    @Value("${payment.security.encryption.key}")
    private String encryptionKey;
    
    @Value("${payment.security.signature.private-key}")
    private String privateKeyString;
    
    private final SecureRandom secureRandom = new SecureRandom();
    private final ConcurrentHashMap<String, Long> nonceCache = new ConcurrentHashMap<>();
    
    /**
     * 获取当前加密密钥
     */
    public SecretKeySpec getCurrentEncryptionKey() {
        byte[] keyBytes = Base64.getDecoder().decode(encryptionKey);
        return new SecretKeySpec(keyBytes, "AES");
    }
    
    /**
     * 获取私钥
     */
    public PrivateKey getPrivateKey() throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(privateKeyString);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }
    
    /**
     * 生成随机数
     */
    public String generateNonce() {
        byte[] nonceBytes = new byte[16];
        secureRandom.nextBytes(nonceBytes);
        String nonce = Base64.getEncoder().encodeToString(nonceBytes);
        
        // 防重放攻击:记录nonce
        long timestamp = System.currentTimeMillis();
        nonceCache.put(nonce, timestamp);
        
        // 清理过期nonce(5分钟)
        cleanExpiredNonces(timestamp - 300000);
        
        return nonce;
    }
    
    /**
     * 验证nonce是否已使用
     */
    public boolean isNonceUsed(String nonce) {
        return nonceCache.containsKey(nonce);
    }
    
    /**
     * 清理过期nonce
     */
    private void cleanExpiredNonces(long expireTime) {
        nonceCache.entrySet().removeIf(entry -> entry.getValue() < expireTime);
    }
}

2. 监控和告警

java 复制代码
// PaymentMetrics.java
package com.example.payment.monitoring;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class PaymentMetrics {
    
    private final Counter paymentSuccessCounter;
    private final Counter paymentFailureCounter;
    private final Timer paymentProcessingTimer;
    private final Counter securityViolationCounter;
    
    @Autowired
    public PaymentMetrics(MeterRegistry meterRegistry) {
        this.paymentSuccessCounter = Counter.builder("payment.success")
            .description("Number of successful payments")
            .register(meterRegistry);
            
        this.paymentFailureCounter = Counter.builder("payment.failure")
            .description("Number of failed payments")
            .register(meterRegistry);
            
        this.paymentProcessingTimer = Timer.builder("payment.processing.time")
            .description("Payment processing time")
            .register(meterRegistry);
            
        this.securityViolationCounter = Counter.builder("security.violation")
            .description("Number of security violations")
            .register(meterRegistry);
    }
    
    public void recordPaymentSuccess() {
        paymentSuccessCounter.increment();
    }
    
    public void recordPaymentFailure() {
        paymentFailureCounter.increment();
    }
    
    public Timer.Sample startPaymentTimer() {
        return Timer.start();
    }
    
    public void recordPaymentTime(Timer.Sample sample) {
        sample.stop(paymentProcessingTimer);
    }
    
    public void recordSecurityViolation() {
        securityViolationCounter.increment();
    }
}

场景一总结

金融支付系统案例展示了:

  1. 多层安全防护:加密、签名、防重放攻击
  2. 可靠性保证:幂等性、重试机制、补偿事务
  3. 合规要求:审计日志、敏感数据保护
  4. 监控告警:实时监控、性能指标、安全告警
  5. 高可用设计:异步处理、故障转移、降级策略

关键要点

  • 敏感数据必须加密传输和存储
  • 所有操作都要有审计日志
  • 实现完善的幂等性机制
  • 建立多层安全防护体系
  • 设置实时监控和告警

场景二:电商促销系统

业务背景

电商促销系统需要在短时间内处理大量并发请求,特别是在秒杀、限时抢购等场景下。系统需要与商品服务、库存服务、用户服务、订单服务等多个微服务协作,确保在高并发情况下的数据一致性和系统稳定性。

技术挑战

  1. 高并发:秒杀场景下的瞬时高并发
  2. 库存一致性:防止超卖问题
  3. 系统稳定性:防止系统雪崩
  4. 用户体验:快速响应、公平性
  5. 数据一致性:分布式环境下的数据一致性

解决方案

1. 项目结构

bash 复制代码
promotion-system/
├── src/main/java/
│   ├── com/example/promotion/
│   │   ├── PromotionApplication.java
│   │   ├── client/
│   │   │   ├── ProductServiceClient.java
│   │   │   ├── InventoryServiceClient.java
│   │   │   ├── UserServiceClient.java
│   │   │   └── OrderServiceClient.java
│   │   ├── service/
│   │   │   ├── PromotionService.java
│   │   │   ├── SeckillService.java
│   │   │   └── CacheService.java
│   │   ├── interceptor/
│   │   │   ├── HighConcurrencyInterceptor.java
│   │   │   ├── CacheInterceptor.java
│   │   │   └── CircuitBreakerInterceptor.java
│   │   ├── model/
│   │   │   ├── PromotionRequest.java
│   │   │   ├── SeckillRequest.java
│   │   │   └── PromotionResult.java
│   │   └── config/
│   │       ├── PromotionConfig.java
│   │       └── CacheConfig.java
│   └── resources/
│       └── application.yml
└── pom.xml

2. 高并发配置

yaml 复制代码
# application.yml
server:
  port: 8080
  tomcat:
    threads:
      max: 2000
      min-spare: 200
    max-connections: 20000
    accept-count: 2000
    connection-timeout: 5000

atlas:
  httpclient:
    enabled: true
    default-connect-timeout: 500
    default-read-timeout: 2000
    logging-enabled: false
    metrics-enabled: true
    
    # 高并发优化配置
    clients:
      productService:
        base-url: http://product-service:8080
        connect-timeout: 300
        read-timeout: 1000
        async: true
      inventoryService:
        base-url: http://inventory-service:8080
        connect-timeout: 200
        read-timeout: 800
        async: true
      userService:
        base-url: http://user-service:8080
        connect-timeout: 400
        read-timeout: 1200
        async: true
      orderService:
        base-url: http://order-service:8080
        connect-timeout: 600
        read-timeout: 2000
        async: true

# 促销系统配置
promotion:
  seckill:
    max-concurrent-users: 10000
    queue-capacity: 50000
    processing-timeout: 5000
  
  cache:
    redis:
      host: redis-cluster.internal.com
      port: 6379
      timeout: 1000
      pool:
        max-active: 500
        max-idle: 100
        min-idle: 50
  
  circuit-breaker:
    failure-threshold: 50
    timeout: 10000
    reset-timeout: 30000

# 线程池配置
spring:
  task:
    execution:
      pool:
        core-size: 100
        max-size: 1000
        queue-capacity: 5000
        keep-alive: 60s
相关推荐
用户9446814013503 小时前
JUC CountDownLatch 源码详解
java
uhakadotcom3 小时前
分享近期学到的postgresql的几个实用的新特性!
后端·面试·github
CoovallyAIHub3 小时前
华为发布开源超节点架构,以开放战略叩响AI算力生态变局
算法·架构·github
七夜zippoe3 小时前
微服务配置中心高可用设计:从踩坑到落地的实战指南(一)
java·数据库·微服务
天天摸鱼的java工程师3 小时前
Java 设计模式(观察者模式)+ Redis:游戏成就系统(条件达成检测、奖励自动发放)
java·后端
忘了ʷºᵇₐ3 小时前
在hadoop中Job提交的流程
java·hadoop
编啊编程啊程3 小时前
Netty从0到1系列之RPC通信
java·spring boot·rpc·kafka·dubbo·nio
召摇3 小时前
Java Web开发从零开始:初学者完整学习指南
java·后端·面试
xinxinhenmeihao3 小时前
HTTP代理HTTP(S)、SOCKS5有哪些作用?
网络·网络协议·http