程序员必备的十大技能(进阶版)之架构规划与项目统筹(二)

简介: 教程来源 http://oieaw.cn/ 本文系统阐述微服务架构设计核心:基于限界上下文划分订单、库存、支付等清晰边界;通过防腐层隔离外部依赖(如物流系统);遵循单一职责、数据自治等服务划分原则;并全面覆盖性能、可用性、安全等非功能性需求,集成SLI/SLO/SLA监控及超时、重试、熔断、舱壁等容错机制。

三、系统分解与边界划分

3.1 限界上下文(Bounded Context)

限界上下文定义:
  上下文 A: 订单上下文
    核心概念: Order, OrderItem, OrderStatus
    职责: 订单创建、修改、取消、查询
    事件: OrderCreated, OrderPaid, OrderCancelled
    数据: 订单表、订单明细表

  上下文 B: 库存上下文
    核心概念: Product, Inventory, Reservation
    职责: 库存管理、库存扣减、库存预留
    数据: 商品表、库存表、预留记录表

  上下文 C: 支付上下文
    核心概念: Payment, Transaction, Refund
    职责: 支付处理、退款、对账
    数据: 支付单表、交易流水表

  上下文映射模式:
    - 合作关系: 订单上下文 ↔ 库存上下文(同步RPC调用)
    - 防腐层: 订单上下文 → 物流上下文(通过适配器隔离)
    - 开放主机服务: 支付上下文提供标准API

3.2 防腐层(Anti-Corruption Layer)

/**
 * 防腐层示例:隔离外部物流系统
 */
@Service
public class LogisticsAntiCorruptionLayer {

    private final ThirdPartyLogisticsClient legacyClient;
    private final LogisticsMapper mapper;
    private final CircuitBreaker circuitBreaker;

    // 适配器:将外部模型转换为内部模型
    public ShipmentResult createShipment(InternalShipmentRequest request) {
        // 1. 转换为外部系统格式
        ExternalShipmentRequest externalRequest = mapper.toExternal(request);

        // 2. 调用外部系统(带熔断)
        ExternalShipmentResponse externalResponse = circuitBreaker.execute(() ->
            legacyClient.createShipment(externalRequest)
        );

        // 3. 处理外部系统的特殊响应
        if (externalResponse.getCode() == 503) {
            // 降级策略:记录任务,异步重试
            saveToRetryQueue(request);
            return ShipmentResult.deferred();
        }

        // 4. 转换为内部模型
        return mapper.toInternal(externalResponse);
    }
}

// 映射器:隔离外部模型变化的影响
@Component
public class LogisticsMapper {

    public ExternalShipmentRequest toExternal(InternalShipmentRequest internal) {
        ExternalShipmentRequest external = new ExternalShipmentRequest();
        external.setOrderId(internal.getOrderId());
        external.setReceiverName(internal.getReceiverName());
        external.setReceiverAddress(internal.getAddress().toString());
        external.setPackageWeight(internal.getWeight().getGrams());
        // 外部系统使用旧的单位制
        external.setPackageLength((int) (internal.getLength().getCm() * 10));
        return external;
    }

    public ShipmentResult toInternal(ExternalShipmentResponse external) {
        ShipmentResult result = new ShipmentResult();
        result.setTrackingNumber(external.getWaybillNo());
        result.setEstimatedDelivery(external.getEstimateDate());
        result.setStatus(mapStatus(external.getStatus()));
        return result;
    }

    private ShipmentStatus mapStatus(String externalStatus) {
        switch (externalStatus) {
            case "CREATED": return ShipmentStatus.PENDING;
            case "PICKED": return ShipmentStatus.PICKED;
            case "DELIVERED": return ShipmentStatus.DELIVERED;
            default: return ShipmentStatus.UNKNOWN;
        }
    }
}

3.3 服务边界划分原则

/**
 * 服务划分检查清单
 */
public class ServiceBoundaryChecklist {

    // 1. 单一职责:一个服务只做一件事
    // 2. 独立性:服务可以独立开发、测试、部署、扩展
    // 3. 数据边界:服务拥有自己的数据存储(不应共享数据库)
    // 4. 团队边界:一个服务由一个团队维护
    // 5. 变更边界:不同服务的变更频率应该独立

    // 反模式检查
    boolean isDistributedMonolith(Service a, Service b) {
        // 如果两个服务经常需要同时部署,就是分布式单体
        return a.deploymentFrequency == b.deploymentFrequency;
    }

    boolean hasSharedDatabase(Service a, Service b) {
        // 共享数据库破坏服务边界
        return a.database == b.database;
    }

    boolean hasChattyCalls(Service a, Service b) {
        // 循环调用或批量调用过多
        return a.callsTo(b) > 100 && a.callsTo(b) < 1000;
    }
}

四、非功能性需求设计

4.1 非功能性需求清单

性能:
  - 预期QPS/TPC: 峰值 10000 QPS
  - 响应时间: P99 < 200ms
  - 吞吐量: 每秒处理 5000 笔订单

可用性:
  - SLA目标: 99.99%(每年宕机 < 52分钟)
  - MTBF: 平均故障间隔 > 30天
  - MTTR: 平均恢复时间 < 15分钟

可扩展性:
  - 水平扩展: 支持从3节点扩展到100节点
  - 数据扩展: 支持每年2倍数据增长
  - 功能扩展: 支持插件化扩展新支付方式

安全性:
  - 认证: OAuth2/JWT
  - 授权: RBAC权限模型
  - 数据加密: TLS传输 + 字段级加密
  - 合规: GDPR, PCI-DSS

可维护性:
  - 代码质量: 圈复杂度 < 10
  - 文档完整: API文档、架构决策记录
  - 可测试性: 单元测试覆盖率 > 80%

可靠性:
  - 数据持久化: 强一致或最终一致
  - 灾备: RTO < 1小时, RPO < 5分钟
  - 容错: 熔断、重试、降级

可观测性:
  - 日志: 结构化日志, 分级管理
  - 指标: 业务指标、技术指标
  - 追踪: 全链路分布式追踪

4.2 SLA、SLO、SLI设计

SLI (Service Level Indicator): 服务质量指标
  - 请求成功率: 成功请求数 / 总请求数
  - 延迟: P99响应时间
  - 吞吐量: QPS
  - 可用性: 服务可访问时间比例

SLO (Service Level Objective): 服务质量目标
  - 99.9%的请求成功率 > 99.99%
  - P99延迟 < 200ms
  - 可用性 > 99.99%

SLA (Service Level Agreement): 服务等级协议
  - 承诺:99.99%可用性
  - 补偿:每降低0.01%赔偿1%月费
  - 例外:计划维护、第三方故障

计算公式:
  - 可用性 = (总时间 - 不可用时间) / 总时间 × 100%
  - 错误预算 = 1 - SLO目标
    (99.99% SLO → 0.01%错误预算 ≈ 52分钟/年)
// SLI监控实现示例
@Component
public class SLIMonitor {
    private final AtomicLong totalRequests = new AtomicLong();
    private final AtomicLong successRequests = new AtomicLong();
    private final Histogram latencyHistogram = Histogram.build()
        .buckets(1, 5, 10, 25, 50, 100, 200, 500, 1000)
        .register();

    @Around("@annotation(Monitored)")
    public Object monitor(ProceedingJoinPoint joinPoint) throws Throwable {
        totalRequests.incrementAndGet();
        long start = System.currentTimeMillis();

        try {
            Object result = joinPoint.proceed();
            successRequests.incrementAndGet();
            return result;
        } finally {
            long latency = System.currentTimeMillis() - start;
            latencyHistogram.observe(latency);
        }
    }

    @Scheduled(fixedDelay = 60000)
    public void reportSLO() {
        long total = totalRequests.getAndSet(0);
        long success = successRequests.getAndSet(0);

        double successRate = total > 0 ? (double) success / total : 1.0;
        double p99 = latencyHistogram.quantile(0.99);

        // 发送到监控系统
        metrics.push("sl_success_rate", successRate);
        metrics.push("sl_p99_latency", p99);

        // 检查是否违反SLO
        if (successRate < 0.999) {
            alert.send("SLO Violation: success rate below 99.9%");
        }
        if (p99 > 200) {
            alert.send("SLO Violation: P99 latency above 200ms");
        }
    }
}

4.3 容错设计模式

/**
 * 超时控制
 */
public class TimeoutConfiguration {

    @Bean
    public RestTemplate restTemplate() {
        RequestConfig config = RequestConfig.custom()
            .setConnectTimeout(1000)      // 连接超时1秒
            .setSocketTimeout(3000)       // 读超时3秒
            .setConnectionRequestTimeout(500)  // 从池获取连接超时
            .build();

        return new RestTemplateBuilder()
            .setConnectTimeout(Duration.ofSeconds(1))
            .setReadTimeout(Duration.ofSeconds(3))
            .build();
    }

    // 超时建议:
    // - 连接超时: 通常是网络问题,100-1000ms
    // - 读超时: 取决于业务处理时间,预估P99 * 2
    // - 避免使用过长的超时(会堆积线程)
    // - 超时后必须有降级或重试逻辑
}

/**
 * 重试策略
 */
@Component
public class RetryConfiguration {

    @Retryable(
        value = {RemoteServiceException.class},
        maxAttempts = 3,
        backoff = @Backoff(delay = 100, multiplier = 2, maxDelay = 5000)
    )
    public String callRemoteService() {
        // 重试间隔:100ms, 200ms, 400ms
        return restTemplate.getForObject("http://service/api", String.class);
    }

    // 重试注意事项:
    // 1. 只对幂等操作进行重试
    // 2. 设置最大重试次数(避免死循环)
    // 3. 使用退避策略避免重试风暴
    // 4. 区分可重试异常(网络超时)和不可重试异常(参数错误)
}

/**
 * 熔断器
 */
@Service
public class CircuitBreakerService {

    private final CircuitBreaker circuitBreaker;

    public CircuitBreakerService() {
        CircuitBreakerConfig config = CircuitBreakerConfig.custom()
            .failureRateThreshold(50)              // 失败率阈值50%
            .slidingWindowSize(10)                 // 滑动窗口大小
            .minimumNumberOfCalls(5)               // 最少调用次数
            .waitDurationInOpenState(Duration.ofSeconds(30))  // 熔断开启时间
            .permittedNumberOfCallsInHalfOpenState(3)         // 半开状态试探请求数
            .build();

        this.circuitBreaker = CircuitBreaker.of("payment-service", config);
    }

    public PaymentResult processPayment(PaymentRequest request) {
        return circuitBreaker.executeSupplier(() -> {
            return restTemplate.postForObject("http://payment/api/charge", request, PaymentResult.class);
        });
    }
}

/**
 * 舱壁隔离(线程池隔离)
 */
@Component
public class BulkheadConfig {

    // 为不同服务分配独立的线程池
    @Bean(name = "paymentExecutor")
    public ExecutorService paymentExecutor() {
        return new ThreadPoolExecutor(
            10, 20, 60L, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(100),
            new NamedThreadFactory("payment"),
            new ThreadPoolExecutor.CallerRunsPolicy()
        );
    }

    @Bean(name = "orderExecutor")
    public ExecutorService orderExecutor() {
        return new ThreadPoolExecutor(
            20, 50, 60L, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(200),
            new NamedThreadFactory("order"),
            new ThreadPoolExecutor.CallerRunsPolicy()
        );
    }

    // 使用舱壁隔离
    @Async("paymentExecutor")
    public CompletableFuture<PaymentResult> processPaymentAsync(PaymentRequest request) {
        // 支付调用不会影响订单处理
    }
}

来源:
http://qcycj.cn/

相关文章
|
27天前
|
算法 测试技术 PyTorch
在 AMD ROCm DSW 上部署 Qwen3.6-27B-FP8:vLLM、MTP 解码加速与小并发压测
本文记录一次在 ModelScope DSW AMD GPU 实例上完成的 Qwen3.6-27B-FP8 推理实践。实验重点不是单纯证明模型可以启动,而是围绕 vLLM ROCm 服务、Qwen MTP 投机解码、near-8K 长上下文正确性验证、FP8 KV cache 和小并发 serving 压测,整理一套可复现、可复查、可继续扩展的 AMD GPU 大模型推理 baseline。
662 0
|
27天前
|
存储 人工智能 运维
千亿级 AI 搜索的效能实战:从混合检索到 Agentic RAG 的三年实战
本文为2026 Elastic中国大会演讲实录,直击千亿级AI搜索三大挑战:搜索融合(关键词+向量+稀疏检索原生一体)、极致效能(冷热分层、硬件降级、自研FalconSeek引擎)与Agentic RAG演进(结构化知识图谱+智能体自主推理),揭示企业级AI搜索从“能用”到“好用”再到“自进化”的实战路径。
465 8
|
27天前
|
缓存 前端开发 安全
ReAct推理链的工程化实现与最佳实践
本文介绍向量空间JBoltAI平台基于Spring Boot 3.x与Java 21实现的企业级ReAct推理链架构,涵盖分层设计、模板方法、Function Calling驱动、并发安全机制及推理可视化等核心实践,助力LLM能力可靠落地。
|
27天前
|
API
车型库查询-车型大全-车系大全-车型识别-汽车标志-车型车系-汽车品牌API接口介绍
本API提供全量车型库查询服务,支持按品牌→车系→车型三级检索,覆盖比亚迪、宝马等主流品牌及年款、排量、驱动、环保标准、指导价、配置参数等字段,广泛应用于汽车销售、保险与维修场景。
170 0
|
27天前
|
算法 NoSQL Java
Java在分布式ID生成器(雪花算法)中的实现与优化
在分布式系统中,需要全局唯一、趋势递增、高性能的ID(如订单号、消息ID)。数据库自增ID在分库分表后不再唯一;UUID无序且过长,影响索引性能。
262 1
|
27天前
|
人工智能 运维 搜索推荐
重构搜索范式:阿里云 Elasticsearch 开启“Agent 原生”时代,打造企业级 AI 记忆湖
阿里云Elasticsearch提出“Agent原生搜索”理念,打造面向AI智能体的高性能、全模态企业级AI搜索基础设施。通过Agent Skills、统一Builder平台、上下文引擎与自研FalconSeek引擎,实现结构化结果输出、分钟级Agent开发、混合检索加速及50%-300%性能提升,助力构建企业“Agent知识记忆湖”。
297 3
|
27天前
|
人工智能 自然语言处理 监控
阿里云百炼大模型服务平台如何部署模型?具体流程与模型计费方式和收费标准参考
本文系统介绍了阿里云百炼平台大模型从调优到部署上线的流程。首先需完成数据准备与模型调优,生成自定义模型并获取API Key;随后在模型部署控制台选择模型与计费方式(后付费/预付费),配置推理模式、上下文长度等参数,等待服务状态变为"运行中"即部署成功。平台提供预置吞吐、模型单元、Token用量三种计费模式,分别适用于高并发生产场景、资源隔离需求及效果验证场景,支持按量与包月付费。部署后可通过OpenAI兼容API、Dify、Chatbox等多种方式调用,也可借助Gradio搭建本地Web UI,满足多样化应用需求。
|
27天前
|
存储 算法 C++
C++在高性能内存池(MemoryPool)设计与实现
频繁调用new/delete或malloc/free会造成性能损耗(系统调用、锁竞争、内存碎片)。
164 3
|
27天前
|
人工智能 数据挖掘 调度
2026-05-25OPC中国是什么?智能体来了为何布局OPC一人公司与OPD一人部门人才生态
OPC中国是“智能体来了”旗下开源共创社区,专注AI时代OPC(一人公司)与OPD(一人部门)人才培育。面向政府、高校、园区三大场景,推动人才成长、创业孵化、就业支持与企业智能化,助力个体从AI使用者升级为AI交付者。(239字)
330 1
|
27天前
|
JSON 自然语言处理 前端开发
谷歌深夜发布 Gemini 3.5:多模态能力再升级,开发者该怎么抓住这波机会?
Gemini 3.5 Flash于2026年5月发布,主打原生多模态与实时智能体能力:支持图文音视一体化理解、帧级视频诊断、100万token长上下文,并在编码(76.2%)、Agent任务(83.6%)等实测中超越前代。速度快4倍、成本更低,已免费开放。