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断线问题?

参考资料


相关推荐
可爱系程序猿7 小时前
Windows 打印链路诊断:从设备枚举、TCP/IP 端口到 Spooler 服务恢复
网络·网络协议·tcp/ip
深念Y9 小时前
P2P组网选型与折腾记录
网络·网络协议·p2p·局域网·远程·组网
会编程的土豆10 小时前
MySQL 入门:库、表、行、主键是什么
linux·数据库·网络协议·http
jjjava2.010 小时前
系统日志:从入门到精通的完整指南
网络·数据库
阿kun要赚马内10 小时前
DNS了解
网络协议
MartinYeung510 小时前
[论文学习]InjecAgent:工具集成大语言模型智能体的间接提示注入基准测试
网络·学习·语言模型
paopaokaka_luck10 小时前
基于Springboot3+Vue3的高校选课系统(AI选课助手、协同过滤算法、分享到微博、扣扣、Echarts图形化分析)
网络·spring boot·网络协议·echarts
三川69811 小时前
深入浅出SSD 10:UFS介绍
网络
BullSmall12 小时前
AFL++ HTTP Mode(网络 / HTTP 服务模糊测试)完整安装教程
网络·网络协议·http
Yuiiii__13 小时前
一次“在家连不上公司内网服务”的排障实战记录
网络·智能路由器