DolphinDB WebSocket接入:实时数据流

目录

    • 摘要
    • 一、WebSocket概述
      • [1.1 什么是WebSocket](#1.1 什么是WebSocket)
      • [1.2 WebSocket vs HTTP](#1.2 WebSocket vs HTTP)
      • [1.3 适用场景](#1.3 适用场景)
    • [二、DolphinDB WebSocket](#二、DolphinDB WebSocket)
      • [2.1 创建WebSocket服务](#2.1 创建WebSocket服务)
      • [2.2 连接管理](#2.2 连接管理)
    • 三、实时数据接收
      • [3.1 连接WebSocket](#3.1 连接WebSocket)
      • [3.2 发送数据](#3.2 发送数据)
      • [3.3 批量发送](#3.3 批量发送)
    • 四、消息处理
      • [4.1 消息格式](#4.1 消息格式)
      • [4.2 消息处理函数](#4.2 消息处理函数)
    • 五、心跳保活
      • [5.1 心跳机制](#5.1 心跳机制)
      • [5.2 服务端心跳响应](#5.2 服务端心跳响应)
    • 六、断线重连
      • [6.1 自动重连](#6.1 自动重连)
      • [6.2 数据缓冲](#6.2 数据缓冲)
    • 七、实战案例
      • [7.1 实时监控数据推送](#7.1 实时监控数据推送)
    • 八、总结
    • 参考资料

摘要

本文深入讲解DolphinDB WebSocket接入技术。从WebSocket协议原理到连接管理,从实时数据接收到消息处理,从心跳保活到断线重连,全面介绍WebSocket数据接入的核心方法。通过丰富的代码示例,帮助读者掌握实时数据流处理的核心技能。


一、WebSocket概述

1.1 什么是WebSocket

WebSocket是全双工实时通信协议:
#mermaid-svg-Ultmphfbe6oaaeZL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Ultmphfbe6oaaeZL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Ultmphfbe6oaaeZL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Ultmphfbe6oaaeZL .error-icon{fill:#552222;}#mermaid-svg-Ultmphfbe6oaaeZL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Ultmphfbe6oaaeZL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Ultmphfbe6oaaeZL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Ultmphfbe6oaaeZL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Ultmphfbe6oaaeZL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Ultmphfbe6oaaeZL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Ultmphfbe6oaaeZL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Ultmphfbe6oaaeZL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Ultmphfbe6oaaeZL .marker.cross{stroke:#333333;}#mermaid-svg-Ultmphfbe6oaaeZL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Ultmphfbe6oaaeZL p{margin:0;}#mermaid-svg-Ultmphfbe6oaaeZL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Ultmphfbe6oaaeZL .cluster-label text{fill:#333;}#mermaid-svg-Ultmphfbe6oaaeZL .cluster-label span{color:#333;}#mermaid-svg-Ultmphfbe6oaaeZL .cluster-label span p{background-color:transparent;}#mermaid-svg-Ultmphfbe6oaaeZL .label text,#mermaid-svg-Ultmphfbe6oaaeZL span{fill:#333;color:#333;}#mermaid-svg-Ultmphfbe6oaaeZL .node rect,#mermaid-svg-Ultmphfbe6oaaeZL .node circle,#mermaid-svg-Ultmphfbe6oaaeZL .node ellipse,#mermaid-svg-Ultmphfbe6oaaeZL .node polygon,#mermaid-svg-Ultmphfbe6oaaeZL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Ultmphfbe6oaaeZL .rough-node .label text,#mermaid-svg-Ultmphfbe6oaaeZL .node .label text,#mermaid-svg-Ultmphfbe6oaaeZL .image-shape .label,#mermaid-svg-Ultmphfbe6oaaeZL .icon-shape .label{text-anchor:middle;}#mermaid-svg-Ultmphfbe6oaaeZL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Ultmphfbe6oaaeZL .rough-node .label,#mermaid-svg-Ultmphfbe6oaaeZL .node .label,#mermaid-svg-Ultmphfbe6oaaeZL .image-shape .label,#mermaid-svg-Ultmphfbe6oaaeZL .icon-shape .label{text-align:center;}#mermaid-svg-Ultmphfbe6oaaeZL .node.clickable{cursor:pointer;}#mermaid-svg-Ultmphfbe6oaaeZL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Ultmphfbe6oaaeZL .arrowheadPath{fill:#333333;}#mermaid-svg-Ultmphfbe6oaaeZL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Ultmphfbe6oaaeZL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Ultmphfbe6oaaeZL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ultmphfbe6oaaeZL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Ultmphfbe6oaaeZL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ultmphfbe6oaaeZL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Ultmphfbe6oaaeZL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Ultmphfbe6oaaeZL .cluster text{fill:#333;}#mermaid-svg-Ultmphfbe6oaaeZL .cluster span{color:#333;}#mermaid-svg-Ultmphfbe6oaaeZL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Ultmphfbe6oaaeZL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Ultmphfbe6oaaeZL rect.text{fill:none;stroke-width:0;}#mermaid-svg-Ultmphfbe6oaaeZL .icon-shape,#mermaid-svg-Ultmphfbe6oaaeZL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ultmphfbe6oaaeZL .icon-shape p,#mermaid-svg-Ultmphfbe6oaaeZL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Ultmphfbe6oaaeZL .icon-shape .label rect,#mermaid-svg-Ultmphfbe6oaaeZL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ultmphfbe6oaaeZL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Ultmphfbe6oaaeZL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Ultmphfbe6oaaeZL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} WebSocket架构
客户端
WebSocket连接
服务端

DolphinDB
特点
全双工
实时推送
长连接

1.2 WebSocket vs HTTP

特性 HTTP WebSocket
通信方式 半双工 全双工
连接 短连接 长连接
实时性 轮询 实时推送
开销

1.3 适用场景

场景 说明
实时监控 实时数据推送
告警通知 实时告警推送
仪表盘 实时数据展示
设备控制 实时指令下发

二、DolphinDB WebSocket

2.1 创建WebSocket服务

python 复制代码
// 创建WebSocket服务
// DolphinDB内置WebSocket支持

// 创建流表接收数据
share streamTable(1:0, 
    `device_id`timestamp`temperature`humidity,
    [SYMBOL, TIMESTAMP, DOUBLE, DOUBLE]) as ws_stream

// WebSocket端点
// ws://localhost:8848/ws

2.2 连接管理

python 复制代码
// WebSocket连接配置
config = dict(STRING, ANY, [
    ["maxConnections", 1000],
    ["heartbeatInterval", 30000],
    ["maxMessageSize", 1048576]
])

三、实时数据接收

3.1 连接WebSocket

javascript 复制代码
// JavaScript客户端示例
const ws = new WebSocket('ws://localhost:8848/ws');

ws.onopen = function() {
    console.log('WebSocket连接成功');
    // 订阅主题
    ws.send(JSON.stringify({
        action: 'subscribe',
        topic: 'sensor/data'
    }));
};

ws.onmessage = function(event) {
    const data = JSON.parse(event.data);
    console.log('收到数据:', data);
};

ws.onerror = function(error) {
    console.error('WebSocket错误:', error);
};

ws.onclose = function() {
    console.log('WebSocket连接关闭');
};

3.2 发送数据

javascript 复制代码
// 发送数据到DolphinDB
function sendData(data) {
    ws.send(JSON.stringify({
        action: 'write',
        table: 'ws_stream',
        data: data
    }));
}

// 示例
sendData({
    device_id: 'D001',
    timestamp: new Date().toISOString(),
    temperature: 25.5,
    humidity: 50.0
});

3.3 批量发送

javascript 复制代码
// 批量发送数据
function sendBatch(dataList) {
    ws.send(JSON.stringify({
        action: 'write',
        table: 'ws_stream',
        data: dataList
    }));
}

// 示例
const batch = [];
for (let i = 0; i < 100; i++) {
    batch.push({
        device_id: `D${i.toString().padStart(3, '0')}`,
        timestamp: new Date().toISOString(),
        temperature: 20 + Math.random() * 10,
        humidity: 40 + Math.random() * 20
    });
}
sendBatch(batch);

四、消息处理

4.1 消息格式

python 复制代码
// JSON消息格式
{
    "action": "write",     // 操作类型
    "table": "ws_stream",  // 目标表
    "data": {              // 数据
        "device_id": "D001",
        "timestamp": "2024-01-01T00:00:00",
        "temperature": 25.5,
        "humidity": 50.0
    }
}

// 订阅消息
{
    "action": "subscribe",
    "topic": "sensor/data"
}

// 查询消息
{
    "action": "query",
    "sql": "select * from ws_stream limit 10"
}

4.2 消息处理函数

python 复制代码
// 消息处理函数
def handleWsMessage(msg) {
    action = msg.action
    
    if (action == "write") {
        // 写入数据
        table = msg.table
        data = msg.data
        // 写入逻辑
    } else if (action == "subscribe") {
        // 订阅主题
        topic = msg.topic
        // 订阅逻辑
    } else if (action == "query") {
        // 查询数据
        sql = msg.sql
        // 查询逻辑
    }
}

五、心跳保活

5.1 心跳机制

javascript 复制代码
// 客户端心跳
let heartbeatInterval;

function startHeartbeat() {
    heartbeatInterval = setInterval(() => {
        if (ws.readyState === WebSocket.OPEN) {
            ws.send(JSON.stringify({ action: 'ping' }));
        }
    }, 30000);  // 每30秒发送心跳
}

function stopHeartbeat() {
    clearInterval(heartbeatInterval);
}

ws.onopen = function() {
    startHeartbeat();
};

ws.onclose = function() {
    stopHeartbeat();
};

5.2 服务端心跳响应

python 复制代码
// 服务端心跳处理
def handleHeartbeat(conn) {
    // 收到ping,返回pong
    ws::send(conn, {action: "pong", timestamp: now()})
}

六、断线重连

6.1 自动重连

javascript 复制代码
// 自动重连机制
let ws;
let reconnectAttempts = 0;
const maxReconnectAttempts = 5;

function connect() {
    ws = new WebSocket('ws://localhost:8848/ws');
    
    ws.onopen = function() {
        console.log('WebSocket连接成功');
        reconnectAttempts = 0;
    };
    
    ws.onclose = function() {
        console.log('WebSocket连接关闭');
        if (reconnectAttempts < maxReconnectAttempts) {
            reconnectAttempts++;
            console.log(`尝试重连 (${reconnectAttempts}/${maxReconnectAttempts})`);
            setTimeout(connect, 3000);
        }
    };
    
    ws.onerror = function(error) {
        console.error('WebSocket错误:', error);
    };
}

connect();

6.2 数据缓冲

javascript 复制代码
// 断线时缓冲数据
const dataBuffer = [];
const maxBufferSize = 10000;

function sendDataWithBuffer(data) {
    if (ws.readyState === WebSocket.OPEN) {
        ws.send(JSON.stringify(data));
        // 发送缓冲数据
        while (dataBuffer.length > 0) {
            ws.send(JSON.stringify(dataBuffer.shift()));
        }
    } else {
        // 缓冲数据
        if (dataBuffer.length < maxBufferSize) {
            dataBuffer.push(data);
        }
    }
}

七、实战案例

7.1 实时监控数据推送

python 复制代码
// ========== 实时监控数据推送 ==========

// 1. 创建流表
share streamTable(100000:0, 
    `device_id`timestamp`temperature`humidity`pressure,
    [SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE]) as monitor_stream

// 2. 启用持久化
enableTablePersistence(monitor_stream, true, true, 1000000)

// 3. 创建分布式表
db = database("dfs://ws_db", VALUE, 1..1000)
schema = table(1:0, `device_id`timestamp`temperature`humidity`pressure,
               [SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `monitor_data, `device_id)

// 4. 订阅写入
subscribeTable(, "monitor_stream", "persist", -1,
    def(msg) {
        loadTable("dfs://ws_db", "monitor_data").append!(msg)
    }, 10000, 5000)

// 5. WebSocket端点
// ws://localhost:8848/ws

// 6. 客户端示例(JavaScript)
/*
const ws = new WebSocket('ws://localhost:8848/ws');

ws.onopen = function() {
    console.log('连接成功');
};

function pushData(deviceId, temp, humid, press) {
    ws.send(JSON.stringify({
        action: 'write',
        table: 'monitor_stream',
        data: {
            device_id: deviceId,
            timestamp: new Date().toISOString(),
            temperature: temp,
            humidity: humid,
            pressure: press
        }
    }));
}
*/

print("实时监控数据推送系统已就绪")

八、总结

本文详细介绍了DolphinDB WebSocket接入:

  1. WebSocket原理:全双工、实时推送、长连接
  2. 连接管理:创建连接、配置参数
  3. 数据接收:连接、发送、批量发送
  4. 消息处理:消息格式、处理函数
  5. 心跳保活:心跳机制、响应处理
  6. 断线重连:自动重连、数据缓冲

思考题

  1. WebSocket相比HTTP有什么优势?
  2. 如何设计可靠的WebSocket连接?
  3. 如何处理WebSocket断线问题?

参考资料


相关推荐
DeboPXK1 小时前
NSK VH25EM 高防尘法兰型导轨技术手册
服务器·网络·数据库·经验分享·规格说明书
超级赛博搬砖工2 小时前
SEO代理解析:成功搜索引擎抓取你需要了解的事项
大数据·运维·服务器·网络
行走__Wz2 小时前
【网工入门-eNSP模拟-07】单臂路由
网络·智能路由器
网络研究院2 小时前
德国网络安全法律与实践
网络·安全·法律·实践·德国
盟接之桥2 小时前
电子数据交换(EDI)|制造业汽车零配件场景方案
大数据·网络·人工智能·安全·低代码·汽车·制造
闪电悠米2 小时前
黑马点评-Redis ZSet-实现关注 Feed 流
服务器·网络·数据库·redis·缓存·junit·lua
caimouse2 小时前
Reactos 第 10 章 网络操作 — 10.3.2 LAN驱动模块
服务器·网络·windows
yyuuuzz3 小时前
2026游戏云服务器推荐的技术判断思路
运维·服务器·开发语言·网络·人工智能·游戏·php
勇敢牛牛_3 小时前
Zeplyn:通过P2P构建服务共享网络
网络·网络协议·p2p·服务