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

Muduo网络库剖析 --- 架构设计

文章目录

  • 前言
  • 概述篇
    • 一、Muduo网络库简介
      • Reactor事件处理模式
    • 二、基于muduo实现简易聊天服务器
      • 实现
      • 测试运行
    • 三、muduo的架构设计
      • Reacor模式
      • muduo框架架构解析
      • 主从Reactor工作流程
        • 主线程(main Reactor)
        • 工作线程(sub Reactor)
      • 线程分配与负载均衡
    • 四、总结
      • 线程分配与负载均衡
    • 四、总结

前言

muduo库是陈硕个人开发基于reactor模式的tcp网络编程库。本人之前有学习过boost.asio网络库,故学习一下Muduo网络库,并分析它们之间的优缺点。

本系列将重点放在以下几件事情:

  1. 梳理Muduo的核心架构设计以及各个模块的职责
  2. 理解Muduo的事件驱动机制
  3. 理解Muduo的多线程模型
  4. 剖析作者精妙的代码设计思路并且重写其核心代码,将原来依赖boost库的地方都替换成C++11语法

下面列出主要讲解的模块

  1. 网络相关模块
    • Socket
    • InetAddress
    • TcpConnection
    • Acceptor
    • TcpServer
  2. 事件循环相关模块
    • EventLoop
    • Channel
    • Poller
    • EpollPoller
  3. 线程相关模块
    • Thread
    • EventLoopThread
    • EventLoopThreadPool
  4. 基础模块
    • Buffer
    • Timestamp
    • Logger

概述篇

一、Muduo网络库简介

Muduo网络库是一个基于非阻塞IO和事件驱动的C++高并发TCP网络库。它基于Reactor的事件处理模式,并且采用了one loop per thread的线程模型,即每个线程只运行了一个事件循环。这种模型使得Muduo能够充分利用多核CPU的性能,实现高效的网路通信。

Reactor事件处理模式

Reactor是这样的一种模式,它要求主线程只负责监听文件描述符上是否有事件发生,如果有的话立即通知工作线程。除此之外,主线程不做任何其他实质性工作。读写数据,接受新的连接,以及处理客户请求均在工作线程中完成。

二、基于muduo实现简易聊天服务器

实现

在使用muduo网络库的一个巨大优势在于:

业务逻辑与网络层的解耦。muduo是一个网络层框架,已经把网络层面的接受新的连接、收发数据等操作都封装好了,开发者可以只去关注业务逻辑而不必花费大量时间在底层网络通信的细节上。

这里介绍下面的代码会用到的两个模块:

  • 接受新连接:Muduo 的 TcpServer 模块自动处理新客户端的连接请求。
  • 连接的生命周期管理:通过 TcpConnection 管理每个连接的状态(建立、关闭)。

聊天服务器功能:

  1. 支持多个客户端同时连接。
  2. 广播消息:当某个客户端发送消息时,服务器将消息广播给所有其他客户端
  3. 管理客户端连接,支持连接建立和断开通知

ChatServer用来抽象这一过程,下面是ChatServer的声明

#include <muduo/net/TcpServer.h>
#include <muduo/net/EventLoop.h>
#include <muduo/base/Logging.h>
#include <set>
#include <string>class ChatServer {
public:// ChatServer的构造函数ChatServer(muduo::net::EventLoop* loop,const muduo::net::InetAddress& listenAddr);void start();private:// 连接新的客户端的回调函数void onConnection(const muduo::net::TcpConnectionPtr& conn);// 接受消息的回调函数void onMessage(const muduo::net::TcpConnectionPtr& conn,muduo::net::Buffer* buf,muduo::Timestamp time);// 管理Server的组件muduo::net::TcpServer server_;// // 保存连接的客户端 std::set<muduo::net::TcpConnectionPtr> connections_; // 保存连接的客户端
};

下面是ChatServer的定义

#include "ChatServer.h"using namespace muduo;
using namespace muduo::net;ChatServer::ChatServer(EventLoop* loop, const InetAddress& listenAddr): server_(loop, listenAddr, "ChatServer") {server_.setConnectionCallback(std::bind(&ChatServer::onConnection, this, std::placeholders::_1));server_.setMessageCallback(std::bind(&ChatServer::onMessage, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
}void ChatServer::start() {server_.start();
}void ChatServer::onConnection(const TcpConnectionPtr& conn) {if (conn->connected()) {LOG_INFO << "New connection from " << conn->peerAddress().toIpPort();connections_.insert(conn);} else {LOG_INFO << "Connection from " << conn->peerAddress().toIpPort() << " closed";connections_.erase(conn);}
}void ChatServer::onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time) {std::string msg = buf->retrieveAllAsString();LOG_INFO << "Received message: " << msg;// 将消息广播给所有连接的客户端for (const auto& client : connections_) {client->send(msg);}
}

由上述代码可知,程序员只需要定义好接受新的连接,接受客户端发来的消息的回调函数就可以实现简易的聊天服务器。做到业务逻辑 与 网络层面 的 解耦。

接下来实现main函数

#include <iostream>
#include "ChatServer.h"int main()
{int port = 10086;muduo::net::InetAddress listenAddr(port);	// 监听Addrmuduo::net::EventLoop loop;ChatServer server(&loop, listenAddr);server.start();loop.loop();return 0;
}
cmake_minimum_required(VERSION 3.5.0)
project(QTalk VERSION 0.1.0 LANGUAGES C CXX)add_executable(QTalk 
main.cpp
ChatServer.cpp)set(EXECUTABLE_OUTPUT_PATH ../)target_link_libraries(QTalkmuduo_netmuduo_basepthread
)

测试运行

之后将程序运行起来后,利用Linux命令可以快速地进行TCP连接与收发数据:nc localhost 10086

Server会输出两条消息:

image-20241204190831951

第一条消息是muduo库输出的信息,第二条是在ChatServer::onConnection即接受新的连接后的回调函数输出的消息。

发送一条消息后,客户端会接收到同样的消息,在服务端这里:

image-20241204191031291

同理,第一条消息是muduo库输出的消息,第二条是ChatServer::onMessage即收到新的消息的回调函数输出的消息。

三、muduo的架构设计

muduo网络库是基于reactor事件处理模式的TCP网络库。

Reacor模式

Reactor模式的核心为:Event事件Reactor反应堆、Demultiplex事件分发器、EventHandler事件处理器

image-20241204195612430

Reactor 模式通过以上组件协作完成事件的处理,以下是其具体流程:

  1. 事件注册:
    • 应用程序将需要监听的事件及对应的事件处理器(EventHandler)注册到Reactor
  2. 事件循环:
    • Reactor启动循环,调用Demuliplex等待事件发生
  3. 事件检测:
    • 当事件就绪时,Demultiplex将事件返回给Reactor
  4. 事件分发:
    • Reactor根据事件类型找到对应的EventHandler,并触发处理
  5. 事件处理:
    • EventHandler执行具体的业务逻辑,如读取数据、处理消息等。

muduo框架架构解析

Muduo的架构以one loop per thread即每个线程都有一个事件循环设计,每个线程都有它自己的Reactor,负责该线程的所有事件。主线程(main reactor)负责监听新的连接,并把accept后的socket封装起来交付给其他线程的 sub reactor处理,之后各个sub reactor负责与该连接的所有读写事件。

image-20241204200817017

主从Reactor工作流程

主线程(main Reactor)
  • 职责:
    • 负责监听客户端的连接
    • 处理accept操作,接受新的客户端连接
    • 将接收到的客户端连接进行封装,通过负载均衡算法分配给线程池的sub Reactor
  • 工作流程:
    1. 主线程监听套接字的可读事件(即有新连接到来)
    2. 调用 accept 接受新连接
    3. 将新连接的 socket 封装为 TcpConnection 对象
    4. 将新连接分配给某个工作线程的 EventLoop
工作线程(sub Reactor)
  • 职责:
    • 独立运行EventLoop,负责管理其分配的客户端连接
    • 处理连接的读写以及超时等操作
  • 工作流程
    1. 主线程将新连接分配给工作线程后,工作线程接管该连接
    2. 工作线程的 EventLoop 注册该连接的事件(如可读、可写)
    3. 当连接上的事件触发时,调用对应的回调函数处理
    4. 处理完成后,根据需要更新事件监听状态

线程分配与负载均衡

Muduo使用线程池ThreadPool来管理多个工作线程,每个工作线程运行一个EventLoop。新连接分配策略采用简单的轮询算法(Round-Robin):

  1. 主线程维护一个线程池,每个线程绑定一个EventLoop
  2. 每次接收到新连接后,按照轮询算法选择一个线程,将连接分配到该线程对应的EventLoop
  3. 开发人员调用TcpServer::setThreadNum来设置工作线程的数量

四、总结

线程分配与负载均衡

Muduo使用线程池ThreadPool来管理多个工作线程,每个工作线程运行一个EventLoop。新连接分配策略采用简单的轮询算法(Round-Robin):

  1. 主线程维护一个线程池,每个线程绑定一个EventLoop
  2. 每次接收到新连接后,按照轮询算法选择一个线程,将连接分配到该线程对应的EventLoop
  3. 开发人员调用TcpServer::setThreadNum来设置工作线程的数量

四、总结

muduoOne Loop Per Thread模型通过主从Reactor的组合,合理分配了主线程和工作线程的职责,兼顾了性能与易用性。这种设计能够充分利用多核资源,同时屏蔽了复杂的底层网络细节,为开发者提供了一种简单、高效的开发体验。

相关文章:

Muduo网络库剖析 --- 架构设计

文章目录 前言概述篇一、Muduo网络库简介Reactor事件处理模式 二、基于muduo实现简易聊天服务器实现测试运行 三、muduo的架构设计Reacor模式muduo框架架构解析主从Reactor工作流程主线程(main Reactor)工作线程(sub Reactor) 线程分配与负载均衡 四、总结线程分配与负载均衡 四…...

lwip raw、netcoon、socket三种接口编程的区别

目录 一、前言 二、LWIP 简介 三、LWIP RAW 编程 1.概念与原理 2.编程模型与流程 3.示例代码 4.优点与缺点 四、LWIP NETCONN 编程 1.概念与原理 2.编程模型与流程 3.示例代码 4.优点与缺点 五、LWIP SOCKET 编程 1.概念与原理 2.编程模型与流程 3.示例代码 …...

在办公室环境中用HMD替代传统显示器的优势

VR头戴式显示器&#xff08;HMD&#xff09;是进入虚拟现实环境的一把钥匙&#xff0c;拥有HMD的您将能够在虚拟现实世界中尽情探索未知领域&#xff0c;正如如今的互联网一样&#xff0c;虚拟现实环境能够为您提供现实中无法实现的或不可能实现的事。随着技术的不断进步&#…...

P3916 图的遍历(Tarjan缩点和反向建边)

P3916 图的遍历 - 洛谷 | 计算机科学教育新生态 写法一&#xff1a;Tarjan 思路&#xff1a;先运用Tarjan算法得到每个连通块中最大的编号&#xff0c;然后对每个连通块进行缩点重新建图&#xff0c;进行dfs&#xff0c;得到缩点后的连通块能够达到的最大编号。 Code: conste…...

Element UI 的 el-tree 组件e中默认展开前两层,设置 default-expanded-keys 属性来实现

在使用 Element UI 的 el-tree 组件时&#xff0c;如果你希望默认展开树的前两层节点&#xff0c;可以通过设置 default-expanded-keys 属性来实现。这个属性接受一个数组&#xff0c;数组中的值是需要默认展开的节点的 key。 首先&#xff0c;你需要确保你的每个树节点都有唯…...

Vue 项目中未登录状态如何统一处理

在 Vue 项目中&#xff0c;处理未登录状态&#xff08;比如用户访问需要登录的页面时&#xff09;是一项常见的需求。为了实现这一需求&#xff0c;我们通常使用 Vue Router 配合 Vuex 或者 Vue 的全局状态管理来统一处理未登录的状态&#xff0c;确保用户只能访问允许的页面。…...

Java 集合:强大的数据管理工具

在 Java 编程中&#xff0c;集合是一种非常重要的工具&#xff0c;它提供了一种方便的方式来存储和操作一组对象。本文将深入探讨 Java 集合框架&#xff0c;包括其主要类型、特点、用法以及一些最佳实践。 一、引言 在软件开发过程中&#xff0c;我们经常需要处理一组数据。…...

Creating Server TCP listening socket *:6379: bind: No error

启动redis报错&#xff1a;Creating Server TCP listening socket *:6379: bind: No error 解决方案&#xff1a; 1、直接在命令行中输入 redis-cli.exe 2、输入shutdown&#xff0c;关闭 3、输exit&#xff0c;退出 4、重新输入 redis-server.exe redis.windows.conf&…...

iOS免费共享企业证书、苹果最新企业证书免费获取

前言 大家可能都注意到了&#xff0c;苹果手机和安卓手机在安装软件上有点不一样。如果你在苹果手机上想装那些没在官方商店&#xff08;App Store&#xff09;里的软件&#xff0c;那就得给它们“签个名”&#xff0c;就像是给它们盖个章&#xff0c;这样手机才能认识它们&am…...

如果用Python写爬虫,具体怎么实现随机请求间隔呢?

在Python中实现随机请求间隔&#xff0c;通常使用time.sleep()函数结合random模块来生成随机的等待时间。以下是一个具体的实现方法&#xff1a; 导入必要的模块 首先&#xff0c;你需要导入time和random模块&#xff1a; import time import random 设置随机间隔 然后&am…...

aws(学习笔记第十五课) 如何从灾难中恢复(recover)

aws(学习笔记第十五课) 如何从灾难中恢复 学习内容&#xff1a; 使用CloudWatch对服务器进行监视与恢复区域(region)&#xff0c;可用区(available zone)和子网(subnet)使用自动扩展(AutoScalingGroup) 1. 使用CloudWatch对服务器进行监视与恢复 整体架构 这里模拟Jenkins Se…...

nginx4层限速

Nginx的功能概述 Nginx是一个高性能的HTTP和反向代理服务器&#xff0c;也可以作为邮件代理服务器等。它主要工作在7层&#xff08;应用层&#xff09;&#xff0c;但在某些场景下也可以实现部分4层&#xff08;传输层&#xff09;的功能。 关于4层限速 Nginx自身的限制&#x…...

Spring Cloud Alibaba 之 “Feign多参数构造”

在上一篇文章整合好了Feign&#xff0c;现在来总结以下Feign调用多参数方法的使用。 GET方式&#xff1a; Spring Cloud为Feign支持了Spring Mvc注解的。如果请求的是localhost:8083/test?id1&namecoco,那么如果我们这样写&#xff08;User实体类有这二个属性&#xff09…...

C#高级教程

目录 C# 特性&#xff08;Attribute&#xff09;C# 反射&#xff08;Reflection&#xff09;C# 属性&#xff08;Property&#xff09;C# 索引器&#xff08;Indexer&#xff09;C# 委托&#xff08;Delegate&#xff09;C# 事件&#xff08;Event&#xff09;C# 集合&#xf…...

c++ 位图和布隆过滤器

位图&#xff08;bitmap&#xff09; 定义 位图是一种使用位数组存储数据的结构。每一位表示一个状态&#xff0c;通常用于快速判断某个值是否存在&#xff0c;或者用来表示布尔类型的集合。 特点 节省空间&#xff1a;一个字节可以表示8个状态。高效操作&#xff1a;位操作…...

基于Springboot开发的云野旅游平台

一、功能介绍 云野旅游平台包含管理员、用户两个角色以及前后台系统。 前台系统功能 用户登录成功后&#xff0c;可以进行查看旅游路线、最新线路、旅游资讯、个人中心、后台管理、购物车、客服等功能模块。进行相对应操作。 后台系统功能 管理员或用户登录成功后&#xf…...

微服务即时通讯系统(5)用户管理子服务,网关子服务

用户管理子服务&#xff08;user文件&#xff09; 用户管理子服务也是这个项目中的一个业务最多的子服务&#xff0c;接口多&#xff0c;但是主要涉及的数据表只有user表&#xff0c;Redis的键值对和ES的一个搜索引擎&#xff0c;主要功能是对用户的个人信息进行修改管理&#…...

docker.io连接超时的处理,用代理网站

docker pull的时候会超时&#xff1a; Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers) 这时可以找一些代理网站&#xff0c;比如…...

【测试工具JMeter篇】JMeter性能测试入门级教程(四):JMeter中BeanShell内置方法使用

一、什么是BeanShell BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法;BeanShell是一种松散类型的脚本语言(这点和JS类似);BeanShell是用Java写成的,一个小型的、免费的、可以下载的、嵌入式的Java源代码解释器,具有对象脚本语言特性,非常精简…...

JavaScript 键盘控制移动

如果你想通过 JavaScript 实现键盘控制对象&#xff08;比如一个方块&#xff09;的移动&#xff0c;下面是一个简单的示例&#xff0c;展示如何监听键盘事件并根据按下的键来移动一个元素。 HTML 和 CSS&#xff1a; <!DOCTYPE html> <html lang"en">…...

如何预防服务器后台爆破攻击

服务器后台爆破&#xff08;Brute Force Attack&#xff09;是一种通过反复尝试用户名和密码组合&#xff0c;以非法获取系统访问权限的攻击方式。这种攻击不仅会消耗服务器资源&#xff0c;还可能导致合法用户被锁定或敏感数据泄露。为了有效预防服务器后台爆破攻击&#xff0…...

AI 写作(一):开启创作新纪元(1/10)

一、AI 写作&#xff1a;重塑创作格局 在当今数字化高速发展的时代&#xff0c;AI 写作正以惊人的速度重塑着创作格局。AI 写作在现代社会中占据着举足轻重的地位&#xff0c;发挥着不可替代的作用。 随着信息的爆炸式增长&#xff0c;人们对于内容的需求日益旺盛。AI 写作能够…...

【HarmonyOS】鸿蒙应用使用lottie动画

【HarmonyOS】鸿蒙应用使用lottie动画 一、lottie动画是什么&#xff1f; https://airbnb.design/lottie Lottie是由Airbnb团队开发的一个适用于iOS、Android、React Native、Web和Windows的开源动画库&#xff0c;用于解析使用Bodymovin导出为JSON的Adobe After Effects动…...

SQL面试题——腾讯SQL面试题 合并连续支付订单

合并连续支付订单 现有一张用户支付表:user_pay包含字段订单ID,用户ID,商户ID,支付时间,支付金额。如果同一用户在同一商户存在多笔订单,且中间该用户没有其他商户的支付记录,则认为是连续订单,请把连续订单进行合并,时间取最早支付时间,金额求和。 +----------+------…...

【docker】10. 容器操作案例

容器操作案例 容器基本操作 • 通过 nginx 镜像文件创建容器 • 容器的列举(包含正在运行的容器) # 发现此时 e7c33d9f5c61 这个容器运行的状态为 Up,即运行状态 rootLAPTOP-H2EI4I6A:~# docker container ls CONTAINER ID IMAGE COMMAND CREATED …...

postman测试

当然&#xff0c;以下是针对你提供的API层和Service层代码中涉及到的各个接口&#xff0c;如何使用 Postman 进行详细测试的指南。这个指南将帮助你理解如何配置 Postman 来测试这些接口&#xff0c;包括请求的构造、认证的处理、以及如何解读响应。 目录 准备工作接口测试指…...

【攻防实验】溯源与取证分析实验

溯源与取证分析实验 溯源取证分析作为网络攻防过程中重要环节&#xff0c;准确找到攻击者的入侵线索(尤其是攻击突破口、攻击IP地址、域名、工具等信息)&#xff0c;对于企业或者团队安全运营团队来说都是必备技能。常规攻击取证过程中往往会结合流量、Web访问日志、终端系统或…...

【测试工具JMeter篇】JMeter性能测试入门级教程(七):JMeter断言

一、前言 在 JMeter 中&#xff0c;断言元件&#xff08;Assertion&#xff09;用于验证测试结果是否符合预期。断言元件可以检查服务器的响应数据&#xff0c;以确保它们符合期望的模式或值&#xff0c;从而验证性能测试脚本的正确性。断言元件通常在每个请求的响应中添加&am…...

Linux 常用命令

目录 一、ls 指令 二、pwd命令 三、cd 指令 1、cd 目录名 2、cd .. 返回上级目录 3、cd ~ 进入用户家目 4、cd - 返回最近访问目录 5、cd相对路径&&cd绝对路径 四、touch指令 五、mkdir指令 1、mkdir 目录名 创建一个目录 2、mkdir -p 递归创建多…...

汽车IVI中控OS Linux driver开发实操(二十八):回声消除echo cancellation和噪声消除Noise reduction

概述: 在当今高度互联的世界中,清晰的实时通信比以往任何时候都更重要。在远程团队会议期间,没有什么能像回声一样打断对话。当说话者听到他们的声音回响时,可能会分散注意力,甚至无法理解对话。即使是很小的回声也会产生很大的影响,仅仅25毫秒的振幅就足以造成声音干扰…...

003-SpringBoot整合Pagehelper

SpringBoot整合Pagehelper 一、引入依赖二、配置 application.yml三、配置 MybatisPlusConfig四、Controller五、ServiceImpl 一、引入依赖 <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</ar…...

零基础学安全--shell练习

目录 用shell写一个计算器 测试​ 一些小问题 n阶乘数 测试 拓展 写⼀个Shell脚本去筛选出eth0⽹卡的ipv4地址&#xff0c;并赋值⼀个变量输出 测试 无限重启 用shell写一个计算器 read -p "请输入数字a: " number1 read -p "请输入操作符&#xf…...

【专题】计算机网络之运输层(传输层)

1. 运输层协议概述 1.1 进程之间的通信 (1) 运输层的作用 运输层提供进程间的逻辑通信。 运输层的屏蔽作用&#xff1a; 运输层向高层用户屏蔽了下面网络核心的细节&#xff08;如网络拓扑、所采用的路由选择协议等&#xff09;&#xff0c;使应用进程看见的就是好像在两个运…...

【leetcode100】旋转图像

1、题目描述 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],…...

软件工程——期末复习(1)

名词解释&#xff1a; 名词解释--人月 答案&#xff1a;人月是软件开发工作量的单位&#xff0c;1人月表示1个程序员1个月的工作时间所开发的代码量。 请解释软件缺陷、错误和失败&#xff0c;并简单举例说明。 答案&#xff1a;缺陷&#xff08;defect&#xff09;指系统代…...

HTML5系列(3)--多媒体标签详解

前端技术探索系列&#xff1a;HTML5 多媒体标签详解 &#x1f3a5; 开篇寄语 &#x1f44b; 前端开发者们&#xff0c; 在前三篇文章中&#xff0c;我们探讨了 HTML5 的语义化和表单特性。今天&#xff0c;让我们深入了解 HTML5 的多媒体能力&#xff0c;看看如何构建强大的…...

Spring Boot 3.4.0 发布:功能概览与示例

Spring Boot 3.4.0 带来了许多增强功能&#xff0c;使现代应用开发更加高效、便捷和强大。以下是最新功能的完整概述&#xff0c;以及一些帮助您快速入门的代码示例。 1. 应用程序版本管理 Spring Boot 引入了 spring.application.version 属性&#xff0c;方便开发者设置和访…...

【Vue3】【Naive UI】<n-upload>标签

【Vue3】【Naive UI】标签 基本设置 【VUE3】【Naive UI】&#xff1c;NCard&#xff1e; 标签 【VUE3】【Naive UI】&#xff1c;n-button&#xff1e; 标签 【VUE3】【Naive UI】&#xff1c;a&#xff1e; 标签 【VUE3】【Naive UI】&#xff1c;NDropdown&#xff1e; 标签…...

7.代理模式(Proxy Pattern)

古朗月行 代理模式JDK动态代理代码示例原码分析 cglib动态代理代码示例源码分析 JDK cglib动态代理对比ClassLoader类的生命周期&#xff1a; 参考资料 唐 李白 小时不识月&#xff0c;呼作白玉盘。 又疑瑶台镜&#xff0c;飞在青云端。 仙人垂两足&#xff0c;桂树何团团。…...

【效果】回到顶部功能实现

实现效果&#xff1a; 相关代码&#xff1a; <template><div class"cats" :style"{ top: catsTop }" ref"cats" click"catTop"></div> </template> 样式&#xff1a; /* 回到顶部 - 小猫咪 */ .cats {posi…...

项目搭建+修改

一 : 在列表成功回调函数,追加数据中,添加修改的按钮 for (let x of res) {//追加数据$("#table").append(<tr><td><input type"checkbox" class"ck" value"\${x.uid}"></td><td>\${x.uid}</td>…...

GD库如何根据颜色生成纯色背景图

GD库是一个用于图像处理的PHP扩展模块&#xff0c;它提供了一系列函数来创建、编辑和操作图像。要使用GD库根据颜色生成纯色背景图&#xff0c;可以按照以下步骤进行&#xff1a; 一、检查并安装GD库 检查GD库是否已安装&#xff1a; 可以通过运行phpinfo();或在命令行中使用p…...

Python 网络爬虫入门全知道

一、引言 在当今数字化时代&#xff0c;网络上的数据量呈爆炸式增长。无论是进行数据分析、市场调研&#xff0c;还是开发智能应用&#xff0c;获取网络数据都变得极为重要。而 Python 网络爬虫就是一把打开网络数据宝库的利器。它能够自动地从网页中抓取我们需要的信息&#…...

MATLAB期末复习笔记(下)

目录 五、数据和函数的可视化 1.MATLAB的可视化对象 2.二维图形的绘制 3.图形标识 4.多子图绘图 5.直方图的绘制 &#xff08;1&#xff09;分类 &#xff08;2&#xff09;垂直累计式 &#xff08;3&#xff09;垂直分组式 &#xff08;4&#xff09;水平分组式 &…...

基于大数据爬虫数据挖掘技术+Python的网络用户购物行为分析与可视化平台(源码+论文+PPT+部署文档教程等)

#1024程序员节&#xff5c;征文# 博主介绍&#xff1a;CSDN毕设辅导第一人、全网粉丝50W,csdn特邀作者、博客专家、腾讯云社区合作讲师、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老…...

【go】只读通道和只写通道

文章目录 概述1. 通道的方向2. 为什么会有只读通道和只写通道&#xff1f;3. 总结 概述 在 Go 中&#xff0c;只读通道和只写通道的概念通过通道的方向来实现。Go 语言允许你在函数参数中指定通道的方向&#xff0c;从而限制通道的使用方式&#xff0c;这样可以确保代码的清晰…...

带Burst AOT Settings移植问题

报错 burst问题 Burst AOT Settings 是 Unity 的 Burst Compiler 的一部分&#xff0c;用于预编译程序集&#xff08;AOT&#xff0c;Ahead-Of-Time Compilation&#xff09;&#xff0c;以便在不支持 JIT&#xff08;即时编译&#xff09;的平台上运行&#xff0c;例如 iOS 和…...

Debezium日常分享系列之:Debezium Engine

Debezium日常分享系列之&#xff1a;Debezium Engine 依赖打包项目在代码中输出消息格式消息转换消息转换谓词高级记录使用引擎属性异步引擎属性数据库模式历史属性处理故障 Debezium连接器通常通过部署到Kafka Connect服务来运行&#xff0c;并配置一个或多个连接器来监视上游…...

运行 GreatSQL 时为什么要求关闭透明大页

在大部分运维规范中&#xff0c;一般都会要求在运行 GreatSQL/MySQL 的环境中要关闭透明大页&#xff0c;那么到底什么是透明大页&#xff0c;为什么要关闭&#xff0c;打开有什么风险吗&#xff1f; 在此之前&#xff0c;我也是有点懵的&#xff0c;本文试着回答这个疑问&…...

【Rive】Rive在Android上的简单应用

1 前言 Rive 是一款强大的矢量图编辑器&#xff0c;可以设计图形、也可以制作动画。Rive 提供了矩形、圆形、三角形、多边形、星形、钢笔、文字等工具来绘制各式各样的矢量图形&#xff1b;提供了平移、旋转、缩放等工具对矢量图形进行各种变换&#xff1b;提供了骨骼、约束、时…...