
简介这份PDF资料围绕企业总体架构展开面向架构师、技术负责人及中高级研发人员系统讲解业务架构、应用架构、数据架构与技术架构四大领域的定位与协作关系。内容以一家拥有200位研发、200多台服务器的公司为案例复盘系统故障频发、运维困难等真实问题并给出从架构现状梳理到中远期规划、领域模型与分层设计的完整思路帮助读者建立全局架构视角理解物理架构不合理如何拖累应用架构。资源包内含1个PDF文件约615KB篇幅精炼适合作为架构改造前的参考文档或团队内部培训材料。目前已有3434人学习读者可从中获得架构文档的目录组织方式、业务模型到应用系统的映射方法以及数据E-R图、状态图与领域模型在服务化中的落地要点对排查系统根因、制定技改方案具有直接借鉴价值。1. 四层架构不是 PPT 分层从一次线上故障说起业务架构、应用架构、数据架构和技术架构这四个词几乎出现在每一份架构评审文档里但真正能把它们拆开讲清楚、并在代码和配置层面落地的人并不多。我见过太多团队把四层架构画成一张漂亮的四层方块图然后该耦合的照样耦合该绕过的照样绕过。直到某次线上故障——一个促销规则变更导致订单服务雪崩排查了六个小时才发现业务规则的改动直接穿透到了数据层中间没有任何防腐层。这就是典型的四层架构没有真正分层。这篇文章面向的是需要做架构设计或评审的工程师、技术负责人。我会把四层架构各自的职责边界、它们之间的依赖关系、以及怎么用可执行的方式去验证分层是否合理一步步讲清楚。不是科普是能直接拿去用的落地方法。如果你正在做系统重构、微服务拆分或者只是想让自己的架构文档不再被挑战这篇值得看完。2. 四层架构各自的职责边界谁管什么、谁不该管什么2.1 业务架构定义做什么而不是怎么做业务架构回答的核心问题是这个系统为谁服务、提供什么价值、业务流程怎么流转。它的产出物通常是业务能力地图、业务流程模型、业务规则定义。注意业务架构不关心用什么数据库、部署几台机器。我一般用业务能力地图来梳理。具体做法是先把业务域拆成一级能力再往下拆二级能力每个能力标注输入、输出和触发条件。比如电商场景下订单履约是一级能力拆单分配仓库生成物流单是二级能力。# 业务能力地图示例YAML 描述可导入架构管理工具 business_capabilities: - name: 订单履约 level: 1 sub_capabilities: - name: 拆单 input: 原始订单 output: 子订单列表 trigger: 订单支付完成 rules: - 按仓库维度拆分 - 按商品类型拆分实物/虚拟 - name: 分配仓库 input: 子订单 output: 仓库分配结果 trigger: 拆单完成 rules: - 优先就近仓库 - 库存不足时降级到备用仓库这段 YAML 的关键在于每个能力都有明确的输入、输出和触发条件。这样做的好处是后续做应用架构映射时每个二级能力都能对应到一个或一组应用服务不会出现这个能力到底归谁管的扯皮。参数上rules字段是业务规则的显式声明这些规则后续要么落在应用层的规则引擎里要么落在数据层的约束里但绝不应该散落在代码的 if-else 中。2.2 应用架构定义怎么组织服务而不是怎么部署应用架构的核心职责是把业务能力映射成应用服务并定义服务之间的协作关系。它关注的是有哪些应用服务、每个服务负责哪些业务能力、服务之间怎么通信同步/异步、有没有共享的服务。常见做法是用领域驱动设计DDD来指导应用架构的划分。限界上下文Bounded Context对应到应用服务上下文映射Context Map对应到服务间的集成关系。# 应用服务注册与依赖声明伪代码用于架构治理平台 from dataclasses import dataclass, field from enum import Enum class CommType(Enum): SYNC_HTTP sync_http ASYNC_MQ async_mq dataclass class AppService: name: str bounded_context: str capabilities: list # 映射的业务能力 dependencies: list field(default_factorylist) # 依赖的其他服务 comm_type: CommType CommType.SYNC_HTTP # 订单服务 order_service AppService( nameorder-service, bounded_context订单上下文, capabilities[拆单, 订单状态管理], dependencies[inventory-service, payment-service], comm_typeCommType.SYNC_HTTP ) # 履约服务 fulfillment_service AppService( namefulfillment-service, bounded_context履约上下文, capabilities[分配仓库, 生成物流单], dependencies[order-service, warehouse-service], comm_typeCommType.ASYNC_MQ )这段代码的价值在于把应用架构的依赖关系显式化。dependencies字段声明了服务依赖comm_type区分了同步和异步。实际落地时这个声明可以接入 CI 流程做依赖检查——如果代码里出现了未声明的依赖调用直接构建失败。参数上bounded_context是 DDD 的核心概念一个上下文内应该只有一个服务拥有写权限其他服务只能通过 API 或消息读取。2.3 数据架构定义数据怎么存、怎么流而不是用什么数据库数据架构解决的是数据的产生、存储、流转和消费。它包括数据模型实体关系、数据分布分库分表策略、数据流转ETL/CDC 管道、数据生命周期归档/删除策略。我一般会先画数据流图标注每个数据实体的源头System of Record、流转路径和消费方。然后针对每个实体定义数据模型和存储选型。数据实体源头服务存储选型分区策略保留周期订单order-serviceMySQL按用户ID哈希3年订单事件order-serviceKafka按订单ID7天履约记录fulfillment-servicePostgreSQL按仓库ID2年库存快照inventory-serviceRedis MySQL按SKU实时1年这张表的关键列是源头服务——每个数据实体只能有一个写入源头其他服务通过 API 或事件获取数据。这是避免数据不一致的第一原则。分区策略决定了扩展性上限保留周期直接影响存储成本这两个参数必须在架构评审时明确。2.4 技术架构定义用什么技术栈和基础设施而不是业务怎么跑技术架构是四层里最底层的它关注的是技术栈选型、基础设施拓扑、非功能性需求性能、可用性、安全性的实现方式。它不应该包含任何业务逻辑。常见的技术架构决策包括服务框架选型Spring Cloud / Dubbo / 自研、通信协议HTTP/gRPC、服务发现方案、配置中心、可观测性体系日志/指标/链路追踪。# 技术架构决策记录ADR模板示例 # 文件adr-001-service-framework.md # ADR-001: 服务框架选型 ## 状态 已采纳 ## 背景 需要为 20 微服务选择统一的服务框架要求支持服务发现、配置管理、熔断限流。 ## 决策 采用 Spring Cloud Alibaba 体系 - 服务发现Nacos - 配置中心Nacos Config - 熔断限流Sentinel - 网关Spring Cloud Gateway ## 理由 1. 团队已有 Spring 技术栈积累学习成本低 2. Nacos 同时覆盖服务发现和配置管理减少组件数量 3. Sentinel 的流控规则支持动态推送无需重启 ## 影响 - 所有新服务必须引入统一的 starter 依赖 - 运维需要维护 Nacos 集群的高可用 - 后续如果迁移到 Service Mesh需要评估兼容性ADR 是技术架构决策的标准做法。每个决策记录背景、决策内容、理由和影响后续如果有人质疑为什么用 Nacos 不用 Consul直接翻 ADR 就行。参数上状态字段很重要——已采纳、已废弃、待评估这能让团队知道哪些决策还有讨论空间。3. 四层架构的依赖关系与映射方法从业务能力到技术组件的追溯链3.1 自上而下的映射业务能力 → 应用服务 → 数据实体 → 技术组件四层架构不是孤立的它们之间存在明确的映射关系。我一般用追溯矩阵来管理这种关系。# 架构追溯矩阵简化实现 traceability_matrix { 拆单: { app_service: order-service, data_entities: [订单, 子订单], tech_components: [MySQL, Kafka] }, 分配仓库: { app_service: fulfillment-service, data_entities: [履约记录, 库存快照], tech_components: [PostgreSQL, Redis] } } # 检查是否存在没有应用服务承载的业务能力 def check_orphan_capabilities(capabilities, matrix): orphans [] for cap in capabilities: if cap not in matrix or not matrix[cap].get(app_service): orphans.append(cap) return orphans # 检查是否存在没有数据实体支撑的应用服务 def check_orphan_services(matrix): orphan_services [] for cap, mapping in matrix.items(): if not mapping.get(data_entities): orphan_services.append(mapping[app_service]) return orphan_services这段代码做的是架构完整性检查。check_orphan_capabilities找出没有应用服务承载的业务能力——这通常意味着有业务需求被遗漏了。check_orphan_services找出没有数据实体支撑的应用服务——这通常意味着服务划分过细或者数据归属不清晰。实际使用时这两个检查可以接入架构评审流程作为准入门槛。3.2 自下而上的验证技术变更如何影响业务能力反向追溯同样重要。当技术架构发生变更时比如数据库从 MySQL 迁移到 PostgreSQL需要评估影响范围。-- 查询某个技术组件变更会影响哪些业务能力 -- 假设有架构元数据表 SELECT bc.name AS business_capability, aps.name AS app_service, de.name AS data_entity, tc.name AS tech_component FROM tech_components tc JOIN data_entities de ON de.tech_component_id tc.id JOIN app_services aps ON aps.id de.app_service_id JOIN business_capabilities bc ON bc.id aps.capability_id WHERE tc.name MySQL ORDER BY bc.name;这条 SQL 查的是如果 MySQL 要变更哪些业务能力会受影响。结果可以直接用于变更影响评估报告。参数上tech_component_id和app_service_id的关联关系需要在架构管理工具中维护建议每次架构评审后更新。3.3 用架构决策记录ADR串联四层每个重要的架构决策都应该记录它影响了哪几层。比如订单服务拆分这个决策业务架构层面是拆单能力独立应用架构层面是新增 order-service数据架构层面是订单库独立技术架构层面是新增一个 MySQL 实例。# ADR-002: 订单服务从单体中拆分 ## 影响的架构层 - 业务架构拆单能力从订单履约中独立成为一级能力 - 应用架构新增 order-service原单体中的订单模块下线 - 数据架构订单库从共享库中独立通过 CDC 同步到数据仓库 - 技术架构新增 MySQL 实例新增 Kafka Topic ## 验证方式 - 业务层拆单流程的端到端测试通过 - 应用层order-service 的契约测试通过 - 数据层订单数据一致性校验通过源库与数仓对比 - 技术层新实例的监控指标接入完成这种记录方式的好处是半年后有人问为什么订单库是独立的翻 ADR 就能看到完整的决策链路。4. 落地实操用代码和配置把四层架构管起来4.1 用 YAML 定义业务架构并生成应用架构骨架我一般会写一个代码生成器从业务能力地图自动生成应用服务的骨架代码。# 从业务能力地图生成应用服务骨架 import yaml def generate_service_skeleton(capability_file, output_dir): with open(capability_file) as f: data yaml.safe_load(f) for cap in data[business_capabilities]: for sub in cap.get(sub_capabilities, []): service_name f{sub[name].lower().replace( , -)}-service # 生成服务目录结构 skeleton { service_name: service_name, capability: sub[name], input: sub[input], output: sub[output], trigger: sub[trigger], rules: sub.get(rules, []) } # 写入服务描述文件 with open(f{output_dir}/{service_name}.yaml, w) as out: yaml.dump(skeleton, out, allow_unicodeTrue) print(fGenerated skeleton for {service_name}) # 使用 generate_service_skeleton(capabilities.yaml, ./services)这段代码做的是从业务能力自动生成服务描述文件。capability_file是业务能力地图的 YAML 文件output_dir是生成目录。每个服务描述文件包含了该服务承载的业务能力、输入输出和业务规则。后续开发人员拿到这个文件就知道自己要实现什么不需要再去翻需求文档。4.2 数据架构的自动化校验确保数据实体有明确的源头数据架构最容易出的问题是多头写入——多个服务同时写同一个数据实体。我一般用自动化校验来防止这种情况。# 数据实体源头校验 import yaml def validate_data_ownership(data_arch_file): with open(data_arch_file) as f: data yaml.safe_load(f) errors [] for entity in data[data_entities]: writers entity.get(writers, []) if len(writers) 1: errors.append( f数据实体 {entity[name]} 有多个写入方: {writers}。 f只能有一个源头服务。 ) if not writers: errors.append( f数据实体 {entity[name]} 没有写入方。 f请指定源头服务。 ) if errors: for e in errors: print(f[ERROR] {e}) return False print(数据实体源头校验通过) return True # 使用 validate_data_ownership(data_architecture.yaml)这段代码检查每个数据实体是否只有一个写入方。writers字段列出所有写入该实体的服务。如果超过一个直接报错。这个校验应该接入 CI 流程每次数据架构变更时自动运行。参数上data_entities列表需要和实际的数据模型保持同步建议从数据库的 DDL 自动生成。4.3 技术架构的依赖检查防止技术组件被业务代码直接引用技术架构的一个常见反模式是业务代码直接依赖具体的技术组件比如直接调用 Redis 客户端导致技术组件变更时业务代码需要大改。// 反模式业务代码直接依赖 Redis public class OrderService { private Jedis jedis new Jedis(redis-host, 6379); public Order getOrder(String orderId) { String cached jedis.get(order: orderId); // ... } } // 正确模式通过抽象接口访问缓存 public interface CachePort { String get(String key); void set(String key, String value, int ttlSeconds); } public class OrderService { private CachePort cache; public OrderService(CachePort cache) { this.cache cache; } public Order getOrder(String orderId) { String cached cache.get(order: orderId); // ... } }正确模式的关键是引入CachePort接口业务代码只依赖接口不依赖具体实现。这样从 Redis 迁移到其他缓存时只需要换一个实现类。参数上CachePort接口应该定义在应用层实现类放在基础设施层这是六边形架构的标准做法。5. 避坑指南四层架构落地中最容易翻车的 5 个场景5.1 业务架构和应用架构混在一起写现象架构文档里既有业务流程图又有服务调用关系还有数据库表设计全部混在一张图里。评审时没人能说清楚某个变更到底影响哪一层。原因没有强制分层输出。很多团队为了省事把四层架构画在一张图上导致边界模糊。解决强制要求每层架构单独输出文档并且用追溯矩阵关联。评审时先过业务架构确认业务能力完整再过应用架构确认服务划分合理最后过数据和技术架构。每层评审通过后才能进入下一层。5.2 数据架构被应用架构倒逼现象应用服务先拆了然后发现数据也要跟着拆但数据拆分方案没有提前设计导致数据一致性问题频发。原因应用架构和数据架构的评审顺序错了。正确的顺序是先定数据架构数据实体、源头、流转再定应用架构服务划分、依赖关系。解决在架构评审流程中数据架构评审必须排在应用架构评审之前。数据实体的源头服务确定后应用服务的划分就有了约束条件——每个服务只能写自己拥有的数据实体。5.3 技术架构决策没有记录导致重复讨论现象团队花了两个月选定了服务框架半年后新来的架构师又提出要重新选型理由是没看到之前的决策记录。原因技术架构决策没有用 ADR 记录或者记录了但没有放在团队能访问的地方。解决所有技术架构决策必须写 ADR并且放在代码仓库的docs/adr/目录下。每个 ADR 包含状态、背景、决策、理由、影响。状态为已采纳的决策除非有新的 ADR 明确废弃否则不允许重新讨论。5.4 业务能力地图太粗或太细现象业务能力地图只有一级能力导致应用服务划分时颗粒度对不上或者拆到了四级能力导致服务数量爆炸。原因没有明确拆分标准。我一般建议拆到二级能力每个二级能力对应一个或一组应用服务。如果某个二级能力还是太大再往下拆一级但最多到三级。解决制定拆分标准——每个二级能力应该能在一个迭代内完成开发并且有明确的输入输出。如果某个能力需要跨多个迭代说明拆得不够细如果某个能力只有一个简单的 CRUD说明拆得太细。5.5 追溯矩阵没人维护变成一次性文档现象架构评审时建了追溯矩阵评审结束后没人更新三个月后矩阵和实际代码完全对不上。原因追溯矩阵没有接入自动化流程全靠人工维护。解决把追溯矩阵的维护嵌入 CI 流程。每次代码提交时自动检查新增的 API 是否在追溯矩阵中声明新增的数据实体是否有明确的源头服务。检查不通过则构建失败。这样追溯矩阵就变成了活文档而不是一次性文档。6. 进阶技巧用架构适应度函数持续验证四层架构架构适应度函数Architecture Fitness Function是我最近两年用得最多的技巧。它的核心思想是把架构约束写成自动化测试每次代码变更时自动验证架构是否仍然符合设计。# 架构适应度函数示例验证应用服务不直接依赖其他服务的数据层 import ast import os def check_no_cross_service_db_access(service_dir): 检查服务代码中是否直接访问了其他服务的数据库。 规则每个服务只能访问自己的数据库跨服务数据访问必须通过 API。 violations [] for root, dirs, files in os.walk(service_dir): for file in files: if not file.endswith(.py): continue filepath os.path.join(root, file) with open(filepath) as f: tree ast.parse(f.read()) for node in ast.walk(tree): # 检查是否有跨服务的数据库连接字符串 if isinstance(node, ast.Constant) and isinstance(node.value, str): if db- in node.value and order-service not in filepath: if order-db in node.value: violations.append( f{filepath}: 直接访问了 order-db f应通过 order-service API 访问 ) return violations # 接入 CI violations check_no_cross_service_db_access(./services) if violations: for v in violations: print(f[FITNESS-FAIL] {v}) exit(1)这个适应度函数检查的是每个服务只能访问自己的数据库。service_dir是服务代码目录函数遍历所有 Python 文件检查是否有跨服务的数据库连接字符串。如果有直接失败。这个检查应该放在 CI 的构建阶段每次提交都运行。除了这个例子我还常用以下几个适应度函数适应度函数验证的架构约束检查时机服务依赖检查应用服务只依赖声明的服务每次提交数据实体源头检查每个数据实体只有一个写入方每次数据架构变更技术组件隔离检查业务代码不直接依赖技术组件每次提交业务能力覆盖检查每个业务能力都有应用服务承载每次业务架构变更接口契约检查服务间接口符合 OpenAPI 规范每次 API 变更这些适应度函数的共同点是它们把架构约束从文档里的规定变成了代码里的测试。架构师不需要每次评审都手动检查这些约束CI 会自动完成。我自己的习惯是每发现一个新的架构反模式就写一个适应度函数来防止它再次出现。这样架构治理就变成了一个持续积累的过程而不是一次性的评审活动。希望帮到你。本文还有配套的精品资源点击获取