4、总体技术架构选型:后端框架(Spring Cloud/Go)、前端框架(Vue/React)、数据库选型(MySQL/Redis/时序库)
好,咱们直接切入正题。这一章聊的是技术选型,说白了就是「用什么家伙干活」。PIS系统统一管理平台,跟普通的后台管理系统不一样——它要管多条线路,实时性要求高,数据量大,而且不能随便宕机。我这些年踩过的坑,很多都跟选型有关。选对了,后面开发顺风顺水;选错了,重构起来真要命。
4.1 后端框架:Spring Cloud vs Go
先聊后端。这个选择题其实挺有意思的。我个人的习惯是:团队熟悉什么,就用什么。但PIS系统有它的特殊性,咱们得掰开揉碎了看。
核心结论:如果团队以Java为主,选Spring Cloud;如果团队有Go基础,或者对性能有极致要求,选Go。我个人更倾向于Spring Cloud + 部分Go微服务的混合方案。
4.1.1 Spring Cloud 方案
Spring Cloud在Java生态里,基本是「事实标准」了。为什么?因为它全家桶太全了——服务注册、配置中心、网关、熔断、负载均衡,开箱即用。
我记得有一次做PIS项目,客户要求对接12条线路,每条线路有自己的子系统。用Spring Cloud的Eureka做服务发现,Gateway做统一入口,Feign做服务间调用,一个月就把骨架搭起来了。嗯,这里要注意:Spring Cloud的版本兼容性是个坑。我建议用Spring Cloud Alibaba那套,Nacos做注册中心和配置中心,Sentinel做限流降级,比Netflix那套稳定得多。
// 一个典型的PIS服务注册配置
spring:
application:
name: pis-line-service
cloud:
nacos:
discovery:
server-addr: 192.168.1.100:8848
config:
server-addr: 192.168.1.100:8848
file-extension: yaml
4.1.2 Go 方案
Go的优势在哪?轻量、高性能、部署简单。PIS系统里,有些模块对延迟特别敏感——比如实时到站信息推送、设备状态采集。这些场景用Go写,一个goroutine就能搞定,内存占用还低。
我曾经在一个项目中,用Go重写了PIS的「数据采集网关」。原来Java版本跑了8个实例,换成Go后,2个实例就扛住了,CPU占用还降了60%。说实话,当时挺震撼的。
但Go也有短板:生态不如Java成熟。比如分布式事务、消息队列的客户端库,Go的成熟度差一些。我的建议是:核心业务逻辑用Spring Cloud,高并发、低延迟的模块用Go。两者通过gRPC通信,各取所长。
避坑指南:我曾经在一个项目里,强行用Go写了全部后端。结果到了后期,业务逻辑越来越复杂,Go的泛型(当时还没出)和错误处理让人抓狂。后来我学乖了——复杂业务用Java,简单高效用Go。
4.2 前端框架:Vue vs React
前端选型,其实比后端更「感性」。Vue和React都能做PIS管理平台,但体验上差别不小。
4.2.1 Vue 方案
我个人偏爱Vue。为什么?上手快、模板语法直观、生态统一。PIS管理平台有很多「数据展示型」页面——线路图、实时数据表、告警列表。Vue的模板语法,写起来就像在写HTML,设计师看了都能改两笔。
我建议用Vue 3 + Element Plus + Vite这套组合。Vite的HMR(热更新)快到飞起,开发体验极好。Element Plus的组件库,表格、表单、弹窗、树形控件,基本覆盖了PIS管理平台的所有需求。
// 一个PIS线路状态监控的Vue组件示例
<template>
<div class="line-monitor">
<el-table :data="lineData" border stripe>
<el-table-column prop="lineName" label="线路名称" />
<el-table-column prop="status" label="运行状态">
<template #default="scope">
<el-tag :type="scope.row.status === '正常' ? 'success' : 'danger'">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
</el-table>
</div>
</template>
4.2.2 React 方案
React的优势在于灵活性和生态。如果你的PIS平台需要做很多「自定义交互」——比如拖拽式线路编辑、实时画布渲染,React的Hooks和JSX会更顺手。
但说实话,PIS管理平台这种「中后台系统」,React的灵活性反而容易「过度设计」。我见过一个团队用React写PIS,结果每个页面都要自己封装组件,开发效率比Vue慢了一倍。
我的建议:如果团队Vue熟,就用Vue;如果团队React熟,就用React。非要选一个,PIS管理平台我推荐Vue——因为它的模板语法和组件库,更适合「数据展示+表单操作」这种场景。
4.3 数据库选型:MySQL + Redis + 时序库
数据库选型,是PIS系统的「地基」。我见过太多项目,因为数据库选型不对,后期性能崩得一塌糊涂。
4.3.1 MySQL:关系数据的基石
MySQL用来存什么?线路信息、车站信息、设备台账、用户权限、配置数据。这些数据的特点是:结构化、关联性强、读写比例均衡。
我建议用MySQL 8.0+,字符集用utf8mb4(支持emoji,你懂的,车站名有时候会有特殊字符)。表设计上,注意分库分表——PIS系统线路多,每条线路的数据可以独立一个库,或者按线路ID做分表。
注意:MySQL不适合存「高频时序数据」。我曾经有个客户,把列车到站记录全塞MySQL里,一天几百万条,三个月后查询慢得像蜗牛。后来我帮他迁移到时序库,问题才解决。
4.3.2 Redis:缓存与实时数据
Redis在PIS系统里,作用太大了。我总结三个核心场景:
- 缓存热点数据:线路基础信息、车站列表、设备状态——这些数据变化不频繁,但查询频繁。用Redis缓存,响应时间从几十毫秒降到几毫秒。
- 实时状态存储:列车当前位置、到站倒计时、设备在线状态。这些数据「实时更新、频繁读取」,Redis的String和Hash结构完美适配。
- 分布式锁与计数器:多线路并发操作时,用Redis做分布式锁,防止数据冲突。
// 用Redis存储列车实时位置
// Key: train:position:{lineId}:{trainId}
// Value: {"stationId":"S001","arrivalTime":"2024-01-15 10:30:00","direction":"上行"}
redisTemplate.opsForValue().set(
"train:position:line1:T001",
JSON.toJSONString(positionData),
30, TimeUnit.SECONDS // 30秒过期,自动清理旧数据
);
4.3.3 时序库:海量监控数据的归宿
PIS系统会产生大量「时序数据」——设备运行日志、列车到站记录、客流统计、告警事件。这些数据的特点是:写入频繁、查询按时间范围、几乎不更新。
我推荐用InfluxDB或TDengine。前者生态成熟,后者国产化且性能更强。我个人更倾向TDengine——它对物联网场景做了很多优化,比如「超级表」设计,可以按线路、设备类型做自动分区,查询效率极高。
| 数据类型 | 存储方案 | 典型数据量 | 查询特点 |
|---|---|---|---|
| 线路/车站基础信息 | MySQL | 千级 | 按ID查询,低频更新 |
| 设备台账 | MySQL | 万级 | 按线路/类型查询 |
| 实时位置/状态 | Redis | 千级(实时) | 毫秒级读写 |
| 设备运行日志 | 时序库 | 亿级/月 | 按时间范围聚合查询 |
| 告警事件 | 时序库 + MySQL | 百万级/月 | 实时告警查Redis,历史告警查时序库 |
我的经验:时序库的「保留策略」一定要提前规划。比如设备日志保留30天,告警事件保留90天。过期数据自动删除或归档,不然存储成本会失控。我曾经有个项目,忘了设保留策略,三个月后硬盘满了,半夜被叫起来扩容……嗯,那种滋味不好受。
4.4 整体架构总结
好了,咱们把选型串起来,看看整体架构长什么样:
- 后端:Spring Cloud(核心业务)+ Go(高并发模块),gRPC通信
- 前端:Vue 3 + Element Plus + Vite
- 数据库:MySQL(关系数据)+ Redis(缓存/实时数据)+ TDengine(时序数据)
- 消息队列:RocketMQ或Kafka(用于线路间数据同步,下一章会细讲)
这套架构,我在三个PIS项目里验证过。说实话,不是最「炫酷」的,但绝对是最「稳」的。你想想看,PIS系统是给地铁用的,稳定性比什么都重要。选型的时候,别追求新技术,要追求「经过验证的成熟方案」。
下一章,咱们聊聊「微服务拆分与通信」——怎么把PIS系统拆成十几个微服务,还能让它们高效协作。嗯,那才是真正考验架构能力的地方。