从零构建轻量级实时监控系统:WebSocket与数据可视化实践

news2026/5/7 22:47:39
1. 项目概述一个名为“Aura”的代码仓库能做什么在GitHub上当你看到一个以开发者用户名命名的仓库比如bryanchen3777/Project-Aura第一反应会是什么这很可能是一个个人项目一个实验性的想法或者是一个正在孵化中的工具。Aura这个名字本身就充满了遐想——光环、氛围、气场。在技术领域它往往与“监控”、“洞察”、“可视化”或“状态感知”相关联。这个项目很可能是一个旨在收集、处理并呈现某种系统状态、数据流或环境信息的工具。它可能是一个轻量级的监控面板一个实时数据仪表盘或者一个用于个人工作流的自动化感知中枢。对于开发者而言尤其是全栈或DevOps方向的从业者我们常常需要一种简单、直接、可定制的方式来“感知”自己的数字世界。无论是服务器资源使用情况、API接口的健康状态、自动化任务的执行日志还是智能家居设备的数据流将这些分散的信息汇聚到一个统一的、美观的界面中能极大地提升效率和对系统的掌控感。Project-Aura很可能就是瞄准了这个痛点它不一定是像PrometheusGrafana那样的企业级重型方案而是更倾向于快速部署、易于配置、聚焦于个人或小团队核心需求的“氛围灯”式监控工具。你可以把它想象成为你数字工作台打造的一个“环境光效”当数据库负载升高时它的界面颜色或许会从宁静的蓝色变为警示的橙色让你一眼知悉。接下来我将基于一个全栈开发者的视角深入拆解如何从零开始构思和实现一个类似Project-Aura的项目。我们将涵盖从技术选型、架构设计到核心功能实现、问题排查的全过程目标是打造一个集数据采集、处理、存储和可视化于一体的轻量级监控与状态感知平台。2. 核心架构设计与技术选型考量构建一个Aura类的项目核心在于平衡实时性、轻量性和可扩展性。我们不需要一开始就追求大而全而是应该设计一个清晰、解耦的架构便于后续迭代。2.1 前后端分离与通信模式现代Web项目几乎都会采用前后端分离架构。前端负责展示和用户交互后端负责数据处理和业务逻辑。对于实时数据监控前后端的通信方式尤为关键。前端技术栈Vue 3或React是主流选择。它们组件化、响应式的特性非常适合构建动态的数据仪表盘。考虑到项目的“轻量”和“氛围”感UI库可以选择Tailwind CSS进行快速、灵活的样式构建它能轻松实现从数据值到颜色、阴影等视觉反馈的映射。对于图表ECharts或Chart.js功能强大且易于集成能够绘制折线图、仪表盘、饼图等多种可视化组件。后端技术栈Node.js with Express或Python with FastAPI都是优秀的轻量级后端框架。Node.js在I/O密集型和高并发实时应用上有天然优势而Python在数据分析和集成各类系统库时更顺手。选择哪一个取决于团队熟悉度和待采集数据源的处理复杂度。实时通信这是项目的灵魂。简单的轮询Polling会增加服务器压力且实时性差。WebSocket是实现全双工实时通信的标准方案。我们可以使用Socket.IONode.js或WebSocketsPython的websockets库来建立持久连接让服务器在数据更新时能主动推送到前端。对于更简单的场景Server-Sent Events (SSE)也是一种轻量的、服务器向客户端单向推送的技术。选型心得如果你的数据更新频率非常高如秒级甚至毫秒级且需要双向通信如前端也能控制后端任务WebSocket是首选。如果主要是服务器向客户端推送日志或状态更新SSE的实现会更简单。在Project-Aura的初期我建议从 Socket.IO 开始它为连接稳定性提供了自动重连等保障能减少很多底层烦恼。2.2 数据流与存储设计数据从哪里来到哪里去怎么存数据采集层我们需要“探针”。这些可以是自定义脚本用Python/Node.js/Bash编写定期收集系统指标如psutil库获取CPU/内存、调用第三方API获取状态、读取日志文件等。Agent在目标机器上部署一个轻量级常驻进程负责收集数据并上报给Aura后端。这比从中心服务器去拉取所有目标的数据更可控。Webhook接收器让外部服务如GitHub Actions、CI/CD平台、IoT设备在事件发生时主动向Aura的特定API端点发送数据。这是集成外部系统的优雅方式。数据处理与聚合层后端接收到原始数据后不能直接扔给前端。可能需要清洗与格式化统一数据格式如JSON处理异常值。聚合将高频的细粒度数据聚合成每分钟、每小时的统计值如平均值、最大值以减少存储压力和前端渲染负担。计算派生指标比如根据CPU使用率和负载计算一个“系统健康度”分数。数据存储层时序数据库监控数据本质上是时间序列数据。InfluxDB是专门为此设计的写入和查询效率极高自带数据过期策略。这是最专业的选择。关系型数据库如果数据量不大结构相对固定PostgreSQL或MySQL完全可以胜任且更通用。可以利用它们的JSON字段类型存储灵活的数据。内存数据库对于纯粹的实时展示数据无需持久化或只需短期留存Redis是绝佳选择。它性能极高支持多种数据结构还可以用作WebSocket连接状态的管理和中转站。实操建议在项目初期数据量不大的情况下使用PostgreSQL足以支撑。它的JSONB类型可以灵活存储采集到的各种指标同时也能利用其强大的关系型特性管理用户、数据源等元信息。当数据量增长到百万、千万级别且查询性能成为瓶颈时再考虑引入 InfluxDB 做专项优化。Redis 则建议一开始就引入用于缓存热点数据和管理WebSocket会话。2.3 整体架构图概念性描述一个典型的Aura系统可能呈现以下数据流[数据源: 服务器/API/IoT] -- [采集器: 脚本/Agent] --(HTTP/Webhook)-- [Aura后端 API] ^ | | v [轮询或事件触发] [数据处理 存储] | | v v [PostgreSQL] [Redis] | v [WebSocket/Socket.IO 服务器] -- [Aura前端] | v [浏览器: 实时仪表盘]3. 核心模块实现与实操要点3.1 后端核心WebSocket服务与数据API我们以 Node.js Express Socket.IO 为例。首先搭建基础服务器并集成Socket.IO// server.js const express require(express); const http require(http); const { Server } require(socket.io); const app express(); const server http.createServer(app); const io new Server(server, { cors: { origin: http://localhost:3000, // 你的前端地址 methods: [GET, POST] } }); // 存储活跃连接和其订阅的数据源 const clientSubscriptions new Map(); io.on(connection, (socket) { console.log(客户端已连接: ${socket.id}); // 客户端订阅特定数据源 socket.on(subscribe, (dataSourceId) { if (!clientSubscriptions.has(dataSourceId)) { clientSubscriptions.set(dataSourceId, new Set()); } clientSubscriptions.get(dataSourceId).add(socket.id); console.log(客户端 ${socket.id} 订阅了数据源 ${dataSourceId}); }); // 客户端取消订阅 socket.on(unsubscribe, (dataSourceId) { const subscribers clientSubscriptions.get(dataSourceId); if (subscribers) { subscribers.delete(socket.id); if (subscribers.size 0) { clientSubscriptions.delete(dataSourceId); } } }); socket.on(disconnect, () { console.log(客户端断开: ${socket.id}); // 清理该客户端的所有订阅 for (const [sourceId, sockets] of clientSubscriptions) { sockets.delete(socket.id); if (sockets.size 0) { clientSubscriptions.delete(sourceId); } } }); }); // 模拟数据更新并广播 function simulateDataUpdate() { const mockData { sourceId: server_metrics_001, timestamp: new Date().toISOString(), metrics: { cpu: Math.random() * 100, memory: Math.random() * 100, load: Math.random() * 5 } }; // 获取订阅了此数据源的所有客户端Socket ID const subscribers clientSubscriptions.get(mockData.sourceId); if (subscribers subscribers.size 0) { io.to([...subscribers]).emit(data-update, mockData); } } // 每2秒模拟一次数据更新 setInterval(simulateDataUpdate, 2000); // 启动服务器 const PORT process.env.PORT || 3001; server.listen(PORT, () { console.log(Aura后端服务运行在端口 ${PORT}); });同时你需要提供RESTful API用于数据的历史查询、配置管理app.use(express.json()); const { Pool } require(pg); const pool new Pool({ /* 你的PostgreSQL连接配置 */ }); // API: 获取某个数据源的历史数据 app.get(/api/data/:sourceId, async (req, res) { const { sourceId } req.params; const { start, end, limit 100 } req.query; try { const query SELECT * FROM metrics WHERE source_id $1 AND timestamp $2 AND timestamp $3 ORDER BY timestamp DESC LIMIT $4 ; const result await pool.query(query, [sourceId, start || 1970-01-01, end || new Date().toISOString(), limit]); res.json(result.rows); } catch (error) { console.error(查询历史数据失败:, error); res.status(500).json({ error: Internal Server Error }); } });3.2 前端核心建立连接与动态可视化前端使用Vue 3和Socket.IO客户端。首先创建一个可复用的WebSocket连接管理钩子Composable// composables/useSocket.js import { ref, onUnmounted } from vue; import { io } from socket.io-client; export function useSocket(url) { const socket ref(null); const isConnected ref(false); const messageLog ref([]); // 用于调试或显示连接状态 const connect () { socket.value io(url, { transports: [websocket], // 优先使用WebSocket传输 autoConnect: true, }); socket.value.on(connect, () { isConnected.value true; console.log(WebSocket连接成功); messageLog.value.push({ type: info, text: 连接已建立 }); }); socket.value.on(disconnect, (reason) { isConnected.value false; console.log(WebSocket连接断开:, reason); messageLog.value.push({ type: warn, text: 连接断开: ${reason} }); }); socket.value.on(connect_error, (error) { console.error(连接错误:, error); messageLog.value.push({ type: error, text: 连接错误: ${error.message} }); }); }; const subscribe (dataSourceId) { if (socket.value isConnected.value) { socket.value.emit(subscribe, dataSourceId); messageLog.value.push({ type: info, text: 已订阅数据源: ${dataSourceId} }); } }; const unsubscribe (dataSourceId) { if (socket.value isConnected.value) { socket.value.emit(unsubscribe, dataSourceId); messageLog.value.push({ type: info, text: 已取消订阅数据源: ${dataSourceId} }); } }; const onDataUpdate (callback) { if (socket.value) { socket.value.on(data-update, callback); } }; const disconnect () { if (socket.value) { socket.value.disconnect(); socket.value null; isConnected.value false; } }; onUnmounted(() { disconnect(); }); return { socket, isConnected, messageLog, connect, disconnect, subscribe, unsubscribe, onDataUpdate, }; }然后在仪表盘组件中使用这个钩子并集成ECharts!-- components/Dashboard.vue -- template div classdashboard div classstatus-bar 连接状态: span :class[status, isConnected ? connected : disconnected] {{ isConnected ? 已连接 : 未连接 }} /span button clicktoggleSubscription {{ isSubscribed ? 取消订阅 : 订阅服务器指标 }} /button /div div classcharts div refcpuChartEl classchart-container/div div refmemoryChartEl classchart-container/div /div div classraw-data h3实时数据流/h3 pre{{ latestData }}/pre /div /div /template script setup import { ref, onMounted, onUnmounted, nextTick } from vue; import * as echarts from echarts; import { useSocket } from /composables/useSocket; const { isConnected, subscribe, unsubscribe, onDataUpdate } useSocket(http://localhost:3001); const isSubscribed ref(false); const latestData ref(null); const cpuChartEl ref(null); const memoryChartEl ref(null); let cpuChart null; let memoryChart null; const cpuData ref([]); const memoryData ref([]); const MAX_DATA_POINTS 60; // 在图表中保留最近60个点 const initChart (chartInstance, domElement, title, dataRef) { if (!chartInstance domElement.value) { chartInstance echarts.init(domElement.value); const option { title: { text: title, left: center }, tooltip: { trigger: axis }, xAxis: { type: time }, yAxis: { type: value, min: 0, max: 100 }, series: [{ name: title, type: line, smooth: true, data: dataRef.value, markLine: { silent: true, data: [{ yAxis: 80, lineStyle: { color: #ff9800 } }, { yAxis: 95, lineStyle: { color: #f44336 } }] } }] }; chartInstance.setOption(option); } return chartInstance; }; const updateChart (chartInstance, newValue, timestamp, dataRef) { dataRef.value.push([timestamp, newValue]); if (dataRef.value.length MAX_DATA_POINTS) { dataRef.value.shift(); } if (chartInstance) { chartInstance.setOption({ series: [{ data: dataRef.value }] }); } }; onMounted(() { nextTick(() { cpuChart initChart(cpuChart, cpuChartEl, CPU使用率 (%), cpuData); memoryChart initChart(memoryChart, memoryChartEl, 内存使用率 (%), memoryData); }); // 监听实时数据 onDataUpdate((data) { latestData.value data; const ts new Date(data.timestamp); updateChart(cpuChart, data.metrics.cpu, ts, cpuData); updateChart(memoryChart, data.metrics.memory, ts, memoryData); }); }); const toggleSubscription () { const dataSourceId server_metrics_001; if (!isSubscribed.value) { subscribe(dataSourceId); isSubscribed.value true; } else { unsubscribe(dataSourceId); isSubscribed.value false; } }; onUnmounted(() { if (cpuChart) { cpuChart.dispose(); cpuChart null; } if (memoryChart) { memoryChart.dispose(); memoryChart null; } }); /script3.3 数据采集器一个通用的Python Agent示例数据采集器需要稳定、轻量且能处理异常。下面是一个Python Agent的框架可以定期收集系统指标并通过HTTP POST发送到Aura后端。# agent/collector.py import psutil import requests import time import logging from datetime import datetime from typing import Dict, Any logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) class SystemMetricsCollector: def __init__(self, aura_server_url: str, source_id: str, interval: int 5): self.server_url aura_server_url.rstrip(/) self.source_id source_id self.interval interval self.headers {Content-Type: application/json} def collect_metrics(self) - Dict[str, Any]: 收集系统指标 try: cpu_percent psutil.cpu_percent(intervalNone) # 非阻塞式获取 memory psutil.virtual_memory() disk psutil.disk_usage(/) load_avg psutil.getloadavg() metrics { source_id: self.source_id, timestamp: datetime.utcnow().isoformat() Z, metrics: { cpu: round(cpu_percent, 2), memory_used_percent: round(memory.percent, 2), memory_used_gb: round(memory.used / (1024**3), 2), disk_used_percent: round(disk.percent, 2), load_1min: round(load_avg[0], 2), load_5min: round(load_avg[1], 2), load_15min: round(load_avg[2], 2), } } return metrics except Exception as e: logger.error(f收集指标时出错: {e}) return {} def send_metrics(self, metrics: Dict[str, Any]) - bool: 发送指标到Aura服务器 if not metrics: return False endpoint f{self.server_url}/api/ingest # 假设后端有 /api/ingest 接收端点 try: response requests.post(endpoint, jsonmetrics, headersself.headers, timeout10) if response.status_code 200: logger.debug(f指标发送成功: {metrics[timestamp]}) return True else: logger.warning(f服务器响应异常: {response.status_code} - {response.text}) return False except requests.exceptions.RequestException as e: logger.error(f发送请求失败: {e}) return False def run(self): 主循环 logger.info(f启动指标采集器源ID: {self.source_id}, 上报至: {self.server_url}) while True: try: metrics self.collect_metrics() if metrics: self.send_metrics(metrics) time.sleep(self.interval) except KeyboardInterrupt: logger.info(收到中断信号停止采集。) break except Exception as e: logger.error(f主循环运行出错: {e}) time.sleep(self.interval) # 出错后等待一个周期再继续 if __name__ __main__: # 配置信息应从环境变量或配置文件中读取 SERVER_URL http://your-aura-server.com SOURCE_ID prod_server_01 collector SystemMetricsCollector(SERVER_URL, SOURCE_ID, interval10) collector.run()这个采集器可以作为一个系统服务如 systemd 服务或 Windows 服务在后台运行。4. 部署、配置与安全考量4.1 环境配置与部署一个完整的Project-Aura需要部署多个组件。后端服务可以使用Docker进行容器化部署这能保证环境一致性。# Dockerfile for Aura Backend FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --onlyproduction COPY . . EXPOSE 3001 CMD [node, server.js]使用docker-compose.yml可以方便地编排后端、数据库和Redis。version: 3.8 services: postgres: image: postgres:15-alpine environment: POSTGRES_DB: aura POSTGRES_USER: aura_user POSTGRES_PASSWORD: your_secure_password volumes: - postgres_data:/var/lib/postgresql/data ports: - 5432:5432 redis: image: redis:7-alpine ports: - 6379:6379 aura-backend: build: ./backend depends_on: - postgres - redis environment: DATABASE_URL: postgresql://aura_user:your_secure_passwordpostgres:5432/aura REDIS_URL: redis://redis:6379 ports: - 3001:3001 restart: unless-stopped volumes: postgres_data:前端服务构建静态文件后可以通过Nginx或直接托管在Vercel/Netlify等平台。# 在前端项目目录 npm run build # 生成的 dist 目录就是静态资源采集器Agent在目标服务器上可以通过systemd来管理。# /etc/systemd/system/aura-agent.service [Unit] DescriptionAura Metrics Collection Agent Afternetwork.target [Service] Typesimple Useraura WorkingDirectory/opt/aura-agent ExecStart/usr/bin/python3 /opt/aura-agent/collector.py Restarton-failure RestartSec10 [Install] WantedBymulti-user.target4.2 安全与权限控制个人项目也不能忽视安全。API认证采集器向后端发送数据时不应完全开放。最简单的方案是使用API Key。在采集器配置和Aura后端中设置相同的密钥后端验证请求头中的X-API-Key。# 在采集器发送请求时添加Header self.headers { Content-Type: application/json, X-API-Key: os.getenv(AURA_API_KEY) }// 在后端Express中验证中间件 app.use(/api/ingest, (req, res, next) { const apiKey req.header(X-API-Key); if (apiKey ! process.env.API_KEY) { return res.status(403).json({ error: Forbidden }); } next(); });WebSocket连接验证在Socket.IO连接建立时进行验证。io.use((socket, next) { const token socket.handshake.auth.token; if (isValidToken(token)) { // 实现你自己的验证逻辑 next(); } else { next(new Error(Authentication error)); } });数据库安全永远不要使用默认密码使用强密码并限制数据库的访问IP。在Docker Compose中密码通过环境变量传入。前端环境变量将后端API地址、WebSocket地址等配置在.env文件中构建时注入。5. 常见问题排查与性能优化在实际运行中你肯定会遇到各种问题。以下是一些典型场景和解决思路。5.1 连接与通信问题问题现象可能原因排查步骤与解决方案前端无法连接到WebSocket1. 后端服务未运行或端口错误。2. 跨域CORS问题。3. 防火墙或网络策略阻止。1. 检查后端服务日志确认端口监听正常 (netstat -tlnp)。2. 确认Socket.IO服务器配置了正确的前端源地址。3. 检查服务器安全组/防火墙规则是否放行了WebSocket端口如3001。连接频繁断开重连1. 网络不稳定。2. 代理服务器如Nginx配置不当未支持WebSocket长连接。3. 客户端/服务器负载过高。1. 检查网络状况。2. 如果使用了Nginx反向代理确保配置中包含对Upgrade和Connection头的转发nginxbrlocation /socket.io/ {br proxy_pass http://aura-backend;br proxy_http_version 1.1;br proxy_set_header Upgrade $http_upgrade;br proxy_set_header Connection upgrade;br proxy_set_header Host $host;br}br3. 监控服务器资源优化代码减少不必要的广播。前端收不到数据更新1. 订阅subscribe事件未成功发送或后端未处理。2. 数据源ID不匹配。3. 后端广播逻辑有误。1. 打开浏览器开发者工具的“网络”-“WS”标签查看WebSocket消息流确认subscribe事件已发出。2. 核对前端订阅的dataSourceId和后端模拟/采集器发送的sourceId是否完全一致。3. 在后端simulateDataUpdate函数中添加日志确认找到了订阅者并执行了emit。5.2 数据与性能问题问题现象可能原因排查步骤与解决方案数据库插入慢CPU占用高1. 采集频率过高写入过于频繁。2. 数据库表缺少索引查询慢拖累写入。3. 单条插入效率低。1. 调整采集器interval对于监控场景5-15秒的间隔通常足够。2. 为source_id和timestamp字段创建复合索引CREATE INDEX idx_metrics_source_time ON metrics (source_id, timestamp DESC);。3. 考虑使用批量插入Bulk Insert例如每收集10条数据再写入一次。前端图表卡顿1. 数据点过多图表渲染压力大。2. WebSocket消息过于频繁Vue响应式更新开销大。3. 内存泄漏旧的图表实例未销毁。1. 像我们示例中一样限制图表中显示的数据点数量如MAX_DATA_POINTS。2. 在后端进行数据聚合降低推送频率或在前端进行防抖throttle处理。3. 确保在Vue组件卸载时onUnmounted调用ECharts实例的dispose()方法。采集器无法上报数据1. API Key配置错误或缺失。2. 目标服务器URL错误或网络不通。3. 依赖库如psutil未安装或权限不足。1. 检查采集器日志确认请求头中包含了正确的API Key。2. 使用curl或wget手动测试Aura后端的/api/ingest端点是否可达。3. 确保Python环境中已安装psutil和requests库并且运行Agent的用户有权限读取系统信息。5.3 扩展性与维护支持更多数据源设计一个插件式的采集器架构。定义一个统一的Collector接口不同的数据源如Docker状态、特定API、日志文件实现这个接口通过配置文件动态加载。配置化管理将数据源定义、图表配置、告警规则等从代码中抽离使用YAML或JSON配置文件甚至设计一个简单的管理界面来动态配置。告警功能这是监控系统的核心价值延伸。可以在后端增加一个告警引擎定期检查存储的数据当某个指标超过阈值时通过邮件、Slack、钉钉Webhook等方式发送通知。数据保留策略原始监控数据会快速增长。需要在PostgreSQL中设置定时任务如使用pg_cron扩展定期删除过期的历史数据或者将旧数据转移到更廉价的存储中。构建一个像Project-Aura这样的项目最大的收获不在于实现了一个多么强大的工具而在于亲手实践了从数据采集、传输、存储到可视化的完整数据流闭环。在这个过程中你会深刻理解实时系统的挑战、不同数据库的选型权衡、前后端协同的细节以及如何让一个系统从“能跑”到“跑得稳”。当你看到自己服务器的心跳以优美的曲线在屏幕上实时跃动时那种对数字世界的掌控感和成就感正是驱动我们不断构建的精髓所在。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2592897.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…