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

参考资料


相关推荐
HelloWorld工程师3 小时前
新手如何快速申请SSL通配符证书...
网络协议·https·ssl
fei_sun7 小时前
开放最短路径优先OSPF----基于链路状态
网络
精明的身影7 小时前
网络计划WebApp求解:融合Python与AI决策的项目管理系统
网络·python·web app
姚不倒8 小时前
F5 SSL Profile 证书卸载深入篇
运维·网络协议·负载均衡·ssl·f5
Let's Chat Coding8 小时前
对称密钥认证:主机和设备共享同一把密钥
运维·服务器·网络
技术不好的崎鸣同学11 小时前
[极客大挑战 2019]EasySQL 思路及解法
网络·安全·web安全
Web极客码11 小时前
跨国网络抖动下的 AI 爬虫流调优:我如何用 Claude 打造“智能退避”资讯清洗管道
网络·人工智能·爬虫
念何架构之路11 小时前
moby-http-api-server
网络·网络协议·http
namexingyun12 小时前
Scaling Law bug实战启示:从“虚胖“到“精瘦“的算力效率革命
开发语言·网络·人工智能·bug·ai编程
阿拉斯攀登12 小时前
NAT 穿透详解:STUN / TURN / ICE
运维·服务器·网络·webrtc·nat