摘要
贵金属回收、珠宝定价、量化监控场景中,伦敦金、伦敦银等国际贵金属行情对实时性要求高。WebSocket 长连接是最优方案,但开发中常遇到心跳缺失断连、网络波动无重连、报文解析异常等问题。本文基于 Node.js 原生 WebSocket 实现完整可部署客户端,支持多品种批量订阅,包含心跳保活、断线自动重连、异常捕获机制,数据源采用脉动行情数据 API。
关键词:Node.js;WebSocket;贵金属;伦敦金;实时行情
一、业务背景
国际贵金属价格是黄金回收门店、珠宝品牌定价、大宗贸易核算的核心参考指标,主流品种包括伦敦现货金、伦敦现货银、COMEX 黄金期货、COMEX 白银期货等。 很多项目初期用 HTTP 轮询获取行情,上线后容易出现延迟高、请求频繁触发限流等问题;改用 WebSocket 又常因为缺少生产级处理逻辑,导致连接不稳定、异常崩溃。
示例品种编码: XAU:伦敦金(现货黄金) XAG:伦敦银(现货白银) GC:COMEX 黄金期货 SI:COMEX 白银期货 通信约定:连接成功发送订阅报文,多品种逗号分隔;客户端每 10 秒发送心跳包维持链路。
二、环境依赖
javascript
npm install ws
三、完整 WebSocket 客户端代码
javascript
const WebSocket = require('ws');
// WebSocket服务地址,仅代码内配置
const WS_URL = 'ws://39.107.99.235/ws';
// 批量订阅贵金属品种
const SYMBOL_LIST = 'XAU,XAG,GC,SI';
// 心跳间隔 10秒
const HEARTBEAT_INTERVAL = 10000;
// 重连延迟 3秒
const RECONNECT_DELAY = 3000;
let ws = null;
let heartbeatTimer = null;
function connect() {
ws = new WebSocket(WS_URL);
ws.on('open', () => {
console.log('WebSocket连接成功,批量订阅贵金属行情');
// 发送订阅报文
ws.send(JSON.stringify({ Key: SYMBOL_LIST }));
// 启动心跳
startHeartbeat();
});
ws.on('message', (data) => {
try {
const message = JSON.parse(data.toString());
if (!message.body) return;
const body = message.body;
console.log('----------------------------------------');
console.log(`品种: ${body.StockCode}`);
console.log(`最新价: ${body.Price} 涨跌: ${body.Diff}`);
console.log(`最高: ${body.High} 最低: ${body.Low}`);
console.log(`更新时间: ${body.Time}`);
console.log('----------------------------------------');
} catch (err) {
console.error('行情解析异常:', err.message);
}
});
ws.on('close', (code, reason) => {
console.log(`连接断开 code: ${code},${RECONNECT_DELAY}ms后自动重连`);
stopHeartbeat();
setTimeout(connect, RECONNECT_DELAY);
});
ws.on('error', (err) => {
console.error('连接异常:', err.message);
});
}
function startHeartbeat() {
heartbeatTimer = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
const ping = JSON.stringify({ ping: Math.floor(Date.now() / 1000) });
ws.send(ping);
}
}, HEARTBEAT_INTERVAL);
}
function stopHeartbeat() {
if (heartbeatTimer) {
clearInterval(heartbeatTimer);
heartbeatTimer = null;
}
}
// 启动连接
connect();
// 优雅退出处理
process.on('SIGINT', () => {
console.log('正在关闭连接...');
stopHeartbeat();
ws.close();
process.exit(0);
});
四、HTTP 快照获取示例
不需要毫秒级推送的场景,可使用 HTTP 接口定时拉取。
javascript
const http = require('http');
const options = {
hostname: '39.107.99.235',
port: 1008,
path: '/getQuote.php?code=XAU,XAG',
headers: {
'Accept-Encoding': 'gzip'
},
timeout: 8000
};
http.get(options, (res) => {
let data = '';
res.on('data', (chunk) => data += chunk);
res.on('end', () => console.log(data));
}).on('error', (err) => {
console.error('请求失败:', err.message);
});
五、核心返回字段说明
| 字段 | 说明 |
|---|---|
| StockCode | 品种编码 |
| Price | 最新价格 |
| Open | 开盘价 |
| LastClose | 昨收价 |
| High | 日内最高价 |
| Low | 日内最低价 |
| Diff | 涨跌额 |
| DiffRate | 涨跌幅百分比 |
| Time | 行情更新时间 |
六、生产环境注意事项
- 必须维持 10 秒心跳,否则服务端会主动回收空闲连接;
- 断线重连增加延迟时间,避免网络未恢复时频繁重连;
- 消息解析必须增加异常捕获,防止畸形报文导致进程退出;
- 贵金属交易覆盖亚欧美盘,几乎全天波动,可 7×24 小时运行;
- 生产环境建议替换控制台输出为日志框架,行情数据落地存储。
七、总结
本方案实现贵金属多品种 WebSocket 实时监听,完整覆盖心跳保活、断线自动重连、异常捕获三大生产级能力,可直接部署用于黄金回收系统、珠宝定价平台、行情大屏等场景。修改订阅品种列表,即可快速扩展到铂金、钯金等其他贵金属品种。