低代码平台高并发实战:从单机压测到集群扩容的完整指南
2026/9/16 19:27:47 网站建设 项目流程

低代码平台能不能扛高并发,这个问题我最近两年被问了不下二十次。尤其是活字格,很多人一听说“低代码开发”,第一反应就是:这东西做点内部小系统行,上生产、扛并发?悬。

我倒觉得,与其迷信或者唱衰,不如把话说清楚。低代码平台的高并发能力,从来不取决于“低代码”这三个字,而取决于它底层的运行机制、资源模型和你能做的架构设计。活字格这批企业级低代码平台,早就不停留在表单+报表的层面,它的服务端命令、计划任务、外部数据库连接、Redis会话缓存、IIS多实例部署这些能力,本质上已经和传统开发没什么区别。你用好了,它扛得住正经的业务流量;用不好,那确实谁来都白搭。

这篇文章我不讲广告,只从技术角度聊三件事:活字格到底凭什么扛并发、压测数据能到什么水平、以及从小单机到大集群,扩容这条路怎么一步步走。内容比较多,建议收藏了慢慢看。

1. 先泼冷水:低代码平台的“高并发恐惧症”到底哪来的

1.1 大多数吐槽来自“把低代码当万能钥匙”的误用

我见过很多对低代码平台性能不满的案例,最后排查下来,真正的问题几乎都出在同一个地方:开发方式没有跟着平台的特性走。

比如有人在活字格里做了一个单据录入页面,一次性把一年的订单数据全查出来,逐行绑定到表格控件上。数据量一旦过万,页面直接卡死。然后他就得出一个结论:低代码不行,扛不住量。问题是这个数据模型放传统后端开发里,也一样会被DBA骂“没分页就敢往页面上怼数据”。

低代码平台的性能口碑差,很大程度是被这种误用毁掉的。平台给了你快速搭界面的能力,但没有告诉你什么时候该用页面端表格、什么时候该用服务端命令、什么时候该走存储过程。如果你完全无视数据访问模式,用“拖控件”的思维去搞一个高并发交易系统,那大概率是灾难。

所以先达成共识:讨论低代码扛不扛高并发,前提是使用方式是合理的,不是拿低代码的生搬硬套去挑战无限流量。拿合理用法去测试,后面的数据才有参考意义。

1.2 低代码高并发能力的本质:它到底在跑什么

聊性能之前得先弄明白活字格这类平台的运行时模型。很多人以为活字格就是个“代码生成器”,生成的页面和逻辑都是黑盒,性能不可控。实际上活字格的架构和传统Web应用没有本质区别,我简单拆一下:

层次活字格对应组件类比传统开发
前端页面页面和单元格绑定的HTML渲染服务端渲染 + 前端框架
业务逻辑服务端命令、计划任务、工作流后端服务中的业务接口
数据访问内置数据表、外部数据库连接ORM + SQL
运行环境Windows服务器上的IIS应用IIS/ASP.NET应用
并发状态用户会话、角色权限、数据行锁Session、权限、事务控制

这意味着你的高并发能力天花板,主要取决于 I/O链路和资源消耗模式,而不是“低代码”这个外衣。活字格本身在服务端会做页面渲染、执行服务端命令、访问数据库。你要优化的就是这三段的性能。

其次要分清一个关键概念:用于交互的动态请求用于展示的静态资源,是两种完全不同的压力。低代码平台里,页面本身的加载开销往往不是最大瓶颈,真正压垮系统的是频繁的数据库交互和未优化的服务端循环。理解了这一点,后面所有的优化动作都会围绕“减少数据库往返、降低服务端重复计算、把压力异步化”展开。

2. 活字格的性能设计:从页面渲染到数据库访问

2.1 页面层:服务端渲染与静态化缓存

活字格的页面默认是服务端渲染的。也就是说,用户请求一个页面时,服务器会把页面需要的HTML结构、数据绑定、单元格逻辑在服务端组装完成,再把结果推给浏览器。这和传统的ASP.NET WebForms有相似之处,好处是浏览器端不需要加载庞大的前端框架包,首屏渲染快;代价是每个页面请求都会消耗CPU和内存来执行渲染逻辑。

所以页面层的性能关键点就很清晰了:缓存。

活字格专门提供了页面缓存的设置项,开启后服务端会把渲染完成的页面HTML缓存到内存中。用户再次访问同一页面时,服务端直接返回缓存副本,不再重复执行页面渲染。这里我要特别强调一个使用细节:开启页面缓存前,务必检查页面上有没有“每次进入页面都必须刷新”的动态数据区。如果有,你需要把动态数据放到服务端命令去拉取,或者拆成子页面延迟加载,否则用户看到的永远是缓存里的旧数据,那就得不偿失了。

另外一个常被忽略的点是静态资源(JS、CSS、图片)的加载。活字格工程在发布时可以把这些静态资源做压缩和合并,配合部署前置的Nginx或CDN,前端静态资源的加载压力基本不需要应用服务器操心。压测时你会发现,静态资源在缓存命中之后,对服务器的资源占用几乎可以忽略不计。

2.2 数据库层:连接池、索引与并发控制策略

数据库永远是低代码平台高并发道路上最先撞上的墙。活字格支持内置数据库(默认是SQLite或SqlServer Compact风格的轻量库,通常用于开发环境)和外部数据库(SQL Server、MySQL、Oracle、PostgreSQL),生产环境建议直接使用外部数据库。为什么?因为内置数据库面对高并发写操作时,性能和并发控制能力都远不如企业级数据库,这不是活字格的问题,是数据库引擎本身的定位差异。

连接池是活的,不会每来一个请求就新建一个数据库连接,池子里的连接是复用的。但连接池大小是有限度的,默认情况和数据库最大连接数相关。压测到了一定并发数,你会在日志里看到类似“connection timeout”的错误,这就是连接池被打满了。解决思路不是无限调大池子,而是先从SQL入手,把慢查询干掉,让每个连接占用时间更短,这样池子里有限的连接能服务更多请求。如果SQL已经优化到极致仍然扛不住,再考虑扩容数据库实例。

活字格在数据更新时默认会带上并发控制机制。简单说,如果两个用户同时编辑同一条记录,后提交的人会收到“数据已被他人修改”的提示,而不是静默覆盖。这是企业级系统必须具备的能力,但很多人感受不到它的存在。代价是:更新操作需要多携带版本信息(通常是一个版本号字段)用于比对,这比无脑更新多一次判断,但对数据正确性来说完全值得。

2.3 服务端命令与计划任务:把压力从客户端挪走

如果说数据库是低代码性能的墙,那么服务端命令就是撞墙前最后的缓冲。

我建议所有涉及复杂逻辑的操作都放到服务端命令里执行,而不是在前端用命令拼接一堆逻辑。原因有三:第一,服务端命令直接运行在服务器上,和数据库之间的网络延迟可以忽略不计;第二,服务端命令可以被日志记录、被性能监控、被权限校验覆盖,出了问题好排查;第三,服务端命令内部支持调用SQL、存储过程、外部API,你可以把最吃性能的数据操作完全下沉到数据库层。

计划任务则解决“高峰时段同步处理”的问题。比如批量生成报表、批量推送通知、定时汇总数据,这些任务放在请求链路里执行,会瞬间抬高响应时间。改成计划任务(比如每隔5分钟跑一次)之后,高峰期的请求链路里就少掉了所有重计算逻辑,系统的吞吐量会明显上升。

提示:服务端命令里如果有循环,务必检查循环里是否有数据库访问。一个循环里套一个SQL查询,循环100次就是100次数据库往返。这种问题在传统开发里会被人打,在低代码里也常见。优化办法是改成一次查出所有数据再到内存里循环,或者直接用SQL的JOIN在数据库层面算完。

3. 实战压测:活字格在常见配置下到底能抗多少

3.1 测试环境与压测方法

纸上谈兵没意思,直接上一组我这边实际压测过的数据。先声明:这个测试环境不代表活字格的上限,只是给大家一个数量级参考。用的是两年前的服务器,放到今天属于中低配。

配置项参数
应用服务器4核8G,Windows Server 2019,活字格单实例
数据库服务器4核8G,SQL Server 2019,与Web应用分离
测试工具JMeter,模拟300并发线程
测试场景用户登录后查询订单列表(分页加载50条),提交一条新增单据
数据量订单表50万行

压测脚本模拟真实用户行为,每轮操作包含一次登录、一次查询、一次新增提交。持续压测30分钟。

3.2 压测结果与瓶颈分析

对页面开启了页面缓存,查询走的是分页加载,新增单走服务端命令。

指标结果
吞吐量约 980 请求/分钟(TPS约16.3)
平均响应时间查询约320ms,新增提交约650ms
99%响应时间查询约1.2s,新增提交约2.1s
应用服务器CPU平均55%-70%
数据库服务器CPU平均35%-45%,查询高峰时到过75%

16的TPS看起来不高?别急,这是单实例4核小机器,而且包含登录(每次登录都涉及密码哈希比对和权限加载)和写入操作,不是纯读接口。这个数据说明两件事:一是在合理的分页、缓存、服务端命令组合下,活字格跑起来没有明显资源瓶颈;二是当CPU到达70%以上时,继续加并发只会让响应时间线性恶化,这时候就该扩容了。

压测过程中我特意观察了数据库侧的慢查询日志。响应时间超过1秒的SQL,几乎都集中在没有索引的大表查询上。给订单表的“单据编号”“客户ID”“创建时间”几个常用查询字段补上索引后,查询的响应时间直接从800ms降到了120ms左右。这个优化在低代码平台里一样见效,因为最终执行的还是SQL。

3.3 定位慢请求的三个步骤

压测或者生产环境里,当你觉得系统“变慢了”,第一步不是加机器,而是先定位慢请求到底慢在哪。我的习惯是三步走:

  1. 看活字格的服务端日志和性能请求日志。活字格发布后有个查看服务器日志的功能,能看到每个请求的耗时详情。先按耗时倒序排,看看最慢的Top10请求是哪些页面或命令。
  2. 根据日志里记录的执行时间,判断瓶颈在渲染层还是在数据库层。如果页面渲染耗时长,考虑页面缓存和静态资源优化;如果数据库查询耗时长,把对应的SQL抓到数据库中执行,看执行计划。
  3. 从数据库层面看行数估算和索引命中情况,做针对性优化。这里需要说明一下,活字格查询页面时,可以主动开启数据库的SQL Profiler或开启数据库的慢日志,这样能直观看到活字格生成的SQL语句。

注意:上线前在开发环境用真实数据量的1/10去压测,意义不大。很多低代码项目线上出问题的原因都是:开发环境几十行数据跑得飞快,生产环境几百万行数据直接超时。所以测试库一定不要用“演示数据”,要想办法导入接近真实量级的数据。

4. 扩容设计:从小单机到大集群的演进路径

4.1 垂直扩容:先把单机榨干

很多人一上来就考虑上集群,我建议先冷静。大多数企业级项目,并发量在几百人以内,单机先用足再说。

单机优化有一个优先级:应用服务器的CPU和内存是最容易解决的,51job上随便加个配置就翻倍;但数据库磁盘I/O往往才是短板。所以单机扩容时,优先把数据库放到SSD上,再把数据库服务器和应用服务器分开部署,消除两者之间的资源竞争。这一步做完,往往就能解决70%的性能焦虑。

活字格部署在IIS上,Windows服务器本身的TCP/IP参数、IIS的应用池回收策略,也会影响性能表现。我建议在生产环境把IIS应用池的“闲置超时”调大,避免长时间没请求时应用池被回收,导致下一个请求要重新编译页面,出现“第一次访问特别慢”的现象。

4.2 水平扩容:IIS多实例与负载均衡

单机配置加到头了,就要考虑横向加机器了。活字格部署在IIS上,天然支持多实例部署:你可以在两台(或多台)服务器上各发布一个相同的应用,然后前置一个负载均衡设备(Nginx、F5、阿里云SLB都行)分发流量。

这里有一个关键前提:保持应用节点无状态。活字格默认的会话信息是存在服务器内存里的,如果用户第一次请求落在A节点,第二次请求被负载均衡转发到B节点,B节点没有用户的会话数据,用户就会被强制退出登录。解决办法是启用会话状态的外部存储,活字格支持把会话存到Redis里。这样所有节点共享同一个会话状态池,任何一个节点处理请求都能读到用户的登录状态,水平扩容才有意义。

配置完多实例之后,需要一个简单的健康检查机制。负载均衡器要能识别某个节点是否宕机,比如通过HTTP探测某个固定页面,连续失败就把节点摘掉,等恢复后再加回来。这块配置必须提前演练,不要等到大规模宕机了才去研究。

4.3 缓存与队列:给数据库“卸压”

多实例部署后,应用服务器的瓶颈往往还在数据库。这时候最有效的两招是缓存和消息队列。

缓存方面,热点数据(比如字典数据、基础资料、商品信息)放到Redis里。活字格的服务端命令可以直接调用Redis的API,把查询结果缓存起来,设置过期时间。同一个针对基础数据的查询,在缓存命中的情况下,对数据库的请求量能减少80%以上。

队列方面,凡是“用户操作后不需要立刻拿到结果”的操作,都值得异步化。举个实际例子:一个单据提交后,需要做流程通知、生成台账、推送消息三个操作。如果同步执行,用户提交一次要等三个下游系统都响应完才看到成功提示。如果改成熟练的异步方案:提交单据成功后,把消息发到消息队列里,后台通过计划任务或者独立worker去消费队列处理后续操作,用户响应时间从2秒降到几百毫秒,数据库压力也明显下降。

提示:活字格和消息队列整合时,建议用服务端命令封装消息发送逻辑。这样页面端调用的是业务动作,而不是直接接触MQ,后续如果替换消息中间件,只需改服务端命令的实现,页面不用动。

4.4 读写分离与数据库层扩展

流量再往上走,单库扛不住写并发的时候,就要动数据库架构了。

最实用的是读写分离:数据库做一主一从(或者一主多从),主库负责增删改操作,从库负责查询操作。活字格允许你配置多个数据库连接,查询场景连接从库,写入场景连接主库,等于应用层直接做路由,不需要引入额外的中间件。

但要注意,读写分离有一个潜在坑:主从同步延迟。如果用户刚提交了一条数据,立刻查询却连接从库,从库还没有同步过来,用户会以为提交失败了。常见的规避办法是:写入后紧接着的这一次查询强制走主库,或者对一致性要求非常高的数据不做读写分离,保持读写同源。

再往上是分库分表和分布式数据库,这个对大多数低代码项目来说已经超纲了。如果真到了这个量级,通常的做法是:把最核心的高频业务从低代码平台中抽出(比如做成专门的服务),低代码平台继续负责长尾业务和管理后台,两者之间通过API互通。这不是拆低代码平台的台,而是合理分工。工具再强,也不可能在每一层都做到最优,该上专用方案的地方就得果断上。

5. 避坑指南:低代码高并发的五个常见误区

5.1 忽略页面数据量控制,把数据库当缓存用

这个问题在低代码开发里太常见了。一个页面加载几万行数据到表格里,用户根本看不过来,却把数据库的查询、传输、渲染全部拖慢。活字格内置的表格控件本身支持分页和按需加载,但很多开发者习惯了Excel思维,总想“一次都查出来再用筛选器过滤”。

正确的做法是:页面上只展示当前屏幕能看到的量,比如每页50行或100行,用户翻页或者搜索时再向后端请求新的数据。如果业务上确实需要看汇总信息,在服务端命令里做聚合,只把汇总结果传给页面。把这个习惯养成,系统的性能起点会高很多。

5.2 权限系统设计不当,每个请求都变成“全表扫描”

活字格内置了用户、角色、组织结构的权限模型,数据库每一行数据都可以通过创建人、负责人来做行级权限控制。这个功能很好用,但如果你的行权限配置里包含了非常复杂的判断逻辑(比如根据部门、职级、区域动态匹配),那数据库查询时很难走索引,甚至会退化成全表扫描。

带上权限条件查询大表,是分布式环境里最难优化的一种场景。我的建议是:高频列表页面的行级权限尽量简单化,比如只按一个固定的“数据归属部门”字段过滤,并给这个字段建索引;如果业务上需要非常复杂的权限矩阵,考虑把查询和对数据的权限判断拆成两步,在内存中执行权限过滤,避免数据库层面承担过多负担。

5.3 页面缓存和实时数据不分家,上线后“缓存混乱”

前面说页面缓存能显著提升性能,但缓存和实时性是一对矛盾。

我碰到过一个项目,一个库存查询页面开了页面缓存,结果库存数据是不断变化的,用户看到的却始终是缓存里的旧库存,等到仓库发货发了超了才被发现。问题不在缓存,而在于页面设计时没有区分哪些区域是静态的、哪些是动态的。

使用页面缓存的正确姿势是:页面框架、菜单、基础资料区这种很少变化的区域可以缓存;实时变化的业务数据区,不要放在缓存里,而是放在页面加载后通过服务端命令异步刷新。这样既保留了缓存的高性能,又保证了业务数据的准确性。

5.4 服务端命令里塞进大量循环和外部接口调用

服务端命令虽然能处理复杂逻辑,但不能把什么逻辑都往里塞。很多人在服务端命令里循环调用外部API,比如拼一个1000条数据的列表,循环里给每条数据调用一次第三方接口,结果接口响应一慢,整体请求就超时了。

正确的做法是批量调用。第三方接口支持批量就尽量批量提交;不支持批量就考虑并发请求,同时控制并发度,不要跑满全部资源。更重要的是,外部依赖的不确定性(第三方接口偶尔超时)不应该直接暴露在用户请求链路上。能异步处理就异步处理,不能异步的就做好超时控制和降级方案(比如失败先返回提示,后台重试)。

5.5 生产环境开着详细日志,磁盘把应用拖死

最后这个坑很简单但很多人踩:生产环境为了排查问题,把日志级别调成了“详细”或“TRACE”,并且没有设置日志滚动删除。业务量一大,日志文件以GB级增长,磁盘被占满,应用直接宕机。

日志是用来给生产环境兜底的,不是用来记录所有细节的。生产环境保持“警告”级别以上日志,只在排查特定问题时临时调成“调试”级别,定位完成立刻改回。同时,在服务器上定期清除历史日志文件,或者让日志按天输出并自动清理,避免日志文件把磁盘吃满。

写在最后的几点体会

如果你问我“活字格到底能不能扛企业级高并发”,我的答案是:在合理架构设计和基础设施配套的前提下,它能扛住绝大多数企业级业务的真实流量。低代码平台降低的是开发门槛,不是性能上限;但它也不会替你解决所有架构问题,这一点和传统开发并没有区别。

我自己在项目中的体会是:用活字格开发时,始终要把“数据链路”放在心里。页面怎么加载、服务端命令怎么组合、数据库查询怎么走索引、缓存和队列怎么接入,这些决策最终决定了系统能跑多远。低代码只是把你从大量重复的页面代码中解脱出来,让你有更多精力去思考真正的性能瓶颈在哪里。

最后再分享一个小技巧:无论你的系统现在规模多大,上线前一定把压测环境搭起来。不需要很复杂,一台测试服务器、JMeter、一份接近真实的业务数据,跑一天就能找出大部分性能隐患。比起线上出问题再去救火,这投入的性价比高太多了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询