做了几年系统架构设计后,我越来越觉得“信息系统工程”这个词被很多同行看小了。多数人一提信息系统工程,第一反应是“做一个管理系统”,第二反应是“画几张架构图”。但真正做完几个跨系统、跨组织、跨数据源的项目之后,你会发现,信息系统工程的核心从来不是代码本身,而是如何把一个单位或一个行业的业务、数据、流程拆成一个个可实施的子系统,再用接口、数据交换、权限控制、监控运维这些工程手段,把它们拼成一个能稳定运行、能长期演进的整体。这篇笔记从定位上说,是给准备从单体应用开发走向系统集成的工程师看的,也是给那些被拉去评审企业级方案的开发负责人看的;你要是最近正被一堆系统集成、接口联调、数据不一致的问题折腾,这篇内容应该能帮你少走不少弯路。
1. 先把边界画清楚:信息系统工程不等于写代码
1.1 信息系统工程到底在解决什么问题
我见过不少团队把信息系统工程做成“一个后台管理加一个前端页面”,做完才发现根本跑不起来。原因不是功能没实现,而是没搞明白这门工程要解决的是三个层次的问题。
第一个层次是流程的电子化。把原本在线下跑的业务审批、数据登记、报表统计搬到系统里,这是最基础的诉求,一般做CRUD就能覆盖。第二个层次是系统之间的协作。一个业务往往不只在单个系统里完成,比如订单在交易系统创建,库存要在仓储系统扣减,财务要在结算系统入账,这些系统可能来自不同厂商、不同年代、不同技术栈,要让它们协同工作,就必须处理接口、数据格式、异常语义、超时重试这些工程问题。第三个层次是组织效率与数据资产的沉淀。系统运行之后会产生大量业务数据,这些数据怎么清洗、怎么汇总、怎么展示给管理层,反过来又会驱动业务流程调整。
所以,信息系统工程更像是“修路”而不是“造一辆车”。路要连接不同的地点,要考虑车流量、收费站、事故处理,还要为将来拓宽留余地。单点功能写得再好,路网不通,整个系统一样是废的。这就是为什么很多项目All in功能开发却最终失败,根子往往在边界、数据、接口这些“路网”问题上。
1.2 先定边界,再谈技术选型
做信息系统工程最忌讳一上来就聊微服务、聊中间件、聊云原生。我在做一个统一工作台项目时就踩过这个坑。客户当时说得很简单:要把三个业务系统的待办事项、消息提醒、常用报表聚合到一个页面上。这个需求听起来就像写一个聚合接口,但真正推进时发现,三个系统的用户体系不一样,同一个人的工号在各系统里叫法都不一样;待办数据有的系统提供接口,有的系统只支持导出Excel;还有一个系统连数据字典都没整理,字段含义要靠翻代码猜。
如果一上来就选技术框架,这些问题根本不会暴露,等到联调阶段才爆发,就是灾难。我后来总结出一套划分系统边界的思路:先按业务能力切,再按数据归属切,最后才按团队组织切。
按业务能力切的意思是,一个业务环节最好由一个系统闭环负责。比如订单、库存、物流、结算,各自是独立能力域,不要把一个能力拆得稀碎。按数据归属切的意思是,每类数据的生产方和消费方要清楚,特别是“主数据”,比如人员、组织、客户、物料,必须有唯一的生产系统,其它系统只能消费,不能各维护一套。按团队组织切则是现实约束,如果两个系统由两个团队长期维护,边界就尽量不要跨团队,否则后续任何改动都要跨团队协调,成本极高。
这个阶段我会使用一个很土的方法:找一块白板,把所有涉及的系统画成圆,只在圆和圆之间画数据流箭头,不画任何技术组件。如果两个系统之间的箭头超过了三条,就要警惕,要么是边界切错了,要么是数据归属没定清楚。箭头多的位置,往往是整个工程后续最容易烂掉的位置。
1.3 需求阶段能救命的检查表
系统集成项目的需求调研,不能只盯着功能清单。我每次做需求访谈时都会带一份固定的检查表,按下面几个维度逐条过。
- 业务现状:当前业务是完全没有系统支持,还是已有旧系统需要替换?如果有旧系统,数据量多大、历史数据要不要迁移、旧系统什么时候彻底停用。
- 干系人边界:这个项目涉及几个部门、几个外部单位?谁对数据准确性负责?谁对系统最终运行负责?很多项目拖期,不是因为技术难,而是没人拍板数据口径。
- 非功能预期:并发量、响应时间、可用性要求分别是什么?能不能接受几分钟的中断?需不需要7×24小时服务?这些指标直接决定后面的架构形态和预算。
- 数据特征:日增数据量级有多大?是结构化数据为主还是有大量文件、图片?数据是要实时流转还是每天批量同步就可以?
- 运维条件:客户有没有专职运维?团队对自动化部署的接受度如何?如果目标环境连Docker都不能用,方案里写Kubernetes就是自找麻烦。
这些问题看起来基础,但评审过几十个方案之后我发现,绝大多数被推翻的方案,都是因为在需求阶段没有把这些边界条件锁死。技术选型错了可以换,边界切错了返工成本极高。
2. 架构选型不是追新,是对着约束做取舍
2.1 三种常见建设模式,先从副作用看
信息系统工程通常有三种建设模式,我习惯从代价的角度去评估,而不是哪个听起来更先进。烟囱式是最常见的老路:每来一个新需求就新建一个系统,各自独立开发、独立部署、独立维护。它的好处是交付快,初期不依赖别的团队;坏处是数据孤岛越来越严重,同一个用户在不同系统里被维护了好几份,报表要对数据时只能靠人工Excel合并。
平台化模式是把公共能力抽出来统一建设,比如统一的用户认证、统一的组织架构、统一的消息中心。好处是数据和能力可以复用,坏处是平台的建设周期长,而且一旦平台能力跟不上,业务系统反而被平台拖住。共享服务化模式则是比平台化更进一步,把可复用的业务能力做成了独立的服务,比如订单中心、库存中心、客户中心,各个前端应用都调用这些服务来组合业务。
三者的对比大致是这样。
| 模式 | 交付速度 | 数据共享能力 | 初期成本 | 长期维护成本 | 适用场景 |
|---|---|---|---|---|---|
| 烟囱式 | 最快 | 差 | 低 | 高 | 临时项目、小团队、明确独立边界 |
| 平台化 | 较慢 | 中 | 中 | 中 | 统一入口、公共能力沉淀 |
| 共享服务化 | 最慢 | 好 | 高 | 低 | 多业务线复用、持续迭代 |
我在实际项目里很少直接选最重的模式,而是看一个关键指标:一家单位未来三到五年内,会有多少新系统需要接入。如果只有一两个系统,烟囱式加一套接口规范完全够用;如果要持续建设数字化能力,就必须往平台化或者共享服务化走,因为等到系统数量堆积到五六个再回头整合,成本翻倍还不止。
2.2 某集团客户报表中心项目的选型复盘
一次做某集团客户报表中心项目时,方案评审上我们争论了很久。集团下面有四个独立业务系统,分别管采购、销售、仓储和财务,各自都有自己的报表模块,领导层需要一个统一的报表入口,能看到集团层面的汇总数据。
第一版方案由一个同事提出,新建一个大而全的数据仓库,把所有系统的数据全部接入,再建一个统一的报表平台,所有报表都从这个平台出。从数据治理角度看它是终态,但实施周期至少八到十个月,投入大,且四个系统的数据质量根本撑不住清洗要求,上线后会陷入长期的对账泥潭。
第二版方案更简单,直接让报表平台连四个系统的生产库做汇总查询,报表需求当天就能出演示效果。但问题是,报表查询会直接影响生产系统性能,而且四套系统的数据字典口径不统一,比如一种商品,在采购系统叫“物资名称”,在财务系统叫“存货品名”,直接汇总的数据根本不敢信。
最终我们选择了折中方案:先建一个统一的报表中心,按月度从各系统批量抽取数据到独立报表库,同时保留各系统原有报表功能,不做强制下线。报表中心先覆盖管理层最关心的核心指标,数据口径问题通过逐项核对解决。这个方案没有一步到位,但它尊重了现实约束——系统改造不可能在半年内完成,数据质量也不可能一蹴而就。事实证明,先让核心报表跑起来,再逐步收敛各系统的口径,是在这类场景里最稳的路径。
2.3 选型时最容易被忽略的三个问题
第一个是存量数据迁移方案。很多架构设计只谈新系统怎么建,完全不提旧数据怎么搬。等到上线前才意识到历史数据有几年、几百万条,清洗规则没人定,迁移时间窗口又极短,最后只能硬着头皮粗糙导入,上线后数据对不上才发现要回退。第二个是组织边界。技术方案里写了统一用户中心,但实际推进时发现各系统不愿意交出自己的用户管理权限,因为那意味着把部门的数据控制权交出去。这种问题不是技术能解决的,必须在选型阶段就让业务方明确数据责任归属。第三个是回退路径。每次评审方案我都会追问一句:“如果上线后出了问题,怎么回到老系统?”回答不出来,说明方案本身还存在未知风险。
3. 数据架构和集成设计:画数据流时就要定接口规范
3.1 主数据集中,业务数据按域收敛
数据架构在信息系统工程里的分量比技术选型重要得多。我见过的设计里,最实用的原则可以概括成两句话:核心主数据集中管理,业务明细数据按域收敛。
主数据指那些被多个系统共同使用的基础数据,比如人员、组织、客户、供应商、物料编码。这类数据最大的特点是复用性高,但各系统如果各自维护,就会出现同一个客户三种编号的情况。正确做法是确定一个权威数据源,由它负责主数据的创建、变更和分发,其它系统通过接口消费变更消息,本地只保留自己关心的子集。
业务明细数据则按业务域收敛。订单归订单域,库存归库存域,资金归资金域,各系统内部自行管理自己的业务表,外部系统要获取数据,走接口或者走数据分发。为什么不把所有数据都集中到一个库里?因为业务数据一旦大集中,写并发全压在一个单元上,数据库会成为瓶颈,而且任何一个系统变更表结构都可能影响所有人。按域收敛的意义是隔离爆炸半径:某个系统挂了,核心数据不会跟着受影响。
3.2 接口设计三个关键点:幂等、分页、消息ID
集成设计具体落到接口上,最容易出问题的不是传输协议选HTTP还是消息队列,而是基础规范。我参与过太多系统的联调,最折磨人的问题就三类:重复调用导致数据错乱、查询接口一次拉全量数据导致内存溢出、日志里根本对不上谁是哪个请求。
幂等是个听得很多但真正落实很少的概念。一个接口无论被调用一次还是十次,结果应该一致。落到操作层面,就是消费方每次请求都带一个业务幂等键,服务端根据这个键判断请求是否已处理。比如订单同步接口,调用方传一个由订单号和请求来源拼接的键,接收方在数据库里建唯一索引,重复请求直接被拒掉。只靠代码逻辑判断不可靠,数据库唯一约束才是兜底。
分页设计同样容易被无视。很多接口默认一次返回全量数据,数据量小没什么,一旦数据到几十万条,接口响应直接超时。规范做法是强制要求所有列表类接口支持分页参数,单页大小上限控制在500条以内,推荐用游标方式分页而不是深分页,因为深分页在数据库层要做大量的扫描,性能会随页码增长越来越差。
消息体设计也有一套固定套路。我在系统间传递消息时,消息头里至少要有三个字段:消息ID、业务ID、时间戳。看下面这个示例。
{ "msgId": "MSG20240501001ABC123456", "bizId": "ORD20240501001", "timestamp": 1714521600000, "data": { "orderNo": "ORD20240501001", "status": "PAID" } }消息ID用于全局标识这条消息本身,接收方可以去重;业务ID用于标识它描述的业务对象;时间戳用于排查消息延迟的问题。没有这三件套,出问题的时候连日志都没法查。
3.3 数据一致性:别一上来就上分布式事务
很多人在系统拆分后第一反应是引入分布式事务框架,把订单、库存、账户更新的操作都放到一个全局事务里。理论上这是最严格的方案,实践里却很难用,因为分布式事务的性能开销大、实现复杂,而且微服务环境里各个服务的数据源都不一样,分布式事务协调方一旦出问题,反而更容易卡死业务。
我在项目里更常用的是“本地消息表加定时对账”的最终一致方案。拿下单扣库存举例,订单服务在自己的数据库里先写订单数据,同时写一条待发送消息;库存服务通过消息队列消费这条消息,完成扣减。如果扣减失败,消息会重试,直到成功或者进入死信队列;同时,定时任务每天跑一次对账,把失败的订单捞出来重新处理。
有人会怀疑最终一致能不能接受,这要回归业务去看。大多数业务场景,比如订单创建后库存扣减、支付成功后发通知,允许秒级甚至分钟级的延迟,完全不影响用户感知。真正需要强一致的是账户余额变更这类敏感场景,这种场景不该拆到多个服务里,而应该放在同一个数据域内部处理。设计原则很简单:能用本地事务解决的就不要拆分,拆了之后尽量用最终一致,千万别拿分布式事务当万能解药。
4. 从评审到落地:架构方案里的实操闭环
4.1 交方案前,先准备好这三张图
我看到过很多架构方案文档,画了系统架构图、时序图、部署图,内容却很虚。一张图上面画了十来个框,框之间画了一堆箭头,但每个框对应哪个团队、哪个系统,数据从哪里来、到哪里去,量级多大、用什么协议,完全没说。评审专家看一眼就知道方案没经过思考。
有效做法是先做接口清单和数据字典,再画架构图。接口清单要列出所有系统间接口的调用方式、触发时机、数据格式、责任人。数据字典要定义清楚每个核心字段的业务含义、格式、来源系统、消费系统。做完这两样,架构图就是水到渠成的事。
至少要有三张图不能省:系统总体架构图,描述系统包含哪些模块、模块之间的依赖;数据流向图,标出数据从哪个系统产生、经过哪些加工、最终落到哪个库;部署视图,说明每个组件部署在哪类机器上,网络分区和安全边界怎么划。注意部署视图往往被忽略,但评审专家最常问的问题就是“这套系统跑在什么环境里,跨不跨区”,没有这张图很难答上来。
4.2 容量估算不能拍脑袋,要能对上公式
架构评审时最尴尬的事是被问到“你的方案能撑多少并发”,回答一句“应该没问题”或者“肯定够用”。正确做法是把估算过程摆出来,哪怕用的是粗略模型,也比没有强。
假设我们要建设一个面向某集团员工的日常办公平台,日活跃用户1万人,峰值并发在线人数按20%算就是2000人。一般业务系统里,一个用户在一个活跃分钟内会产生大概5到10个请求,我们取中间值8。这样每秒请求数就是2000乘8除以60,大约267 QPS。考虑到业务峰值往往出现在上午9点到10点,大概是平均值的3到5倍,那系统就要按1000 QPS左右来设计。
存储侧也要算。假设每天新增10万条业务记录,单条记录按2KB算,一天是200MB;再加日志、临时表、备份空间,按3倍冗余,一天新增约600MB。半年就是约110GB。按照这个量级,在线业务库配置就可以定下来了,选型时也就不用再凭感觉。
| 指标 | 估算值 | 说明 |
|---|---|---|
| 日活跃用户 | 1万人 | 产品预期 |
| 峰值在线数 | 2000人 | 20%日活 |
| 平均单用户请求数 | 8次/分钟 | 含页面资源与接口 |
| 平均QPS | 267 | 2000*8/60 |
| 峰值QPS | 1000 | 平均值的3~5倍 |
| 日均新增数据 | 600MB | 业务数据含冗余 |
| 半年存储 | 110GB | 按180天估算 |
这是一套粗粒度模型,但它把方案评审从“感觉够用”变成了“数字可查”,后续做压测、做容量规划的基准也都在这里。
4.3 高可用设计,对着RTO和RPO选
高可用设计最容易走进两个极端,要么是“全都双机热备”,要么是“先上线再说”。真正靠谱的做法是先明确两个指标:RTO,灾难发生后业务系统多久能恢复;RPO,灾难发生后最多允许丢失多久的数据。
这两个指标业务方必须给答案。如果客户能接受5分钟的中断和最多10分钟的数据丢失,那就没必要上多机房双活,一台应用服务器双节点加数据库一主一从,每日全量备份加两小时增量备份就够了。如果业务要求99.99%可用性,也就是全年停机时间少于53分钟,那必须考虑应用多活、数据库高可用、故障自动切换,机房级别容灾可能也得考虑。
我在方案里常用的一句话是:高可用设计没有最好,只有匹配。预算充足的单位当然可以用最重的方案,但对大部分客户来说,把钱花在监控告警、备份恢复演练上,比盲目堆节点更能带来实际效果。后面我会单独说监控会发现,很多“高可用事故”其实根本不是硬件故障,而是变更操作失误或配置错误,这些靠备份回滚、灰度发布就能解决大半,并不需要昂贵的多活架构。
5. 集成项目排障实录:四类问题我基本都遇到过
5.1 联调几周不畅,先查报文和链路
集成项目最痛苦的阶段是联调。有一次对接某外部单位的人脸识别服务,两边联调了三周,对接开发换了两个人,问题都定位不了。后来我到现场一看,发现两边对“接口成功”的定义就不同:对方认为HTTP 200就算成功,我方认为业务返回码为0才算成功,两个团队对着日志各说各话,白白耗了两周。
从此我整理了一套三层排查法。第一层查报文,抓请求和响应,看HTTP状态码和业务状态码是不是符合双方约定的语义;第二层查环境,确认测试环境、生产环境的IP白名单、证书、加密方式等配置是否一致;第三层查链路,用同一笔业务数据走一遍全链路,把每一步的日志时间戳排出来,看延迟和耗时的瓶颈在哪。
这套方法的重点不是某个工具,而是敢于把问题往小了拆。集成联调绝大多数问题不是逻辑复杂,而是语义不一致、环境配置差异、字段映射错误这三种低水平问题。按层级定位,一般半小时内能找到根因。
5.2 重复扣减的惨案,靠幂等键救回来
某次做订单和库存联调,线上出现了库存被多扣的情况。排查后发现,订单服务调用库存接口时发生了网络超时,订单服务认为调用失败就重试了一次,实际上第一次请求已经到达库存服务并完成了扣减,第二次重试又扣了一遍。
这就是典型的没有幂等保护的问题。事后修复时,我们给库存接口增加了幂等校验:调用方在请求头携带一个幂等键,库存服务在处理前先查询该幂等键是否已存在,存在就直接返回第一次的处理结果,同时数据库加唯一索引兜底。从那以后,我再也没有遇到过同类故障。
这事给我的教训是,幂等不能只靠业务层判断,比如“先查订单状态再决定是否扣减”,因为并发场景下两个请求可能同时读到同一份状态。数据库唯一约束才是最终防线,代码里的判断都只能算辅助。
5.3 评审过不了关的方案,大多死在这三个提问上
每次方案评审,我被挑战最多的问题集中在这几类。第一,可扩展性。方案里写了“支持水平扩展”,但被追问“现在哪台机器是瓶颈?水平扩展时要改配置还是改代码?能扩到多少量级?”就回答不上来。第二,容灾性。评审专家问“这台主机挂了业务怎么办?”,方案如果只有一句“采用高可用设计”,基本等于没说。第三,安全性。领导会问“员工信息等敏感数据怎么保护?谁有权限看到哪一层的数据?审计日志怎么留痕?”设计文档里不提这些,评审很难通过。
我的建议是提前准备一张故障场景表,把可能发生的故障按业务影响、恢复策略、可接受的恢复时间列出来。比如“订单服务宕机,影响订单创建,恢复路径是重启实例并检查消息积压,RTO目标5分钟”。这张表本身比别人问十条才答出来要专业得多。
6. 这些细节看起来小,却能给整套方案加分
6.1 日志、链路追踪和配置管理的工程底座
信息系统工程里有很多“非功能的东西”,平时没人关注,出事时全是痛点。统一日志和链路追踪一定要在架构设计阶段就规划好,每个请求生成一个traceId,贯穿网关、应用、数据库调用,出了问题按traceId一查到底。否则多系统联调时,同一个业务请求在三个系统里的日志编号各不相同,排查一次事故能花半天。
配置管理同样是重点。环境之间的差异,包括数据库地址、缓存地址、第三方密钥、功能开关,都要放到配置中心统一管理,不能出现测试环境能跑、生产环境一部署就报错的情况。我见过太多联调受阻,最后发现是某个同事本地改过配置文件没有提交。
数据库变更管理也要纳入工程体系。所有结构变更要走脚本评审,重要变更需要先查执行计划,避免一张大表加索引锁死业务。每次变更都要有对应回滚脚本,这件事我强调再多也不过分,因为生产环境一旦改错,没有回滚方案就只能干等。
6.2 监控不能只做“好看的面板”
最后聊一句监控。集成系统上线后,最容易掩盖问题的地方就是监控缺失。很多项目的监控面板上画了一堆指标,看起来满满当当,实际事故发生时什么也没提前发现。
有效监控至少要分四层。基础设施层看CPU、内存、磁盘、网络;应用层看接口耗时、错误率、线程池状态;业务层看订单量、支付成功率、任务积压量;用户层看页面响应时间和核心功能可用性。其中最重要的是业务监控,因为用户其实不关心你的CPU是多少,他只关心下单成不成功。我在项目中会把核心业务链路的关键指标单独设告警,比如“支付成功率达到99.5%以上,低于阈值立刻报警”,这样的监控才有实际意义。
我个人做项目复盘时有一个习惯,项目结束后回看当初画的架构图,找一找哪些框最后没有落地,哪些线比想象中粗得多。没落地的框,大多是当时职责边界没讨论清楚;比想象中粗的线,大多是集成问题比预期难。信息系统工程里最贵的不是服务器,也不是开发人力,而是把边界和数据想清楚的时间。下一回你启动新项目时,可以先花一天时间把涉及到的系统、团队、数据源画到一张纸上,只画边界和数据流,不画技术栈,往往在那张纸上就能看到整个项目后面会撞到的墙。