1. 项目概述:制造业ERP系统的技术实现
这个基于SpringBoot+Vue的制造装备物联及生产管理ERP系统,是一个典型的工业互联网应用案例。我在去年为一家中型机械制造企业实施过类似系统,当时客户最迫切的需求就是解决"生产数据黑箱"问题——车间主任每天要花3小时手工统计设备状态,财务部门月底对不上原材料消耗,管理层看不到实时产能。
这套系统核心解决了三个制造业痛点:
- 设备数据自动采集(物联层)
- 生产流程数字化管理(执行层)
- 全链路数据可视化(决策层)
技术栈选择上,后端用SpringBoot而不是传统的SSM框架,主要是看中其嵌入式Tomcat和自动配置特性。当需要对接20多台CNC机床的Modbus协议时,SpringBoot的轻量级线程池管理让数据采集服务稳定运行在车间那台老旧的DELL服务器上。前端选用Vue而非React,是因为制造业客户更习惯传统表单操作方式,Vue的双向绑定和组件化在开发BOM(物料清单)模块时效率提升了40%。
2. 系统架构设计解析
2.1 前后端分离架构实践
项目采用典型的前后端分离架构,但制造业ERP有其特殊之处。我们设计了三种不同粒度的API接口:
-
设备级高频接口(1秒级轮询)
- 用WebSocket保持长连接
- 数据压缩采用Protocol Buffers
- 示例:
/api/equipment/realtime/{deviceId}
-
业务级常规接口
- RESTful规范
- JWT鉴权
- 示例:
/api/production/orders?status=processing
-
报表级大数据接口
- 分页查询默认限制1000条/次
- 采用CSV格式导出
- 示例:
/api/reports/daily-production
特别注意:车间环境网络不稳定,所有设备接口都必须实现断点续传。我们在采集服务中设计了环形缓冲区,网络恢复后自动补传缺失数据。
2.2 数据库设计要点
制造业ERP的数据库设计要特别注意事务一致性。这个项目的SQL脚本中包含几个关键设计:
sql复制-- 工序流转表需要记录完整操作链
CREATE TABLE production_routing (
id BIGINT PRIMARY KEY,
order_no VARCHAR(32) NOT NULL,
current_station INT NOT NULL,
previous_station INT,
next_station INT,
operator_id INT,
start_time DATETIME,
end_time DATETIME,
quality_status TINYINT DEFAULT 0,
version INT DEFAULT 0 -- 乐观锁字段
) ENGINE=InnoDB;
-- 物料批次表需要严格跟踪
CREATE TABLE material_lot (
lot_id VARCHAR(64) PRIMARY KEY,
material_id INT NOT NULL,
quantity DECIMAL(12,3) NOT NULL,
warehouse_id INT NOT NULL,
supplier_batch VARCHAR(64),
production_date DATE,
expiry_date DATE,
quarantine_status TINYINT DEFAULT 0,
INDEX idx_material (material_id),
INDEX idx_warehouse (warehouse_id)
) ENGINE=InnoDB;
3. 核心功能模块实现
3.1 设备物联模块
通过PLC网关采集设备数据时,遇到的最大挑战是不同品牌设备的协议差异。我们最终采用如下方案:
-
协议适配层
- 三菱MELSEC:MC协议
- 西门子S7:S7Comm
- 发那科:FOCAS2
- 通用设备:Modbus TCP
-
数据标准化处理
java复制// 设备数据解析示例
public class EquipmentDataParser {
private static final Map<String, Double> SCALE_FACTORS =
Map.of("temperature", 0.1, "vibration", 0.01);
public EquipmentData parse(byte[] rawData, ProtocolType protocol) {
// 协议特定解析逻辑
EquipmentData data = protocol.parse(rawData);
// 数据标准化
data.getMetrics().forEach((k,v) -> {
if(SCALE_FACTORS.containsKey(k)) {
data.setMetric(k, v * SCALE_FACTORS.get(k));
}
});
return data;
}
}
3.2 生产排程算法
制造业排程要考虑设备能力、模具准备、人员班次等约束条件。我们改进了经典的遗传算法:
- 染色体编码:每个基因代表一个工序的[设备ID, 开始时间]
- 适应度函数:考虑交货期、换模时间、设备利用率
- 特殊处理:模具冷却时间作为硬约束
java复制public class ProductionScheduler {
public ScheduleResult generateSchedule(List<ProductionOrder> orders) {
GeneticAlgorithm<ScheduleGene> ga = new GeneticAlgorithm<>(
populationSize: 100,
mutationRate: 0.01,
crossoverRate: 0.8,
new ScheduleFitnessCalculator()
);
return ga.evolve(100);
}
}
class ScheduleFitnessCalculator implements FitnessCalculator<ScheduleGene> {
@Override
public double calculate(ScheduleGene gene) {
double score = 0;
// 计算交货期偏差
score -= calculateDelayPenalty(gene);
// 计算设备利用率
score += calculateUtilizationScore(gene);
// 模具冷却时间惩罚
score -= calculateMoldCoolingPenalty(gene);
return score;
}
}
4. 典型问题排查实录
4.1 性能问题:生产报表生成超时
现象:当查询3个月的生产数据时,报表接口响应超过30秒
排查过程:
- 发现SQL没有使用日期索引
- N+1查询问题:获取工单详情时循环查询工序
- 物料移动历史表未分区
解决方案:
sql复制-- 优化后的查询示例
SELECT o.order_no, m.material_name, SUM(t.quantity)
FROM production_orders o
JOIN material_transactions t ON o.id = t.order_id
JOIN materials m ON t.material_id = m.id
WHERE o.create_time BETWEEN '2023-01-01' AND '2023-03-31'
GROUP BY o.order_no, m.material_name
ORDER BY o.create_time
-- 新增的索引
CREATE INDEX idx_orders_create_time ON production_orders(create_time);
4.2 数据一致性问题
现象:库存扣减偶尔出现负数
根本原因:
- 并发更新时乐观锁失效
- 事务隔离级别设置不当
最终方案:
java复制@Transactional(isolation = Isolation.SERIALIZABLE)
public void deductInventory(Long materialId, Double quantity) {
MaterialStock stock = stockDao.selectForUpdate(materialId);
if(stock.getQuantity() >= quantity) {
stock.setQuantity(stock.getQuantity() - quantity);
stockDao.update(stock);
} else {
throw new InventoryException("库存不足");
}
}
5. 部署与运维要点
5.1 车间环境部署
制造业现场的特殊要求:
- 使用工业级交换机(推荐赫斯曼或摩莎)
- 服务器需配备UPS不间断电源
- 数据库每日全量备份 + 事务日志每小时备份
- 车间客户端安装无风扇工控机
5.2 性能调优参数
在application.yml中关键配置:
yaml复制spring:
datasource:
hikari:
maximum-pool-size: 20
connection-timeout: 30000
jpa:
properties:
hibernate:
jdbc:
batch_size: 50
order_inserts: true
order_updates: true
server:
tomcat:
max-threads: 200
accept-count: 100
6. 项目扩展建议
在实际运行一年后,我们为客户增加了三个重要扩展:
-
设备预测性维护
- 基于振动数据分析轴承寿命
- 使用Python机器学习模型
- 通过gRPC与Java服务通信
-
移动端应用
- 用Uniapp开发跨平台APP
- 重点实现异常报警推送
- 扫码报工功能
-
与MES系统集成
- 开发专用中间件处理数据同步
- 采用Apache Camel路由引擎
- 冲突解决策略:时间戳优先
这个项目让我深刻体会到,工业软件最难的不是技术实现,而是对制造业务的理解。比如最初我们不知道"模具冷却时间"这个约束,导致排程算法在实际生产中完全不可用。后来花了两周时间跟车间老师傅学习,才真正理解什么是"可执行的"生产计划。
