
信创改造不是“换个U”是拿全栈重新做一遍性能题过去两年我所在的团队一直在做一件事把手里的核心业务系统从传统架构迁移到信创环境下。最初接这个任务时大家的心态都差不多——不就是把服务器从X86换成鲲鹏、海光把数据库从Oracle换成达梦或者人大金仓再把中间件从WebLogic换成东方通吗听起来像是一套“换零件”的活儿。结果第一批应用做兼容适配测试时我们被现实狠狠教育了一课。CPU平台换了操作系统从CentOS换成了麒麟连编译工具链和运行库都变了系统倒是能跑起来但性能指标惨不忍睹。原本单机扛几千TPS的接口在信创环境下直接腰斩有的甚至掉了70%。老板看我们的眼神都不对了“说好的国产化改造怎么改完了比原来还慢”这篇文章就是把我们从“能用”磨到“好用”的整个全栈优化过程拆开揉碎讲清楚。不会只给你讲大道理而是把每一个决策节点、每一项调优参数的依据、每一段性能排查的链路都摆出来。无论你是刚接手信创迁移的架构师还是正在为国产化KPI焦虑的开发负责人这篇文章应该都能帮你少走不少弯路。1. 信创迁移的第一个认知拐点兼容只是及格线性能才是胜负手先说说我们评估过的真实业务画像。这套系统是典型的分布式微服务架构后端有将近60个微服务模块中间层用了统一的分布式任务调度平台前端有面向内部员工的管理端和面向外部客户的门户端数据层则是Oracle加上一套自研的分布式缓存组件。业务特点有两个一个是高频交易型日均请求量在亿级另一个是数据密集型大量的报表分析和批量任务。做信创改造需求分析的时候第一版方案很简单粗暴——按“目录产品名单”把软硬件清单列出来逐项替换跑通就收工。如果只看能否启动、能否完成基本CRUD这确实能交差。但到了压测阶段问题全暴露出来了数据库连接池频繁耗尽、线程阻塞率飙升、Full GC时间占到整个请求时长的三分之一。这时候我们才意识到之前申请的“信创适配及安全管理”类项目如果把目标停留在“适配”两个字上本质上就是把性能问题往后拖。所以我对所有做信创替代的团队有个建议把“兼容适配”这个KPI拆成两层。第一层是功能兼容也就是指令集、操作系统、数据库方言、中间件规范这些层面的跑通第二层才是真正决定项目成败的——性能等价比。你在原有平台上做到的响应时间、吞吐量、并发上限就应该是在信创平台上的及格线而“最优”是在这个及格线之上继续挖潜。这一篇文章里谈论的“性能最优”一个重要前提是在纯信创环境下我们没有把X86服务器的硬件算力当作参照物。不是说海光就一定要输给Intel鲲鹏就一定要输给AMD而是因为在大多数实际部署中信创节点的单核算力和内存带宽确实存在先天差异这时候如果代码层面的写法还停留在老平台的舒适区性能差距就会被放大到不可接受的程度。2. 指令集迁移的底层教训你写的代码换了个CPU之后逻辑都变了信创改造绕不开的第一个硬骨头就是指令集的切换。我们系统的原始技术栈里有不少C/C的底层组件是用在数据加解密、报文解析和高性能序列化这些场景的。原来在X86平台上编译打包换到ARM平台后至少要解决三个层面的问题。2.1 字节序、对齐访问和寻址模式的隐形陷阱第一个问题是字节序。虽然主流架构都是小端序但有些老代码里面为了优化性能直接写了基于X86内存布局的强转逻辑比如把一个uint32_t的指针直接强转为uint16_t的指针再取值。这种代码在X86上没问题换到部分国产ARM芯片上一旦数据类型对齐规则发生变化读出来的数据就是错的而且在跑高并发任务时才会偶现排查难度极高。第二个是对齐访问。ARM平台对未对齐的内存访问是有限制的虽然现在很多芯片已经支持非对齐访问但会有性能惩罚。我们的做法是启用编译器的严格对齐选项同时把那些手工排列的结构体全部改为1:1映射的序列化方案彻底去掉对CPU字节序的隐性依赖。第三是寻址模式。有些老的C代码喜欢在循环里频繁做全局变量访问在X86上因为强大的寻址模式性能损失不明显但在ARM平台上这类代码频繁触发多余的地址计算指令。我们后续用perf去采热点时发现光是把“全局变量改为栈上局部变量”和“循环内不变计算提到循环外”这两类优化就带来了大约15%的性能提升。2.2 编译工具链的选择用对编译器比换CPU更见效很多团队做信创迁移还是习惯用GCC的默认参数直接编一遍就完事儿了。这里我强烈建议在迁移初期就确认清楚你用的是发行版自带的GCC还是针对目标CPU做过指令集调优的版本。以我们用的鲲鹏920为例GCC 9.x以上的版本对ARMv8.2指令集的支持已经比较完善但默认编译参数只会生成通用ARM指令。想要真正压榨性能至少要加上这些优化选项# 针对鲲鹏920这类ARMv8.2平台的推荐编译选项 gcc -O3 -mcputsv110 -mtunetsv110 -ftree-vectorize -ffast-math \ -funroll-loops -fomit-frame-pointer需要注意两点。第一-mcpu和-mtune指定的核心代号必须和你的CPU型号匹配如果目标机器是飞腾FT-2000参数就得改成-mcpuft-2000plus乱用反而会编译出无法运行的指令集。第二-ffast-math能大幅提升浮点运算性能但它会改变IEEE浮点行为对于金融类、科学计算类的业务要慎用我们只在非金额计算的模块里开了这个选项。另外启用LTO链接时代码优化也是一个重要收益点。我们把整个C/C公共库的编译流程加上-flto之后跨编译单元的静态函数内联明显增加加解密模块的单次调用耗时又降了一截。我建议所有做信创迁移的团队把编译选项的调优当作一个独立的测试项而不是藏在“构建部署”这种任务里面悄悄做完就忘了。3. 性能挖潜的核心路径从“代码能跑”到“跑得痛快”的四个发力点兼容层的问题解决后我们开始系统性地做性能优化。这段时间我们总结了四个发力点按投入产出比排序数据库访问层、缓存与序列化策略、线程模型与并发控制、JVM/操作系统参数的协同调整。一个一个展开说。3.1 数据库访问层驱动、方言、连接池、SQL四个维度一起调数据库是整个系统里替换风险最高的部分。我们原系统使用Oracle迁移到达梦数据库后最大的一个坑就是JDBC驱动和方言配置。很多团队做完数据迁移之后代码里还留着Oracle专用的一些写法比如SELECT ... FROM dual、NVL()函数、ROWNUM分页、CONNECT BY PRIOR层级查询等。达梦确实做了大量的Oracle兼容性适配以至于最初我们天真地以为不用改代码。但压测时发现某些在Oracle上跑得飞快的SQL在达梦上的执行计划就是不走索引。原因在于数据库的统计信息没有及时更新优化器基于空的统计信息选择了全表扫描。这里我提供一个标准化的处理流程供你们迁移时直接参考步骤操作内容常见问题与提醒数据迁移用达梦自带的DTS工具做数据同步大表分页抽取避免长事务锁库统计信息收集对所有业务表执行SP_TAB_STAT_INIT或DBMS_STATS.GATHER_TABLE_STATS这是最容易漏掉的一步漏掉后执行计划全乱方言层适配在ORM框架中切换dialect重写Oracle专有SQLMyBatis里的SQL需要逐个review连接池参数调整最大连接数、最小空闲数、连接超时时间信创环境下网络延迟偏高连接池参数不能照搬压测回归用原平台的录制流量回放对比关注慢SQL的Top榜变化连接池这一项特别值得提一下。原平台我们用的连接池最大连接数设为100在信创环境下CPU核数变多但每核频率下降数据库连接池如果还是100的话高并发下每个请求持有数据库连接的时间变长了实际并发能力反而下降。我们把最大连接数上调到150同时把maxWait从默认的30秒改为10秒把连接空闲回收时间从30分钟缩短到10分钟这样既提高了吞吐又避免连接膨胀拖垮数据库节点。3.2 缓存策略重构本地缓存和分布式缓存的比例重新配比在处理信创环境下的性能问题时我们很快就意识到一个事实CPU和内存的相对速度比例发生了变化。在传统X86平台上CPU足够快稍微多一点计算密集型逻辑也无所谓我们可以很奢侈地用分布式缓存扛压力。但在信创平台上一次分布式缓存的RTT往返时延虽然绝对值变化不大但因为CPU算力相对变弱等待缓存返回的时间就变得更加“奢侈”。于是我们把原本大量依赖Redis的访问路径做了分流对一致性要求极高、且更新频率低的数据比如配置类、字典类直接放到应用本地缓存Caffeine里设置合理的过期时间例如5分钟。对一致性要求较高、但读多写少的数据保留Redis分布式缓存同时在更新时通过消息队列主动失效本地缓存。对强一致性的数据不做任何缓存直接穿透到数据库。这个策略调整带来的效果比我们预想的要好。核心交易链路的平均响应时间从420ms直接降到了180ms左右其中大量耗时省在了“少一次网络RTT”上。但要提醒的是本地缓存一旦引入多实例之间的数据一致性就是一个新问题如果没有配套的消息失效机制慎用。序列化这一块也有优化空间。原来我们用Java原生的JDK序列化后来改成Kryo再后来针对高频小对象改成手工编码的二进制协议。每个环节都榨出了几个百分点积少成多。3.3 线程模型重构虚拟线程和协程带来的启发在信创环境下做高并发优化最容易遇到的一个问题是“线程池调参调到怀疑人生”。我们一开始在40个业务节点上做压测把线程池从200调到400、再从400调到800吞吐量不仅没有上涨反而出现了严重下降。分析后发现原因CPU核数有限线程切片的开销比实际业务计算还要高大量线程在等待数据库或者下游RPC的IO返回CPU的有效利用率极低。后来我们引入了一个IO密集场景专用的调度框架——quasar风格的轻量级线程协程。在Java 21的虚拟线程稳定之后我们又验证了一遍。结论是在信创环境中虚拟线程的收益比X86环境下更明显。原因很简单虚拟线程解决的是“线程阻塞时占着平台线程不放”的问题CPU变弱后传统线程阻塞的代价放大而虚拟线程挂起和恢复的开销极小等于把CPU的浪费给堵住了。当然虚拟线程也不是银弹。它会屏蔽掉你原本对线程池参数的控制力如果代码里有同步锁竞争或者阻塞式IO虚拟线程反而可能放大问题。所以我们的原则是核心交易链路用虚拟线程重写IO等待部分批量处理任务仍然使用传统线程池。3.4 JVM与操作系统参数的协同调整信创平台上的JVM除了常规的堆大小设置还要关注几个容易被忽视的参数。第一个是G1垃圾回收器的Region大小和并发线程数。我们发现默认配置下G1的并发标记线程数偏少导致高并发时Mixed GC停顿偏高。通过调整-XX:ConcGCThreads和-XX:ParallelGCThreads把GC的并行度提上来Full GC的次数从每小时几次降到几乎为零。第二个是内存分配策略。ARM平台上内存带宽相对有限-XX:UseNUMA这个参数就变得非常关键。如果你的服务器是多个物理CPU插槽的NUMA架构启用NUMA感知的内存分配后JVM会优先在本地节点分配内存跨节点访问延迟大幅下降。我们实测单接口响应时间又下降了5%左右。第三个是操作系统层面的CPU调度策略。麒麟系统的内核默认使用CFS完全公平调度器对于延迟敏感型业务可以考虑改用SCHED_FIFO配合taskset做CPU绑定。不过这个操作比较敏感需要在测试环境验证充分后再上线。我们只是对最核心的两个交易服务做了CPU亲和性绑定效果也很明显抖动次数减少了大概70%。# 路径规划示例: 给JVM进程绑定一组CPU核避免调度抖动 # 先查看进程PID jps -l # 再按需绑定比如绑定到CPU 4-7: taskset -pc 4-7 pid4. 全栈压测与性能验收建立自己的适配评估体系而不是信“厂商参数”整个优化过程中我们一直反复强调“以评测数据为准”。这个原则在执行层的落地就是一套我们自己搭建的分层压测体系。4.1 分层压测的四个阶段第一层是单组件压测。每个中间件数据库、缓存、消息队列单独压先拿到它们在信创环境下的性能基线数据。这样做的目的是把问题定位到“某个组件是否适配不正常”而不是笼统地说“整个系统慢”。第二层是链路压测。把核心交易链路的所有微服务串起来用生产环境的流量比例做回放。这里要用到流量的录制与回放工具我们选用的是自研的流量染色方案加上开源的录制回放框架在高并发下验证接口的响应时间和错误率。第三层是故障注入测试。当某个节点宕机或网络抖动时系统能否快速切换这决定了整个架构在信创环境下的高可用承诺是否成立。第四层是长稳测试。至少连续压测48小时观察内存泄漏、连接池溢出、慢SQL累积三类问题。很多性能问题在短期压测中不会暴露恰恰会在长稳阶段掉链子。4.2 发现性能瓶颈后的调优顺序我们在压测中反复用到的调优顺序如下先看监控大盘定位响应时间最长的Top5接口。对Top接口做链路追踪区分是CPU密集、IO密集还是锁竞争。如果是CPU密集用perf或者async-profiler抓取火焰图找到热点函数。如果是IO密集查数据库慢SQL和下游依赖的时延。修复之后重新压测记录前后对比数据形成调优闭环。这套流程讲起来平淡执行起来非常考验耐心。我们在优化过程中最大的收获不是某一项技术而是建立的这套**“问题追踪→数据支撑→回归验证”的工作方法**。4.3 整机联调中的“木桶效应”单组件优化完之后还有一个容易被忽视的环节——整机联调。特别是在信创整机服务器操作系统中间件数据库的集成环境中硬件板的固件设置、BIOS参数、RAID策略都会对最终性能产生影响。我们遇到过一个问题测试环境的磁盘性能极差每次刷数据库时总感觉IO卡顿。后来检查发现RAID卡写策略默认是Write Back写回模式但固件版本太老兼容性有问题导致实际落盘变成了Write Through写透模式。调整固件后磁盘IO能力直接翻了三倍。这个案例告诉我们信创环境下的性能优化不能只盯着应用代码底层固件、内核参数和外设策略都要纳入排查范围。5. 信创环境下的“云上改造”K8s迁移与分布式架构的额外一课现在大部分新系统都会跑在K8s容器平台上信创改造也不例外。当我们把微服务迁移到基于麒麟系统的K8s集群之后又遇到了一批新问题这里挑两个典型的讲。5.1 容器网络CNI的性能差异容器之间的通信在X86平台上常常用默认的桥接网络或者Overlay网络比如Calico性能损失在10%以内大多数业务可以接受。但在信创环境下因为CPU算力变弱Overlay网络的封包和解包开销比例被放大了两个服务之间的网络时延增加了将近一倍。我们最终把核心链路的Pod调度改为“亲和性调度”让调用量最大的几个服务优先调度到同一节点上并通过hostNetwork方式直通宿主机网络绕过了Overlay封装。同时把服务间的RPC调用改为基于gRPC的HTTP/2长连接减少频繁建连带来的CPU开销。5.2 分布式定时任务的调度重构原来的分布式任务调度平台用的是中心化的调度模式一个中心调度器扫描任务然后下发到执行器。这种模式在数据量上来后中心调度器的CPU和DB压力都很大。我们把调度策略改成分片模式让每个执行器基于数据库的行级租约自己抢占任务分片中心调度器只负责任务元数据的维护。这个改动让定时任务调度模块在信创环境下的吞吐量提升了近40%。关键是它的思路是通用的在CPU资源受限的环境下能够少一层中转就少一层中转能够并行处理就不要串行排队。5.3 上云时的镜像适配与构建加速容器镜像的构建也需要特别注意。由于ARM架构和X86架构的镜像不能共用我们需要为信创环境单独维护一套镜像仓库和CI流水线。如果你们的研发环境仍然跑在X86上最好采用交叉构建方案在CI中直接使用docker buildx配合QEMU模拟来产出ARM镜像。# 交叉构建ARM64镜像在X86构建机上运行 docker buildx create --name mybuilder --use docker buildx build --platform linux/arm64 \ -t registry.internal/myapp:arm64-latest --push .有个隐性成本不要忽视ARM构建环境下的依赖包下载源有些在国内不是很快最好在搭建镜像仓库时同步配置国内的ARM软件源镜像否则一次构建可能要卡在装包环节大半天。这种看起来不起眼的基建问题往往才是影响信创改造交付进度的元凶。6. 踩过的坑全记录这五个问题每一个都能拖垮整个交付周期最后把我们在信创全栈实践中遇到的最有价值的五个坑分享出来每一个都是拿时间换来的教训。6.1 字符集与排序规则不一致导致的“数据幽灵”数据迁移到信创数据库后出现过一批查询不到的数据。排查发现源库的字符集是AL32UTF8目标库设置成了GB18030某些生僻字在迁移时变成了乱码导致WHERE条件匹配不上。解决方法是迁移前统一字符集规划并且在迁移后用抽样对比脚本验证关键表的数据一致性。6.2 内存屏障与并发编程的“玄学崩溃”这个问题只在ARM平台上暴露。我们有一段无锁队列的实现在X86上跑了一年都没出过问题换到鲲鹏服务器后压测一到高并发就偶发死循环。用gdb挂上去看到线程卡在读状态字段的自旋上。原因在于ARM的内存模型比X86弱X86因为有较强的存储一致性读操作几乎不会重排ARM则可能看到旧值。解决方案是给状态字段的读写加上atomic_thread_fence(memory_order_seq_cst)同时在自旋等待时加入std::this_thread::yield()问题彻底消失。6.3 中间件的高可用不再是“主从切换”而是“脑裂”难题信创环境中一些开源的中间件高可用方案在网络抖动时更容易出现脑裂情况。我们曾经在某消息队列集群上遇到过两个节点同时认为自己是主节点的严重故障。这里给的建议是引入类似哨兵或Raft共识的解决方案时务必要仔细打磨网络分区容忍参数不能拿原来的老经验直接套。6.4 安全合规检查中的“性能拦路虎”信创项目通常伴随等保合规要求需要在业务链路上增加加密传输、审计日志、数据脱敏等能力。这些组件如果实现得比较“重”叠加在性能本就不宽裕的信创链路上会造成明显的额外损耗。我们的经验是对加密算法做硬件加速适配例如使用国产芯片内置的加速指令或SDF接口而不是全部走软件加密库同时审计日志改采样写入异步清洗性能和合规都兼顾。6.5 厂商支持给不了你的“代码级诊断”最后一坑也是最容易踩的出了问题不要只会找厂商。信创软硬件厂商很多适配文档和工具链成熟度参差不齐。我们最有的效的诊断手段始终是自己完整监控体系包括Metrics、Tracing和Logging三件套。没有这三件套你在信创环境里排查问题就像是蒙着眼睛开车。具体来说我们基于SkyWalking扩展了一套针对国产组件Trace解析的方案在核心服务里接入OpenTelemetry的SDK把每一次数据库访问、缓存访问、消息发送都作为Span记录下来。这样即使是没有源码的第三方组件也能从调用链上定位到是哪一段耗时异常。写在最后性能最优不是一个终点而是一种评估习惯回看整个信创架构深度重构的过程我最大的体会是信创替代中最难的从来不是“装上能跑”而是“像打磨自己的系统一样去打磨信创环境下的每一环性能”。很多项目把“信创适配及安全管理赛项”或“信创安全工程师投标”当作交付目标而实际业务部门要的是“信创替代后还能保持甚至超越原有体验”。不在兼容适配之上做性能挖潜这个目标就永远是一座空中楼阁。如果你现在正准备启动一个信创重构项目我建议你把这篇文章里的内容作为一张检查清单指令集编译选项有没有针对性调优数据库统计信息是否收集完整连接池参数是否重新测算过GC和NUMA有没有调过容器网络是否直通全链路压测是否覆盖了故障注入与长稳如果这些问题的答案都是“是”那么你的信创系统才有资格谈“性能最优”。最后再分享一个我们内部沉淀的小技巧在每次性能优化后把结果记录成一篇简短的技术备注附上压测数据和火焰图截图存到团队知识库里。这不仅能帮后来人少踩坑也会成为你们团队在信创领域最宝贵的技术资产。