当前位置: 首页 > news >正文

Vue3 + Node.js 实现客服实时聊天系统(WebSocket + Socket.IO 详解)

Node.js 实现客服实时聊天系统(WebSocket + Socket.IO 详解)

一、为什么选择 WebSocket?

想象一下淘宝客服的聊天窗口:你发消息,客服立刻就能看到并回复。这种即时通讯效果是如何实现的呢?我们使用 Vue3 作为前端框架,Node.js 作为后端,通过 WebSocket+ Socket.IO 协议实现实时通信。

1.1 实时通信的痛点

传统 HTTP 协议就像打电话:客户端发起请求 → 服务器响应 → 挂断连接。要实现实时聊天需要频繁"拨号",这就是长轮询(不断发送请求问:“有新消息吗?”),既浪费资源又延迟高。

1.2 传统 HTTP 的局限性

传统 HTTP 协议 就像写信

  • 必须你先发请求,服务器才能回复

  • 每次都要重新建立连接

  • 服务器无法主动"推"消息给你

1.3 WebSocket 的优势

WebSocket 就像 打电话

  • 一次连接,持续通话
  • 双向实时通信
  • 低延迟,高效率
1.3 Socket.IO 的价值

原生 WebSocket 存在兼容性问题,Socket.IO 提供了:

  • 自动降级(不支持 WS 时回退到轮询)
  • 断线自动重连
  • 房间/命名空间管理
  • 简单的 API 设计

以下是传统HTTP、WebSocket和Socket.IO的对比表格,清晰展示它们的区别和特点:

特性传统HTTPWebSocketSocket.IO
通信模式单向通信(客户端发起)全双工通信全双工通信
连接方式短连接(每次请求后断开)长连接(一次连接持续通信)长连接(自动管理连接)
实时性低(依赖轮询)高(实时推送)高(实时推送)
资源消耗高(重复建立连接和头部开销)低(无重复头部)低(优化传输)
兼容性所有浏览器支持现代浏览器支持自动降级(不支持WebSocket时回退到轮询)
额外功能基础通信断线重连房间管理命名空间二进制传输ACK确认机制
比喻写信(一来一回,每次重新寄信)打电话(接通后持续通话)智能对讲机(自动重连、多频道支持)
适用场景静态资源获取、表单提交实时聊天、股票行情复杂实时应用(游戏、协同编辑、在线客服)
关键点总结:
  1. 传统HTTP:简单但效率低,无法主动推送。
  2. WebSocket:真正双向实时通信,但需处理兼容性和连接管理。
  3. Socket.IO:在WebSocket基础上封装,提供更健壮的解决方案,适合生产环境。

通过表格可以直观看出:Socket.IO是WebSocket的超集,解决了原生API的痛点,同时保留了所有优势。

二、深入解析实时聊天服务端实现(基于Socket.IO)

环境搭建

const http = require('http');
// 初始化Express应用
const app = express();
const server = http.createServer(app);
// 创建WebScoket服务器
const io = socketIo(server, {cors: {origin: "http://192.168.1.3:8080", // 你的前端地址origin: '*',methods: ['GET', 'POST']}
});
// ...
server.listen(3000, async () => {console.log(`Server is running on port 3000`);
});

接下来我会对我后端代码进行详细解析:

一、核心架构解析

1.1 用户连接管理
const userSocketMap = new Map(); // 用户ID到socket.id的映射
const userHeartbeats = new Map(); // 用户心跳检测

设计要点:

  • userSocketMap 维护用户ID与Socket实例的映射关系,实现快速查找
  • userHeartbeats 用于检测用户是否在线(心跳机制)
  • 双Map结构确保用户状态管理的可靠性
1.2 连接事件处理
io.on("connection", async (socket) => {// 所有连接逻辑在这里处理
});

生命周期:

  1. 客户端通过WebSocket连接服务端
  2. 服务端创建socket实例并触发connection事件
  3. 在回调中设置各种事件监听器

二、关键功能模块详解

2.1 用户登录认证
// 当客户端发送 'login' 事件时,触发这个回调函数
socket.on('login', ({ userId, csId }) => {// 参数验证:确保传入的参数是字符串类型userId = String(userId); // 将 userId 转换为字符串,统一类型csId = String(csId); // 将 csId 转换为字符串,表示要聊天的客户id// 存储关联关系:将用户信息与当前 socket 连接关联起来socket.userId = userId; // 将 userId 存储到当前 socket 对象中socket.csId = csId; // 将 csId 存储到当前 socket 对象中userSocketMap.set(userId, socket.id); // 在 userSocketMap 中存储 userId 和 socket.id 的映射关系// 加入房间:根据 csId 创建一个房间,用户加入该房间const room = `room-${csId}`; // 使用 csId 构造房间名称socket.join(room); // 让当前用户加入这个房间// 广播在线状态:通知所有客户端当前用户的在线状态io.emit('user_online', userId); // 发送 'user_online' 事件,通知用户上线io.emit('Online_user', Array.from(userSocketMap.entries())); // 发送 'Online_user' 事件,包含所有在线用户的信息
});

代码功能总结:

  1. 参数验证:确保传入的 userIdcsId 是字符串类型。
  2. 存储关联关系:将用户信息(userIdcsId)存储到当前 socket 对象中,并在 userSocketMap 中存储用户与 socket 的映射关系。
  3. 加入房间:根据 csId 创建一个房间,并让用户加入该房间。
  4. 广播在线状态:通过 io.emit 广播用户的在线状态,通知所有客户端当前用户的上线情况,并发送所有在线用户的信息。

关键点:

  • 强制类型转换确保数据一致性
  • 使用join()方法实现房间功能
  • 实时广播用户在线状态
2.2 房间成员管理
// 当客户端发送 'all_member' 事件时,触发这个回调函数
socket.on('all_member', async () => {// 根据当前用户的 csId 构造房间名称const room = `room-${socket.csId}`;// 获取房间内所有用户的 socket 实例const sockets = await io.in(room).fetchSockets();  // 使用 io.in(room).fetchSockets() 获取房间内的所有 socket 实例// 提取房间内所有用户的 userIdconst users = sockets.map(s => s.userId);  // 从每个 socket 实例中提取 userId,形成一个用户 ID 数组// 数据库查询优化:查询房间内用户的详细信息及未读消息数量const [results] = await pool.query(`SELECT u.id, u.role, u.username,  // 查询用户的基本信息:用户 ID、角色、用户名COUNT(m.id) AS message_count  // 查询未读消息的数量FROM users uLEFT JOIN messages m ON u.id = m.sender_id  // 关联消息表,找到发送给当前用户的消息AND m.receiver_id = ?  // 限定消息的接收者是当前用户AND m.read_at IS NULL  // 限定消息未被阅读WHERE u.id IN (?)  // 限定用户 ID 在房间内用户列表中GROUP BY u.id  // 按用户 ID 分组,确保每个用户只返回一条记录`, [socket.userId, users]);  // 查询参数:当前用户的 ID 和房间内用户 ID 列表// 将查询结果发送回客户端socket.emit('myUsersList', results);  // 发送 'myUsersList' 事件,将查询结果传递给客户端
});

代码功能总结:

  1. 获取房间信息
    • 根据当前用户的 csId 构造房间名称。
    • 使用 io.in(room).fetchSockets() 获取房间内所有用户的 socket 实例。
    • 从每个 socket 实例中提取 userId,形成一个用户 ID 数组。
  2. 数据库查询
    • 查询房间内用户的详细信息,包括用户的基本信息(idroleusername)。
    • 查询每个用户发送给当前用户且未被阅读的消息数量(message_count)。
    • 使用 LEFT JOIN 关联 messages 表,筛选出未读消息。
    • 使用 GROUP BY 确保每个用户只返回一条记录。
  3. 发送结果
    • 将查询结果通过 socket.emit 发送给当前用户,事件名称为 myUsersList

优化技巧:

  • 使用fetchSockets()获取房间内所有socket实例
  • 单次SQL查询获取用户信息+未读消息数
  • LEFT JOIN确保离线用户也能被查询到
2.3 私聊消息处理
// 当客户端发送 'private_message' 事件时,触发这个回调函数
socket.on("private_message", async (data) => {// 获取接收者的 socket.idconst receiverSocketId = userSocketMap.get(String(data.receiverId)); // 从 userSocketMap 中根据接收者的 userId 获取对应的 socket.id// 实时消息推送:将消息发送给接收者if (receiverSocketId) { // 如果接收者在线(存在对应的 socket.id)io.to(receiverSocketId).emit('new_private_message', { // 向接收者的 socket 发送 'new_private_message' 事件senderId: data.senderId, // 发送者的 IDcontent: data.content, // 消息内容timestamp: new Date() // 消息发送的时间戳});}// 消息持久化:将消息存储到数据库中await pool.execute( // 使用数据库连接池执行 SQL 插入语句'INSERT INTO messages VALUES (?, ?, ?, ?)', // 插入消息到 messages 表[data.senderId, data.receiverId, data.content, new Date()] // 插入的值:发送者 ID、接收者 ID、消息内容、消息发送时间);
});

代码功能总结:

  1. 获取接收者的 socket.id
    • userSocketMap 中根据接收者的 userId 获取对应的 socket.id
  2. 实时消息推送
    • 如果接收者在线(存在对应的 socket.id),则使用 io.to(receiverSocketId).emit 向接收者的 socket 发送 new_private_message 事件,包含发送者的 ID、消息内容和时间戳。
  3. 消息持久化
    • 将消息存储到数据库中,插入到 messages 表中,记录发送者 ID、接收者 ID、消息内容和发送时间。

消息流设计:

  1. 通过Map快速查找接收者socket
  2. 使用io.to(socketId).emit()实现点对点推送
  3. 异步存储到MySQL确保数据不丢失
2.4 断连处理机制
socket.on('disconnect', () => {userSocketMap.delete(socket.userId);io.emit('user_offline', socket.userId);io.emit('update_member_list');
});

容错设计:

  • 及时清理映射关系防止内存泄漏
  • 广播离线事件通知所有客户端
  • 触发成员列表更新

三、高级功能实现

3.1 心跳检测系统
// 心跳接收:客户端发送心跳信号时,更新用户的心跳时间
socket.on('heartbeat', () => {userHeartbeats.set(socket.userId, Date.now()); // 将当前用户的心跳时间更新为当前时间戳
});// 定时检测:每隔一段时间检查用户是否离线
setInterval(() => {const now = Date.now(); // 获取当前时间戳for (const [userId, lastTime] of userHeartbeats) { // 遍历 userHeartbeats 中的每个用户及其最后心跳时间if (now - lastTime > 4000) { // 如果当前时间与最后心跳时间的差值超过 4000 毫秒(4 秒)// 清理离线用户userSocketMap.delete(userId); // 从 userSocketMap 中删除该用户,表示用户已离线io.emit('user_offline', userId); // 广播 'user_offline' 事件,通知所有客户端该用户已离线}}
}, 2000); // 每隔 2000 毫秒(2 秒)执行一次定时检测

代码功能总结

  1. 心跳接收
    • 当客户端发送 heartbeat 事件时,更新 userHeartbeats 中对应用户的心跳时间,记录为当前时间戳。
  2. 定时检测
    • 使用 setInterval 每隔 2 秒执行一次检测。
    • 遍历 userHeartbeats 中的每个用户及其最后心跳时间。
    • 如果当前时间与最后心跳时间的差值超过 4 秒,认为用户已离线。
    • userSocketMap 中删除该用户,并广播 user_offline 事件,通知所有客户端该用户已离线。

关键点解释

  • 心跳机制:客户端定期发送心跳信号(heartbeat 事件),服务器记录每次心跳的时间。如果超过一定时间(4 秒)没有收到心跳,认为用户离线。
  • 定时检测:每隔 2 秒检查一次,确保及时清理离线用户并通知其他客户端。

心跳参数建议:

  • 客户端每2秒发送一次心跳
  • 服务端4秒未收到视为离线
  • 检测间隔应小于超时时间
3.2 调试信息输出
setInterval(() => {console.log('\n当前连接状态:');console.log('用户映射:', Array.from(userSocketMap.entries()));io.sockets.forEach(socket => {console.log(`SocketID: ${socket.id}, User: ${socket.userId}`);});
}, 30000);

调试技巧:

  • 定期打印连接状态
  • 输出完整的用户映射关系
  • 生产环境可替换为日志系统

四、性能优化建议

  1. Redis集成

    // 使用Redis存储映射关系
    const redisClient = require('redis').createClient();
    await redisClient.set(`user:${userId}:socket`, socket.id);
    
  2. 消息分片

    // 大消息分片处理
    socket.on('message_chunk', (chunk) => {// 重组逻辑...
    });
    
  3. 负载均衡

    # Nginx配置
    location /socket.io/ {proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";proxy_pass http://socket_nodes;
    }
    

五、常见问题解决方案

问题1:Map内存泄漏

  • 解决方案:双重清理(disconnect + 心跳检测)

问题2:消息顺序错乱

  • 解决方案:客户端添加消息序列号

问题3:跨节点通信

  • 解决方案:使用Redis适配器
    npm install @socket.io/redis-adapter
    
    const { createAdapter } = require("@socket.io/redis-adapter");
    io.adapter(createAdapter(redisClient, redisClient.duplicate()));
    

通过以上实现,您的聊天系统将具备:

  • 完善的用户状态管理
  • 可靠的私聊功能
  • 高效的心跳机制
  • 良好的可扩展性

建议在生产环境中添加:

  1. JWT认证
  2. 消息加密
  3. 限流防护
  4. 监控告警系统

相关文章:

Vue3 + Node.js 实现客服实时聊天系统(WebSocket + Socket.IO 详解)

Node.js 实现客服实时聊天系统(WebSocket Socket.IO 详解) 一、为什么选择 WebSocket? 想象一下淘宝客服的聊天窗口:你发消息,客服立刻就能看到并回复。这种即时通讯效果是如何实现的呢?我们使用 Vue3 作…...

python 上海新闻爬虫

1. 起因, 目的: 继续做新闻爬虫。我之前写过。此文先记录2个新闻来源。后面打算进行过滤,比如只选出某一个类型新闻。 2. 先看效果 过滤出某种类型的新闻,然后生成 html 页面,而且,自动打开这个页面。 比如科技犯罪…...

【Axure高保真原型】中继器表格批量上传数据

今天和大家分享中继器表格批量上传数据的原型模板,效果包括: 点击上传按钮,可以真实的打开本地文件夹选择文件; 选择的文件如果不是表格格式(xls、xlsx、xlt、csv),就会显示提示弹窗&#xff1…...

复刻低成本机械臂 SO-ARM100 单关节控制(附代码)

视频讲解: 复刻低成本机械臂 SO-ARM100 单关节控制(附代码) 代码仓库:GitHub - LitchiCheng/SO-ARM100: Some Test code on SO-ARM100 昨天用bambot的web的方式调试了整个机械臂,对于后面的仿真的sim2real来说&#x…...

视频编解码学习7之视频编码简介

视频编码技术发展历程与主流编码标准详解 视频编码技术是现代数字媒体领域的核心技术之一,它通过高效的压缩算法大幅减少了视频数据的体积,使得视频的存储、传输和播放变得更加高效和经济。从早期的H.261标准到最新的AV1和H.266/VVC,视频编码…...

【NextPilot日志移植】整体功能概要

整体日志系统的实现功能 该日志系统主要实现了飞行日志的记录功能,支持多种日志记录模式,可将日志存储到文件或通过 MAVLink 协议传输,同时具备日志加密、空间管理、事件记录等功能。具体如下: 日志记录模式:支持按武…...

Windows系统下使用Kafka和Zookeeper,Python运行kafka(二)

1.配置 Zookeeper 进入解压后的 Zookeeper 目录(例如 F:\zookeeper\conf),复制 zoo_sample.cfg 文件并命名为 zoo.cfg(如果 zoo.cfg 已经存在,则直接编辑该文件)。 打开 zoo.cfg 文件,配置相关…...

《构建社交应用用户激励引擎:React Native与Flutter实战解析》

React Native凭借其与JavaScript和React的紧密联系,为开发者提供了一个熟悉且灵活的开发环境。在构建用户等级体系时,它能够充分利用现有的前端开发知识和工具。通过将用户在社交应用中的各种行为进行量化,比如发布动态的数量、点赞评论的次数…...

Oracle OCP认证考试考点详解083系列13

题记: 本系列主要讲解Oracle OCP认证考试考点(题目),适用于19C/21C,跟着学OCP考试必过。 61. 第61题: 题目 解析及答案: 关于基于RPM的Oracle数据库安装,以下哪两项是正确的? A) …...

【AI】DeepWiki 页面转换成 Markdown 保存 - Chrome 扩展

GitHub: https://github.com/zxmfke/deepwiki-md-chrome-extension 背景 个人比较喜欢整理项目架构,更多都是保存成 markdown 的格式保存,然后发博客。deepwiki 刚好把 github 仓库代码的架构输出出来了,不过没有办法下载成 markdown 格式&…...

HTTP 状态码是服务器对客户端请求的响应标识,用于表示请求的处理结果

以下是完整的 HTTP 状态码分类和常见状态码详解: 一、状态码分类(5大类) 分类范围描述常见场景1xx100-199信息性响应请求已被接收,继续处理2xx200-299成功响应请求成功处理3xx300-399重定向响应需要进一步操作4xx400-499客户端错…...

【AI论文】FlexiAct:在异构场景中实现灵活的动作控制

摘要:动作定制涉及生成视频,其中主体执行由输入控制信号指示的动作。 当前的方法使用姿势引导或全局运动定制,但受到空间结构(如布局、骨架和视点一致性)严格约束的限制,降低了在不同主题和场景下的适应性。…...

ubuntu24.04安装anaconda

1. ubuntu安装ananconda 进入官网:添加链接描述 直接点击Download下载,它会自动匹配合适的版本 打开保存下载文件,点击右键,选择在终端打开,输入 bash Anaconda3-2024.10-1-Linux-x86_64.sh不断点击Enter&#xff0c…...

六、Hadoop初始化与启动

成功部署一个Hadoop集群并不仅仅是安装好软件那么简单。在它真正能够为我们处理海量数据之前,还需要一系列精心的初始化和启动步骤。这些步骤确保了各个组件能够正确协同工作。完成启动后,Hadoop还提供了便捷的 Web 用户界面 (Web UI),帮助我…...

边缘网关(边缘计算)

边缘网关是边缘计算架构中的关键组件,充当连接终端设备(如传感器、IoT设备)与云端或核心网络的桥梁。它在数据源头附近进行实时处理、分析和过滤,显著提升效率并降低延迟。 核心功能 协议转换 ○ 支持多种通信协议(如…...

学成在线之课程管理

一:业务概述 我负责的课程管理这一块,可以发布课程,可以对课程列表进行一个管理,发布课程这分为三步:首先是需要进行填写课程相关的信息,再设计这个课程的大纲,最后是选择发布这门课程&#xff…...

python里面的class,类,方法,函数,def

一、ds 好的!我将用专业术语结合通俗解释来梳理这些概念,并用结构化方式呈现它们的关系: 1. 核心概念解析 类 (Class) 定义:类是面向对象编程(OOP)中的核心概念,是创建对象的模板(蓝图)。它封装了一组属性(数据)和方法(行为),用于描述具有相同特征和功能的对象…...

复盘20250508

根据行业趋势、政策支持、公司基本面及技术壁垒,我推荐以下两支最可能持续上涨的个股,并深度分析原因: 1. 奥普光电(机器视觉光刻机芯片) 核心逻辑: 光刻机国产化核心标的:控股股东长春光机所…...

数据结构 - 10( B- 树 B+ 树 B* 树 4000 字详解 )

一:B- 树 1.1 B- 树的引入 在使用二叉搜索树对数据进行排序时,存在一个缺陷:随着数据量的增大,二叉搜索树的高度也会随之增加。虽然在数据量较小时,这种情况并不明显,但当数据量变得庞大时,树…...

算法与数据结构 - 常用图算法总结

在图论中,图算法非常重要,广泛应用于计算机科学、网络分析、社交网络、地理信息系统等领域。下面是一些常用的图算法,按不同功能和应用场景分类: 1. 图的遍历 图遍历算法用于遍历图中的节点和边。主要有两种常见的图遍历方法&am…...

涨薪技术|0到1学会性能测试第53课-Tomcat配置

前面的推文我们掌握了Tomcat服务器的3种监控技术知识。今天给大家分享Tomcat调优技术。后续文章都会系统分享干货,带大家从0到1学会性能测试。 01Tomcat配置 当Tomcat服务器安装好并开始运行后,需要对服务器进行一些基本配置,通常关于Tomcat服务器的配置包括两部分: 第一:…...

亚马逊推出新型仓储机器人 Vulcan:具备“触觉”但不会取代人类工人

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...

后退n帧协议

滑动窗口机制(Sliding Window) 发送方有一个发送窗口,最多可以连续发送 N 个未确认的帧(N 就是窗口大小)。 接收方通常只有一个接收窗口,只接收按序到达的帧,不接受乱序帧。 累计确认机制&…...

R9周:RNN实现阿尔茨海默病诊断

🍨 本文为🔗365天深度学习训练营中的学习记录博客 🍖 原作者:K同学啊 一、导入数据 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import torch import torch.nn as nn f…...

node.js 实战——在express 中将input file 美化,并完成裁剪、上传进度条

美化上传按钮 在ejs 页面 <!DOCTYPE html> <html> <head><meta charset"utf-8"></meta><title><% title %></title><link relstylesheet href/stylesheets/form.css/><!-- 本地 Bootstrap 引入方式 -->…...

Linux环境下部署MaxScale

测试环境&#xff1a;两台服务器&#xff0c;Mysql版本 8.0&#xff0c;linux版本&#xff1a;Ubuntu 20.04.3&#xff1b; 介绍 在我之前的文章里面有介绍MySql主从服务器的配置&#xff0c;我们项目通常使用.NET开发Server端&#xff0c;如果是代码直接去管理主从服务器的访…...

新能源汽车CAN通信深度解析:MCU、VCU、ECU协同工作原理

1. 什么是CAN通信&#xff1f; CAN&#xff08;Controller Area Network&#xff0c;控制器局域网&#xff09; 是一种广泛应用于汽车电子系统的串行通信协议&#xff0c;由德国Bosch公司在1980年代开发&#xff0c;主要用于实现车内电子控制单元&#xff08;ECU&#xff09;之…...

按句子切分文本、保留 token 对齐信息、**适配 tokenizer(如 BERT)**这种需求

在之前的文章中我解释了 把长文本切分成一句一句的小段&#xff08;chunk&#xff09;&#xff0c;每一段尽量是一个完整的句子&#xff0c;而不是强行按字数截断。 但是这个方法自己写会比较复杂&#xff0c;有很多处理这种场景的工具可以直接拿来用。 下面就 处理按句子切分…...

缓存(1):三级缓存

三级缓存是指什么 我们常说的三级缓存如下&#xff1a; CPU三级缓存Spring三级缓存应用架构&#xff08;JVM、分布式缓存、db&#xff09;三级缓存 CPU 基本概念 CPU 的访问速度每 18 个月就会翻 倍&#xff0c;相当于每年增⻓ 60% 左右&#xff0c;内存的速度当然也会不断…...

Kubernetes client-go 客户端类型与初始化指南

Kubernetes client-go 客户端类型与初始化指南 在 Kubernetes 的 client-go 库中&#xff0c;存在多种客户端用于与 API 服务器交互。以下介绍主要客户端类型&#xff0c;包括用途、初始化方式及 Demo。 1. RESTClient 用途 RESTClient 是底层 REST 客户端&#xff0c;直接…...

【金仓数据库征文】金仓数据库:创新驱动,引领数据库行业新未来

一、引言 在数字化转型的时代洪流中&#xff0c;数据已跃升为企业的核心资产&#xff0c;宛如企业运营与发展的 “数字命脉”。从企业日常运营的精细化管理&#xff0c;到战略决策的高瞻远瞩制定&#xff1b;从客户关系管理的深度耕耘&#xff0c;到供应链优化的全面协同&…...

图漾相机——Sample_V2示例程序(待补充)

文章目录 1.SDK支持的平台类型1.1 Windows 平台1.2 Linux平台 2.Sample_V2编译流程2.1 Windows环境2.2 Linux环境编译 3.Sample_V2示例程序测试3.1 ListDevice_v23.2 DepthStream_v23.3 ExposureTimeSetting_v23.4 ForceDeviceIP_v23.5 GetCalibData_v23.6 NetStatistic_v23.7 …...

手写 vue 源码 ===:自定义调度器、递归调用规避与深度代理

目录 引言 自定义调度器&#xff08;Scheduler&#xff09; 什么是调度器&#xff1f; 调度器的实现原理 自定义调度器的实际应用 切面编程&#xff08;AOP&#xff09;思想在调度器中的应用 递归调用规避 递归调用的问题 Vue 如何规避递归调用 深度代理&#xff08;D…...

WPF实时调试的一种实现方法

在WPF程序中&#xff0c;如果我们需要对程序进行调试&#xff0c;一般是使用断点/单步或输出日志之类的调试方法。 如果我们需要实时查看程序输出&#xff0c;可以将程序的输出类型修改为控制台应用程序 这样我们在程序运行后&#xff0c;就可以得到一个控制台窗口。 然后再配…...

数据库操作

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人能接…...

学习笔记:数据库——事务

1.内容&#xff1a; 基于现有数据库设计检查点实验&#xff0c;观察比较提交前后执行结果并分析。 2.实现 源码 -- 开启事务 START TRANSACTION;-- 插入一条订单记录&#xff08;客户ID为10002&#xff09; INSERT INTO orders (o_date, c_id) VALUES (NOW(), 10002);-- 获…...

企业级可观测性实现:OpenObserve云原生平台的本地化部署与远程访问解析

文章目录 前言1. 安装Docker2. 创建并启动OpenObserve容器3. 本地访问测试4. 公网访问本地部署的OpenObserve4.1 内网穿透工具安装4.2 创建公网地址 5. 配置固定公网地址 前言 嘿&#xff0c;各位小伙伴们&#xff0c;今天要给大家揭秘一个在云原生领域里横扫千军的秘密法宝—…...

【Linux系统】第三节—权限

Hello&#xff0c;好久不见—— 云边有个稻草人-CSDN个人博客主页 Linux-本节文章所属专栏-欢迎订阅-持续更新中~~~ 目录 hi&#xff01;在这里—本节课重要知识点详解 一、Shell命令以及运行原理 二、Linux权限 2.1 Linux权限的概念 2.2 Linux权限管理 2.3 ⽂件权限值的…...

@Data和 @NoArgsConstructor注解详解

Data 和 NoArgsConstructor 注解详解 1. Data 注解 作用&#xff1a;Data 是 Lombok 提供的一个复合注解&#xff0c;用于自动生成 Java 类的常用方法&#xff0c;减少样板代码。生成的内容&#xff1a; Getter 和 Setter&#xff1a;为所有非静态、非 final 字段生成 getter…...

《云计算》第三版总结

《云计算》第三版总结 云计算体系结构 云计算成本优势 开源云计算架构Hadoop2.0 Hadoop体系架构 Hadoop访问接口Hadoop编程接口 Hadoop大家族 分布式组件概述ZooKeeperHbasePigHiveOozieFlumeMahout 虚拟化技术 服务器虚拟化存储虚拟化网络虚拟化桌面虚拟化OpenStack开源虚…...

滚珠导轨:电子制造领域精密运动的核心支撑

电子制造正朝着高精度、高效率方向飞速发展&#xff0c;滚珠导轨在这一进程中扮演着重要角色。滚珠导轨在电子制造领域中具有广泛且重要的应用&#xff0c;主要体现在以下几个方面&#xff1a; 1、印刷电路板&#xff08;PCB&#xff09;制造设备&#xff1a;滚珠导轨在PCB制造…...

Spark缓存--cache方法

在Spark 中&#xff0c;cache() 是用于优化计算性能的核心方法之一&#xff0c;但它有许多细节需要深入理解。以下是关于 cache() 的详细技术解析&#xff1a; 1. cache() 的本质 简化的 persist()&#xff1a;cache() 是 persist(StorageLevel.MEMORY_ONLY) 的快捷方式&#x…...

kafka logs storage

Kafka 会将日志文件按段&#xff08;Segment&#xff09;存储。 Segment是Kafka的最小存储单元&#xff0c;它是一个可追加的文件&#xff0c;用于存储Kafka分区中的一部分消息。 在文件系统中&#xff0c;Partition 是目录名&#xff0c;而Segment 是文件名。 Segment可以通过…...

数据分析平台选型与最佳实践:如何打造高效、灵活的数据生态?

数据分析平台选型与最佳实践:如何打造高效、灵活的数据生态? 在大数据时代,数据分析平台已经成为企业决策的核心支撑。从传统 BI(商业智能)到现代 AI 驱动的数据分析,选择合适的平台不仅影响数据处理效率,也决定了企业的数字化竞争力。面对市场上的众多解决方案(如 Ap…...

MYSQL之索引结构,为何要用B+树

索引的目的就是为了提高查询效率 索引的结构是B树&#xff0c;那么说到B树&#xff0c;必须提一下其他三种结构&#xff0c;分别是&#xff1a;二叉查找树、平衡二叉树、B树 我们来看看各自的结构特征 二叉查找树 特点:任何节点的左子节点的值都小于当前节点的值&#xff0c;右…...

OpenCV 中用于背景分割的一个类cv::bgsegm::BackgroundSubtractorLSBP

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::bgsegm::BackgroundSubtractorLSBP 是 OpenCV 中用于背景分割的一个类&#xff0c;它基于局部样本二进制模式&#xff08;Local Sample Bina…...

【PmHub后端篇】PmHub Gateway全局过滤器:接口调用耗时统计及黑白名单配置技术深度解析

在微服务架构日益成为现代应用开发主流模式的背景下&#xff0c;网关作为微服务架构前端的关键组件&#xff0c;肩负着路由请求、负载均衡、安全认证、流量控制、监控和日志记录等多项重要任务。本文将围绕PmHub项目中Gateway全局过滤器实现接口调用耗时统计的相关技术进行深入…...

国产激光二极管厂家

中国在激光二极管&#xff08;Laser Diode&#xff09;领域已有多家厂商布局&#xff0c;涵盖从低功率到高功率、不同波长的产品&#xff0c;应用于工业、医疗、通信、消费电子等领域。以下是部分国产激光二极管厂家及相关信息&#xff0c;供参考&#xff1a; 1. 武汉锐科光纤…...

安卓基础(XML)

123 属性​​​​行为​​​​适用场景​​​​注意事项​​match_parent填满父容器可用空间全屏视图、占满剩余空间父容器需有固定尺寸wrap_content根据内容自适应尺寸动态文本、图标、浮动按钮内容过长时可能超出父容器需处理 123 ​​属性​​​​作用​​​​常用值​​…...

uniapp|获取当前用户定位、与系统设定位置计算相隔米数、实现打卡签到(可自定义设定位置、位置有效范围米数)

基于UniApp阐述移动应用开发中定位功能的实现全流程,涵盖实时定位获取、动态距离计算与自定义位置、有效范围设定等功能。文章提供完整的代码示例与适配方案,适用于社交签到、课堂教室打卡等场景。 目录 引言定位功能在移动应用中的价值(社交、导航、O2O等场景)UniApp跨平台…...