1. 项目概述:疫情防控隔离调度系统的核心价值
2020年以来的全球公共卫生事件让疫情防控系统成为刚需,我去年为某三甲医院开发的隔离调度系统上线后,日均处理300+人员转运任务,将调度效率提升40%。这个基于SpringBoot的Java系统核心解决三个痛点:隔离人员信息混乱、转运资源分配不均、各部门协同效率低下。
传统Excel表格管理方式在疫情爆发期会出现数据不同步、权限混乱等问题。我们采用B/S架构实现多终端实时协同,通过智能算法自动匹配隔离点床位资源与转运车辆,系统包含六大模块:人员信息登记、隔离点管理、转运调度、物资调配、数据看板和消息通知。下面结合我的实战经验,详解如何从零构建这样一个企业级应用。
2. 技术选型与架构设计
2.1 为什么选择SpringBoot+MySQL组合
在技术选型阶段我们对比了三种方案:
- PHP+Laravel:开发快但性能瓶颈明显
- Python+Django:适合快速原型但并发处理弱
- SpringBoot+MySQL:最终选择方案
SpringBoot的自动配置特性让开发效率提升显著,比如:
- 内置Tomcat省去服务器配置
- starter依赖一键集成MyBatis、Redis等
- Actuator提供完善的健康监控
MySQL选用5.7版本而非8.0,主要考虑:
- 医院IT环境多为CentOS7,对MySQL8支持不完善
- 5.7的JSON字段已满足业务需求
- 更稳定的分区表性能
重要提示:生产环境务必配置主从复制,我们吃过单点故障的亏。建议至少1主2从,采用GTID复制模式。
2.2 微服务还是单体架构?
初期考虑过微服务架构,但评估后选择适度拆分的单体架构,原因如下:
- 团队规模:3人开发团队维护多个服务成本高
- 事务需求:跨服务的分布式事务会大幅增加复杂度
- 部署环境:医院私有云资源有限
架构分层设计:
com.epidemic ├── config # 配置类 ├── controller # 表现层 ├── service # 业务逻辑 │ ├── impl # 实现类 ├── dao # 数据访问 ├── entity # 实体类 ├── util # 工具包 └── task # 定时任务3. 核心功能实现细节
3.1 人员信息登记模块
采用分级录入机制:
- 社区人员:自助填写基础信息
- 医护人员:补充医学观察数据
- 管理员:审核并分配隔离点
关键代码示例(MyBatis动态SQL):
@Select("<script>" + "SELECT * FROM person_info " + "<where>" + " <if test='name != null'>AND name LIKE CONCAT('%',#{name},'%')</if>" + " <if test='status != null'>AND status = #{status}</if>" + "</where>" + "ORDER BY create_time DESC" + "</script>") List<Person> queryByCondition(@Param("name") String name, @Param("status") Integer status);避坑经验:
- 身份证号字段用varchar(18)并添加唯一索引
- 医学观察记录用JSON格式存储,方便扩展字段
- 批量导入时使用MyBatis的BatchExecutor
3.2 智能调度算法实现
核心调度逻辑包含四个步骤:
- 需求分析:解析隔离人员属性(是否确诊、是否有基础病等)
- 资源匹配:根据隔离点剩余床位、医疗等级匹配
- 路径规划:高德API获取实时路况计算最优路径
- 冲突检测:防止同一车辆时段冲突
调度算法伪代码:
function schedule(person, transportList): // 优先级计算 priority = calculatePriority(person.healthStatus) // 过滤可用车辆 availableTransports = filterByTimeWindow(transportList) // 最优匹配 bestMatch = null for transport in availableTransports: if checkCapacity(transport) and checkEquipment(transport, person): bestMatch = transport break return new ScheduleResult(person, bestMatch, priority)性能优化点:使用Redis缓存隔离点实时床位数据,更新策略采用旁路缓存模式。
4. 典型问题排查实录
4.1 并发更新导致的库存超卖
现象:同一隔离点被多次分配 解决方案:
@Transactional public boolean assignBed(Long isolationId, Long personId) { // 使用SELECT FOR UPDATE加行锁 IsolationPoint point = isolationMapper.selectForUpdate(isolationId); if (point.getAvailableBeds() > 0) { point.setAvailableBeds(point.getAvailableBeds() - 1); isolationMapper.updateById(point); // 记录分配关系... return true; } return false; }4.2 高并发下的系统响应延迟
优化措施:
- Nginx配置负载均衡 + 静态资源缓存
- 热点数据使用Redis集群缓存
- MySQL查询优化:
- 添加复合索引:(status, create_time)
- 大表分库分表(按地区分片)
4.3 微信通知发送失败
排查发现医院网络限制第三方API调用,最终方案:
- 搭建内网消息中转服务
- 采用异步队列重试机制
- 增加备用通道(短信+邮件)
5. 部署与监控方案
5.1 生产环境部署清单
| 组件 | 版本 | 配置要求 |
|---|---|---|
| JDK | 1.8 | 服务器内存≥8G |
| MySQL | 5.7 | SSD磁盘 |
| Redis | 6.2 | 哨兵模式部署 |
| Nginx | 1.18 | 开启gzip压缩 |
5.2 监控指标配置
- SpringBoot Actuator暴露/metrics端点
- Prometheus采集关键指标:
- JVM内存使用率
- 数据库连接池活跃数
- 接口响应时间P99
- Grafana监控看板配置示例:
sum(rate(http_server_requests_seconds_count{uri=~"/api/.*"}[1m])) by (uri)
6. 扩展优化方向
- 接入健康码系统:通过OpenAPI实现状态同步
- 增加BI分析模块:使用ECharts展示疫情热力图
- 移动端优化:基于Uniapp开发跨平台应用
- 应急演练模式:模拟大规模疫情爆发时的压力测试
这个项目让我深刻体会到,好的业务系统需要平衡技术先进性与落地可行性。比如最初设计的复杂分布式架构最终简化为适度解耦的单体应用,反而提升了交付效率。如果重新设计,我会更注重:
- 初期建立完善的埋点体系
- 采用领域驱动设计划分限界上下文
- 编写更全面的集成测试用例
最后分享一个调度系统特有的优化技巧:在车辆路径规划时,将"司机熟悉度"作为权重因子加入算法(老司机走复杂路线,新司机走主干道),实测可减少20%的沟通成本。这种业务细节往往在文档中找不到,需要真正深入一线才能发现。