从零实现浏览器端 Redis 在线查询:WebSocket 隧道
一、要解决什么问题做一个在线 Redis 查询工具技术挑战分两层第一层浏览器怎么连 Redis浏览器 JS 只能发 HTTP/WebSocket不能直接建立 TCP 连接到 Redis 的 6379 端口。必须有一个中间层做协议转换。第二层用户 Redis 在内网怎么办公司内网的192.168.25.71:6379云端服务器根本访问不到。二、整体架构┌──────────┐ WebSocket ┌────────────────┐ WebSocket ┌──────────────┐ TCP:6379 ┌────────┐ │ 浏览器 │ ◄──────────► │ Spring Boot │ ◄──────────► │ Python Agent │ ◄────────► │ Redis │ │ Vue 2 │ │ (消息转发) │ │ (redis-py) │ │ (内网) │ └──────────┘ └────────────────┘ └──────────────┘ └────────┘浏览器WebSocket 客户端发 JSON 命令Spring Boot纯消息转发不解析 Redis 协议不存密码Agent收到 JSON → 调用 redis-py 执行 → 返回结果NginxWebSocket Upgrade 代理三、Spring Boot 端纯透明转发3.1 会话配对ComponentpublicclassSessionManager{// sessionId → { agentSession, browserSession }privatefinalConcurrentHashMapString,SessionPairpairsnewConcurrentHashMap();// Agent 连接 → 生成 8 位 sessionIdpublicStringregisterAgent(WebSocketSessionagentSession){StringsessionIdUUID.randomUUID().toString().replace(-,).substring(0,8);SessionPairpairnewSessionPair(sessionId);pair.agentSessionagentSession;pairs.put(sessionId,pair);returnsessionId;}// 浏览器连接 → 和 Agent 配对publicbooleanpairBrowser(StringsessionId,WebSocketSessionbrowserSession){SessionPairpairpairs.get(sessionId);if(pairnull)returnfalse;pair.browserSessionbrowserSession;returntrue;}// 消息转发Browser → AgentpublicvoidrelayToAgent(StringsessionId,Stringmessage){SessionPairpairpairs.get(sessionId);if(pair!nullpair.agentSession!nullpair.agentSession.isOpen()){pair.agentSession.sendMessage(newTextMessage(message));}}}3.2 两个 WebSocket 端点ConfigurationEnableWebSocketpublicclassWebSocketConfigimplementsWebSocketConfigurer{OverridepublicvoidregisterWebSocketHandlers(WebSocketHandlerRegistryregistry){registry.addHandler(agentHandler,/ws/agent);// Agent 连这里registry.addHandler(browserHandler,/ws/browser/*);// 浏览器连这里}}AgentWebSocketHandler在 Agent 连接时生成 sessionId 返回之后收到的每条消息都 relay 给浏览器。BrowserWebSocketHandler从 URL 路径/ws/browser/{sessionId}提取 ID配对后收到的每条消息 relay 给 Agent。3.3 关键坑AuthFilter 拦截 WebSocket 握手Spring Boot 的Filter先于 WebSocket 处理器执行。ApiAuthFilter拦截了/ws/**握手阶段的 HTTP Upgrade 请求被 401 拦截。加一行白名单即可if(apiUrl.startsWith(/api/pub/)||apiUrl.startsWith(/ws/)){filterChain.doFilter(servletRequest,servletResponse);return;}四、Python Agent协议转换核心4.1 消息协议所有通信走 JSON清晰可调试// 连接 Redis浏览器 → Agent:{type:connect,host:192.168.25.71,port:6379,password:xxx,db:0}Agent → 浏览器:{type:connected,msg:192.168.25.71:6379 DB0 - PONG}// 执行命令浏览器 → Agent:{type:query,command:HGETALL user:1001}Agent → 浏览器:{type:result,result:{name:Alice,age:25},resultType:map}// 错误Agent → 浏览器:{type:error,message:Connection refused}4.2 Redis 连接与命令执行importredisasredis_libdefconnect_redis(ws,msg):globaldb dbredis_lib.Redis(hostmsg.get(host),portmsg.get(port,6379),passwordmsg.get(password)orNone,dbmsg.get(db,0),socket_connect_timeout5,socket_timeout5,decode_responsesTrue,protocol2,# ← 关键强制 RESP2兼容 Redis 6.0)db.ping()defquery_redis(ws,msg):partsshlex.split(msg[command])# HGETALL user:1001 → [HGETALL, user:1001]cmd,argsparts[0].upper(),parts[1:]ifcmdnotinREDIS_READ_CMDS:# 白名单校验returnsend_error(ws,fCommand {cmd} not allowed)resultdb.execute_command(cmd,*args)# 底层调用比反射更可靠send(ws,{type:result,result:display,resultType:rtype})4.3 兼容旧版 Redisredis-py8.x 默认用 RESP3 协议连接时先发HELLO 3协商。Redis 6.0 不支持这个命令直接报错unknown command HELLO, with args beginning with: 3解决办法连接时强制指定 RESP2。dbredis.Redis(...,protocol2)一行搞定兼容所有 Redis 版本。4.4 连接稳定性浏览器 ──ping/15s──► 服务器 ──relay──► Agent ← 应用层心跳 ▲ │ └── pong ────────────┘ ← 服务端 echo 回执 Agent 断开 → 保留 sessionId → 带旧 ID 重连 ← 浏览器无感恢复 浏览器断开 → 指数退避重连2s/4s/8s最多3次 ← 超过3次提示检查 AgentAgent 主循环用whileWebSocketApp每次重连带?sessionId旧IDwhileshould_run[0]:wsWebSocketApp(build_url(),...)ws.run_forever(ping_interval0)delaymin(delay*2,30)time.sleep(delay)五、前端Vue 2 实现5.1 双模式切换el-radio-groupv-modelmodeel-radio-buttonlabeldirect直连模式/el-radio-buttonel-radio-buttonlabelagentAgent 模式/el-radio-button/el-radio-group直连模式HTTP POST 给后端后端用 Jedis 直连 Redis同网段场景Agent 模式WebSocket 发到 AgentAgent 在本地执行后返回5.2 WebSocket 连接管理connectViaAgent(){constwsUrl${location.protocolhttps:?wss::ws:}//${location.host}/ws/browser/${this.conn.sessionId}this.wsnewWebSocket(wsUrl)this.ws.onopen(){this.startHeartbeat()// 15s 间隔 ping/pongthis.ws.send(JSON.stringify({type:connect,host,port,password,db}))}this.ws.onmessage(e){constmsgJSON.parse(e.data)if(msg.typeconnected){this.connectedtrue// 连接成功显示命令输入区}elseif(msg.typeresult){this.resultmsg// 查询结果停止 loadingthis.loadingfalse}}}5.3 结果智能渲染根据resultType自动选渲染方式!-- string --divv-ifresTypestringdivclassmeta{{ resSize }}/divprev-ifisJson{{ resJson }}/pre!-- JSON 自动格式化 --spanv-else{{ resStr }}/span!-- 长文本折叠 --buttonclickcopyResult复制/button/div!-- list --divv-else-ifresTypelistdivclassmeta{{ resList.length }} items/divdivv-for(v,i) in pagedList:class{stripe: i%2}span{{ i }}/spancode{{ v }}/code/divbuttonclickloadMore显示更多/button!-- 分页加载 --/div!-- map --divv-else-ifresTypemapinputv-modelfilterplaceholder筛选字段.../!-- 搜索过滤 --tabletrv-fork in filteredKeystdcode{{ k }}/code/tdtdcode{{ resMap[k] }}/code/td/tr/table/div!-- nil --divv-else-ifresStr(nil)classnil-tip(键不存在)/div每种类型的渲染方式不同string 展示字节数 折叠list 斑马纹 分批加载map 搜索框 隔行变色nil 独立卡片。六、部署架构6.1 Nginx WebSocket 代理location /ws/ { proxy_pass http://127.0.0.1:8000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_read_timeout 3600s; proxy_send_timeout 3600s; }6.2 Agent 打包pipinstallpyinstaller pyinstaller--onefile--nameagent--iconagent.ico agent.py# dist/agent.exe12MB单文件可分发七、结果展示八、总结核心设计思路就三条协议转换下沉到 Agent服务器不碰 Redis 协议只做消息转发。Agent 用原生 redis-py 连接不受浏览器限制Agent 主动出站WebSocket 从内网往外连天然穿透 NAT/防火墙用户零网络配置在线体验https://onltool.site

相关新闻

深度学习环境配置终极指南:从CUDA、cuDNN到PyTorch的兼容性全解析

深度学习环境配置终极指南:从CUDA、cuDNN到PyTorch的兼容性全解析

1. 项目概述:为什么深度学习环境配置是“玄学”? 每次打开深度学习项目,准备大干一场,结果第一步就被环境配置卡住半天,这种感觉太熟悉了。CUDA版本不对、PyTorch装不上、跑起来报各种“RuntimeError: CUDA error”………

2026/8/7 11:44:32 阅读更多 →
暗黑3一键战斗终极指南:D3KeyHelper图形化宏工具完整教程

暗黑3一键战斗终极指南:D3KeyHelper图形化宏工具完整教程

暗黑3一键战斗终极指南:D3KeyHelper图形化宏工具完整教程 【免费下载链接】D3keyHelper D3KeyHelper是一个有图形界面,可自定义配置的暗黑3鼠标宏工具。 项目地址: https://gitcode.com/gh_mirrors/d3/D3keyHelper 想要在暗黑破坏神3中彻底解放双…

2026/8/7 11:44:32 阅读更多 →
像素vs条数级虚拟列表

像素vs条数级虚拟列表

目录 面试(像素):定/估高 缓冲区 DOM 数学公式(缓冲区) 完整代码 动态高度:估高 高度缓存二分查找 避坑指南 找起始索引 start:改用“二分查找” 关于 endIdx 的查找(用二分…

2026/8/8 13:53:44 阅读更多 →

最新新闻

3分钟掌握KS-Downloader:免费获取快手无水印视频的终极指南

3分钟掌握KS-Downloader:免费获取快手无水印视频的终极指南

3分钟掌握KS-Downloader:免费获取快手无水印视频的终极指南 【免费下载链接】KS-Downloader 快手(KuaiShou)作品视频/图片下载工具 项目地址: https://gitcode.com/gh_mirrors/ks/KS-Downloader 还在为无法保存喜欢的快手视频而烦恼吗…

2026/8/8 14:27:34 阅读更多 →
AI安全认证CAISP与AAIA对比:DevOps工程师如何选择

AI安全认证CAISP与AAIA对比:DevOps工程师如何选择

1. 项目概述:AI安全认证的行业现状与选择困境 最近两年AI安全与治理领域突然火起来的CAISP和AAIA两大认证,已经成了我们DevOps圈子里茶余饭后的热门话题。上周团队技术分享会上,几个负责AI系统部署的同事为"该考哪个证"争得面红耳赤…

2026/8/8 14:27:34 阅读更多 →
Legacy iOS Kit:终极iOS设备降级与恢复完整指南

Legacy iOS Kit:终极iOS设备降级与恢复完整指南

Legacy iOS Kit:终极iOS设备降级与恢复完整指南 【免费下载链接】Legacy-iOS-Kit An all-in-one tool to restore/downgrade, save SHSH blobs, jailbreak legacy iOS devices, and more 项目地址: https://gitcode.com/gh_mirrors/le/Legacy-iOS-Kit 你是否…

2026/8/8 14:27:34 阅读更多 →
3分钟免安装微信终极指南:浏览器插件让工作沟通零门槛

3分钟免安装微信终极指南:浏览器插件让工作沟通零门槛

3分钟免安装微信终极指南:浏览器插件让工作沟通零门槛 【免费下载链接】wechat-need-web 让微信网页版可用 / Allow the use of WeChat via webpage access 项目地址: https://gitcode.com/gh_mirrors/we/wechat-need-web 还在为无法在办公电脑安装微信而烦恼…

2026/8/8 14:27:34 阅读更多 →
Whisky终极指南:在Apple Silicon Mac上运行Windows应用的免费解决方案

Whisky终极指南:在Apple Silicon Mac上运行Windows应用的免费解决方案

Whisky终极指南:在Apple Silicon Mac上运行Windows应用的免费解决方案 【免费下载链接】Whisky A modern Wine wrapper for macOS built with SwiftUI 项目地址: https://gitcode.com/gh_mirrors/wh/Whisky 还在为Mac无法运行Windows专属软件而烦恼吗&#x…

2026/8/8 14:27:34 阅读更多 →
PostgreSQL分区管理终极指南:pg_partman如何让大数据表管理变得简单高效

PostgreSQL分区管理终极指南:pg_partman如何让大数据表管理变得简单高效

PostgreSQL分区管理终极指南:pg_partman如何让大数据表管理变得简单高效 【免费下载链接】pg_partman Partition management extension for PostgreSQL 项目地址: https://gitcode.com/gh_mirrors/pg/pg_partman PostgreSQL分区管理神器pg_partman是PostgreS…

2026/8/8 14:26:34 阅读更多 →

日新闻

AI多智能体时代来临,读懂MCP与A2A架构,抢占企业数字化新风口

AI多智能体时代来临,读懂MCP与A2A架构,抢占企业数字化新风口

当下AI应用飞速普及,无数企业下场搭建智能体系统,可落地阶段难题接踵而至:上下文无限堆积频繁爆栈、AI工具调用准确率低下、Token成本居高不下、企业数据权限混乱暗藏安全隐患……很多团队卡在架构搭建环节,空有前沿技术概念&…

2026/8/8 0:00:07 阅读更多 →
PHP二维码生成终极指南:用chillerlan/php-qrcode打造专业级二维码

PHP二维码生成终极指南:用chillerlan/php-qrcode打造专业级二维码

PHP二维码生成终极指南:用chillerlan/php-qrcode打造专业级二维码 【免费下载链接】php-qrcode A PHP QR Code generator and reader with a user-friendly API. 项目地址: https://gitcode.com/gh_mirrors/ph/php-qrcode 在当今数字时代,二维码已…

2026/8/8 0:00:08 阅读更多 →
UniApp微信小程序隐私保护组件开发:从原理到实战

UniApp微信小程序隐私保护组件开发:从原理到实战

1. 项目缘起:为什么我们需要一个隐私保护通用组件?最近在维护一个基于uniapp开发的微信小程序矩阵时,我遇到了一个非常棘手的问题。随着平台对用户隐私保护的要求越来越严格,几乎每一个新版本发布,或者在某些特定机型&…

2026/8/8 0:00:08 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/6 22:02:27 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/8 8:58:26 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/7 23:24:08 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/7 17:02:37 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/7 23:54:54 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/7 17:02:36 阅读更多 →