施磊老师rpc(一)
文章目录
- mprpc项目
- **项目概述**:
- 深入学习到什么
- **前置学习建议**:
- 核心内容
- 其他技术与工具
- **项目特点与要求**:
- **环境准备**:
- 技术栈
- 集群和分布式理论
- 单机聊天服务器案例分析
- 集群聊天服务器分析
- 分布式系统介绍
- 多个模块的局限
- 引入分布式 RPC 通信框架的意义
- 三大形态对比--**重点**
- RPC 通信原理讲解整理
- 为什么要使用 RPC?
- RPC 通信的完整过程(调用链)
- 关键模块说明(图中重要角色)
- 返回结果的组成与处理
- 框架的作用与实现目标
- 举例巩固(Login 方法调用)
- protobuf优点
- 总结
- 环境配置
- 类似于集群项目
- protobuf
- protobuf使用(一)
- 安装vscode插件
- 简单使用
- 代码
- protoc编译
- 序列化和反序列化使用
- 编译注意
- protobuf使用(二)
- string和**bytes**
- `bytes` 类型的作用:
- 与 `string` 的区别:
- 注意事项
- protobuf的枚举
- repeated(重复)
- repeated常用方法(C++)
- message嵌套message
- mutable_字段--**重点**
- add_成员和()
- main使用
- 重要的是-学会看**.h**里面的函数
mprpc项目
分布式 网络通信 框架
基于muduo+protobuf
业界优秀的RPC框架:baidu的brpc,google的grpc
项目概述:
本课程将使用 C/C++ 编写分布式网络通信框架项目,重点讲解从单机服务器到集群服务器,再到项目模块化分解与分布式部署的过程。
深入学习到什么
希望 可以 对 单机----集群-----分布式 有更好的理解
前置学习建议:
学习本项目前,建议先完成 C/C++ 项目集群的网络聊天通信项目,以便更好地理解服务器集群概念及其优势,为学习分布式知识打下基础。
技术选型
- 网络库:采用 muduo 高性能网络库(底层基于 I/O 线程池模型) 。
- 序列化 / 反序列化:使用 protobuf 处理数据序列化和反序列化,以及远程调用方法的识别、参数处理。
- 命名:基于 muduo 库和 protobuf 首字母,将项目命名为 mprpc。
核心内容
- 讲解集群与分布式的概念及原理。
- 剖析 rpc 远程过程调用的原理与实现。
- 阐述服务注册中心(如 ZooKeeper)在分布式环境中的作用。
其他技术与工具
- 涉及 C++11 和 C++14 的新语法(如线程级别的本地变量、绑定器与函数对象等)。
- 使用 VS Code 进行跨平台开发,在 Linux 环境下远程开发项目。
- 介绍 muduo 库网络编程、conf 配置文件读取、cmake 构建集成编译环境及 GitHub 项目托管。
项目特点与要求:
项目代码量虽比集群聊天项目少,但对技术栈的理解深度和广度要求更高,更注重对集群和分布式的理解 。
环境准备:
开发前需掌握 Linux 环境下 muduo 网络库(依赖 boost 库)的安装,相关安装步骤可参考博主博客,且 muduo 库网络编程示例、cmake 构建编译环境在集群聊天服务器项目中已详细讲解。
技术栈
- 集群和分布式概念以及原理
- RPC远程过程调用原理以及实现
- Protobuf数据序列化和反序列化协议
- ZooKeeper分布式一致性协调服务应用以及编程
- muduo网络库编程
- conf配置文件读取
- 异步日志
- CMake构建项目集成编译环境
- github管理项目
代码没有集群多, 但是 知识更深入
集群和分布式理论
单机聊天服务器案例分析
服务器模块与业务:以单机聊天服务器为例,其包含用户管理、好友管理、群组管理、消息管理和后台管理五个模块。每个模块对应多项特定业务,如用户管理包括登录、注册、注销;好友管理涉及添加、删除好友等,这些业务由一个或多个相关函数实现。
性能与设计瓶颈:
- 硬件资源限制:单机服务器受硬件资源制约,例如 32 位 Linux 系统的聊天服务器,进程资源耗尽时,最多仅能支持约两万用户同时在线,难以承载更多客户端连接与服务。
- 运维与代码编译成本高:由于模块都在同一项目运行单元,任意模块的修改(哪怕只是一行代码),都需重新编译整个项目代码(耗时约 2 小时),并重新部署(耗时约 3 小时),成本巨大。
- 硬件资源分配不合理:不同模块对硬件资源需求不同,存在 CPU 密集型和 IO 密集型模块。但单机服务器只能采用平衡方案部署,无法针对各模块需求进行硬件资源的精准匹配。
集群聊天服务器分析
性能提升:通过水平扩展硬件资源,增加服务器数量(如三台或更多),每台独立运行聊天服务器程序,解决了单机服务器受硬件资源限制导致的用户并发量低的问题。
存在问题:
- 编译成本高:各服务器上的模块仍在同一项目中部署,运行于一个服务进程,因此任意模块修改仍需整体重新编译代码,且需多次部署到不同服务器,运维成本更高。
- 硬件资源分配不合理:集群只是简单扩展机器,无法针对不同模块(CPU 密集型或 IO 密集型)的硬件资源需求进行精准部署,存在资源浪费。例如后台管理模块并发需求低,却随整体系统在多台服务器部署 。
其他特点应用:集群部署方式简单,在高并发突发场景(如双 11)能快速通过增加服务器和负载均衡器提升服务能力 。
在集群中机器数量与性能并非成正比,原因如下:
- 通信成本:机器增多使节点间通信开销增大,占用带宽与处理时间,易引发网络拥塞。
- 分配难题:数据和任务难以在更多机器上均匀分配,易造成资源浪费。
- 复杂故障:系统复杂度随机器数上升,故障和配置问题更易影响性能。
- 并行局限:部分任务不适合大规模并行或并行度有限,加机器也无法提升性能。
以下任务不适合大规模集群并行处理:
- 顺序依赖型:步骤间严格先后关联,无法拆分并行,如按序的数据清洗与分析。
- 高通信成本型:执行中需频繁大量数据交互,易受网络带宽制约,如高频金融交易数据处理。
- 任务粒度过小:任务简单微小,集群调度、协调开销超执行时间,如大量小文件简单格式转换。
分布式系统介绍
定义与特点:将一个工程拆分为多个模块,每个模块独立部署为可运行的服务进程,多台服务器(分布式节点)协同工作构成完整系统。与集群区别在于,集群中每台服务器运行完整系统,而分布式是多台服务器共同组成一个系统 。
解决的问题
- 并发与资源优化:可根据分布式节点的并发需求灵活扩容,如对用户管理模块所在节点增加服务器以支持更高并发,同时合理利用其他节点空闲资源,提升资源利用率。
- 编译与部署优化:模块独立部署,单个模块修改仅需重新编译和更新该模块,无需影响其他模块,大大降低编译和部署成本。
- 硬件匹配优化:模块拆分后,可依据各模块特性(CPU 密集型或 IO 密集型)精准匹配硬件资源,实现资源的合理配置。
潜在问题与应对:分布式系统中部分节点故障可能影响整体服务,但实际生产中可通过配置主备服务器等容灾方案保障高可用性 。
多个模块的局限
模块划分困难
- 模块之间的边界不清晰,容易出现功能重叠或代码重复。
- 模块耦合度高,修改难、维护难。
- 若划分不当,容易造成大量重复代码、逻辑冗余、维护成本高。
模块之间的通信复杂–重点
- 分布式部署后,模块间通信需跨进程、跨机器。
- 函数调用从本地调用变为远程调用,需涉及:
- 函数名、参数传输
- 网络通信、序列化/反序列化
- 异常处理、响应返回等机制
引入分布式 RPC 通信框架的意义
核心作用
让“跨主机远程调用函数”像“调用本地函数”一样简单透明
解决的核心问题
- 统一通信流程,屏蔽底层复杂性
- 请求封装 + 网络传输 + 响应处理全部自动完成。
- 提高模块间调用效率与开发体验
- 用户感知不到远程调用的差异,只需像本地函数一样使用接口。
- 支持参数序列化与传输
- 使用 Protobuf 进行高效的数据结构序列化。
- 自动服务发现与定位
- 通过 ZooKeeper 注册中心查找服务位置,实现动态服务绑定。
三大形态对比–重点
系统形态 | 特点 | 优势 | 局限性 |
---|---|---|---|
单机服务器 | 所有模块在一个进程 | 开发简单 | 扩展性差、耦合高 |
集群服务器 | 多台相同服务器 | 水平扩展、简单粗暴 | 不是线性扩展、资源浪费 |
分布式模块化系统 | 各模块独立部署 | 高可维护性、易扩展、低耦合 | 设计复杂、通信困难(需RPC) |
RPC 通信原理讲解整理
为什么要使用 RPC?
- 为了解耦与扩展:
- 大型系统按需模块化(不同模块对硬件/并发等要求不同),分布式部署成为必然。
- 模块分布在不同进程、甚至不同机器上,相互之间仍需调用方法 —— 就必须跨进程/跨机器通信。
- 屏蔽底层通信细节:
- 本质是“远程函数调用”,但不同于本地函数调用的直接跳转和传参。
- 不希望每个开发者都去手动处理 socket、序列化、反序列化、错误码等细节。
- 引入“框架”来自动完成这些通信细节,开发者只专注于业务逻辑即可。
RPC 通信的完整过程(调用链)
举例:用户模块调用好友模块的 getUserFriendList(userId)
方法(模块部署在不同服务器)
Caller(调用方) → Stub(客户端代理) → 网络层↓ ↓ ↓发起调用(方法名+参数) → 序列化(打包) → 网络发送↑ ↑ ↑接收返回(结果/错误) ← 反序列化(解包) ← 网络接收
步骤 | 说明 |
---|---|
1. 调用方发起函数调用 | 比如:getUserFriendList(userId) ,但这个方法实际存在于另一台机器。 |
2. Stub 代理类拦截调用 | 替你处理所有 RPC 通信细节。 |
3. 参数序列化(打包) | 方法名、参数 → 序列化成字节流(如 JSON、Protobuf) |
4. 网络传输 | 使用网络库(如 muduo)将字节流发送到目标服务器 |
5. 服务端接收 | 网络层接收到请求后交给服务端的 Stub 处理 |
6. 参数反序列化 | 字节流 → 方法名 + 参数 |
7. 执行远程函数 | 找到目标函数(如 getUserFriendList ),执行逻辑处理 |
8. 返回结果处理 | 执行结果、错误码、错误信息 → 序列化返回 |
9. 调用方接收响应 | 解包结果 → 返回给应用层,像本地函数一样使用返回值 |
关键模块说明(图中重要角色)
角色 | 功能简述 |
---|---|
Caller | 发起方(如用户模块),调用远端方法 |
Stub(客户端桩) | 代理模块,封装参数、处理序列化、发送请求等 |
网络层 | 通信基础设施(如 muduo 库),负责字节流的收发 |
Stub(服务端桩) | 接收数据并反序列化,请求转发到本地业务模块 |
Callee | 被调方(如好友模块),真正执行业务方法 |
结果返回路径 | 与调用路径对称,同样涉及打包、网络传输和反序列化 |
返回结果的组成与处理
- 返回值通常包括:
- 错误码(errorCode)
- 错误信息(errorMessage)
- 业务数据(result)
- 如果错误码为非零,说明远程执行出错,不应使用返回值,仅使用错误信息。
框架的作用与实现目标
- 由框架来完成:
- 参数/返回值的序列化与反序列化
- 方法名的标识与分发
- 网络通信(请求发送/接收)
- 错误处理与返回机制
- 开发者只需写业务逻辑函数,像调用本地函数一样调用远程服务
举例巩固(Login 方法调用)
- 示例函数:
login(string name, string password)
- 发起调用:
login("zhangsan", "123456")
- 步骤:
- Stub 序列化请求(函数名 + 参数)
- 网络发送请求
- 远端反序列化 + 调用 login()
- 执行返回
true/false
+ 错误码 + 信息 - 远端再次序列化发送
- 调用方反序列化,判断错误码再处理返回值
protobuf优点
高效的序列化性能
- 体积小:二进制格式,比 JSON、XML 更精简,节省网络带宽。
- 速度快:序列化和反序列化速度远快于 JSON/XML,适合高频数据传输场景。
- 示例:1000 条用户消息用 JSON 可能几百 KB,而 Protobuf 仅几十 KB。
跨语言支持
- 支持多种语言自动生成代码(C++、Java、Python、Go 等)。
- 不同平台、语言之间通信无需手写解析逻辑,提高开发效率。
- 示例:后端使用 C++,前端用 JavaScript,通过 proto 文件即可对接。
总结
- RPC 的目标:让远程调用就像本地函数调用一样简单
- 框架解决的是“通信”本质问题,而不是业务逻辑问题
- 图中的每一步都需要代码支持,RPC 框架的核心就是实现这些自动化处理
zookeeper服务配置中心(专门做服务发现)
环境配置
类似于集群项目
protobuf
github 进行下载安装 https://github.com/protocolbuffers/protobuf
一定要 下载 包里面 有 autogen.sh 的版本
没有的 就是 高版本, bazel 和 cmake 都不好用, bug特别多!!
折腾了 半天, 高版本 一个是 安装步骤变了, 一个是 bug一堆!!
不要安装 21 版本之上, 一堆bug, 就装 21版本及以下
sudo apt-get update
sudo apt-get install autoconf automake libtool curl make g++ unzip
git clone 下来
./autogen.sh
./configure
make && sudo make install
sudo ldconfig
protobuf使用(一)
内容并不多, 后续 从实践中 学习
安装vscode插件
vscode-proto3
简单使用
在 Protobuf 中,package
后面跟的就是 包名,表示该 .proto
文件中定义的所有消息、服务、枚举等都属于这个“命名空间”,称为 包名。
包名是你自己定义的一个标识符,用来给这组 protobuf 定义加上“命名空间”。
代码
test/protobuf/test.proto------proto 配置文件
syntax = "proto3"; //声明protobuf的版本package hzhpro; // 声明代码所在的包(例如c++就是namespace)// 定义登录请求消息类型 name pwd
message LoginRequest
{string name = 1;string pwd = 2;
}// 定义登录响应消息类型
message LoginResponse
{int32 errcode = 1;string errmsg = 2;bool success = 3;
}
protoc编译
–cpp_out=OUT_DIR Generate C++ header and source.
protoc test.proto --cpp_out=./
生成
test.pb.cc test.pb.h
messgae 相当于 class类, 里面的 相当于 成员变量
序列化和反序列化使用
test/protobuf/main.cc
#include "test.pb.h"
#include <iostream>
#include <string>
using namespace hzhpro; // 实际开发 要少用命名空间int main()
{// 封装了login请求对象的数据LoginRequest req;req.set_name("zhang san");req.set_pwd("123123");// 对象数据序列化=>char*std::string send_buf; if(req.SerializeToString(&send_buf)){std::cout<< send_buf.c_str()<<std::endl;}// 从send_buf反序列化LoginRequest reqB;if(reqB.ParseFromString(send_buf)){std::cout<<reqB.name()<<std::endl;std::cout<<reqB.pwd()<<std::endl;}return 0;
}
编译注意
必须加 pthread-----因为 Protobuf 内部使用了线程相关的功能(如 std::thread
, pthread_create
)
g++ main.cc test.pb.cc -lprotobuf -pthread
protobuf使用(二)
string和bytes
在 Protobuf 中,bytes
是一种字段类型,表示原始二进制数据,用途非常广泛。
bytes
类型的作用:
它可以用来存储:
- 二进制数据(图片、文件内容、压缩数据)
- 自定义序列化的结构体
- 加密密钥、哈希值
- 或者就是一个 UTF-8 编码的字符串(但不推荐当字符串来用)
与 string
的区别:
类型 | 内容编码 | 是否可包含 \0 | 推荐用途 |
---|---|---|---|
string | UTF-8 | ❌ 不可包含 | 正常文本(人读的) |
bytes | 原始数据 | ✅ 可以包含 | 任意二进制数据 |
注意事项
- 使用
bytes
时不能用set_content("str")
来设置包含\0
的数据,否则会截断。 - 应使用
set_content(const void* data, size_t size)
。
protobuf的枚举
.proto
中每个枚举成员 必须指定数值(不自动递增)。
必须用分号 ;
结束每一行,这和 C++ 是不同的。
枚举成员名建议用 全大写字母,符合 protobuf 的命名习惯。
repeated(重复)
repeated 类型 字段名 = 编号;
message FriendList {repeated string friends = 1;
}
下面这个是 基本类型
FriendList list;
list.add_friends("Tom");
list.add_friends("Jerry");for (int i = 0; i < list.friends_size(); ++i) {std::cout << list.friends(i) << std::endl;
}
repeated常用方法(C++)
add_字段()
→ 添加一个元素字段_size()
→ 获取数量字段(index)
→ 获取第 index 个元素(从 0 开始)mutable_字段()
→ 获取可修改的容器(高级操作)
message嵌套message
test/protobuf/test.proto
syntax = "proto3"; //声明protobuf的版本package hzhpro; // 声明代码所在的包(例如c++就是namespace)message ResultCode
{int32 errcode = 1;bytes errmsg = 2;
}// 定义登录请求消息类型 name pwd
message LoginRequest
{bytes name = 1;bytes pwd = 2;
}// 定义登录响应消息类型
message LoginResponse
{ResultCode result = 1;// int32 errcode = 1;// bytes errmsg = 2;bool success = 3;
}message GetFriendListsRequest
{uint32 userid = 1; // 获取谁的请求
}message User
{bytes name =1;uint32 age = 2;enum Sex // 枚举写法注意{MAN=0;WOMAN=1;}Sex sex=3;
}message GetFriendResponse
{// int32 errcode = 1; // 代码重复// bytes errmsg = 2;ResultCode result = 1;repeated User friend_list=2; // 定义了一个列表类型, 这个_list没啥特殊意义
}
重新编译, 注意 vscode 缓存, 容易没反应, 重新拉一下 头文件
mutable_字段–重点
通过查找 pb.h 的 result 函数 ===== 这个result 就是 那个ResultCode 类对象
result 返回 const 引用, 不能修改值
mutable_result 返回指针, 可以修改值
const ::hzhpro::ResultCode& result() const;
::hzhpro::ResultCode* mutable_result();
void set_allocated_result(::hzhpro::ResultCode* result);
函数名 | 返回类型 | 用途 |
---|---|---|
result() | const ResultCode& | 只读访问 |
mutable_result() | ResultCode* | 可写访问 |
set_allocated_result(ResultCode*) | void | 设置已存在对象的所有权(高级用法) |
add_成员和()
::hzhpro::User* add_friend_list();
const ::hzhpro::User& friend_list(int index) const; //查看第几个, index 根据上面
main使用
LoginResponse rsp;
ResultCode *rc = rsp.mutable_result();
rc->set_errcode(1);
rc->set_errmsg("登录处理失败");
自定义类型的 add_
int main()
{// LoginResponse rsp;// ResultCode *rc = rsp.mutable_result();// rc->set_errcode(1);// rc->set_errmsg("登录处理失败");GetFriendListsResponse rsp;ResultCode *rc = rsp.mutable_result();rc->set_errcode(0);User *user1 = rsp.add_friend_list();user1->set_name("zhang san");user1->set_age(26);user1->set_sex(User::MAN);User *user2 = rsp.add_friend_list();user2->set_name("zhang san-2");user2->set_age(26);user2->set_sex(User::MAN);User *user3 = rsp.add_friend_list();user3->set_name("zhang san-3");user3->set_age(26);user3->set_sex(User::WOMAN);std::cout<<rsp.friend_list_size()<<std::endl;User user = rsp.friend_list(2);std::string userstr;if(user.SerializeToString(&userstr)){// std::cout<<userstr.c_str()<<std::endl;// 这个有问题, 序列化后是二进制数据流, 本身是 字符串能打印出来, 要是有别的 类型, 就不好说了}User userB;if(userB.ParseFromString(userstr)){std::cout<<userB.name()<<std::endl;std::cout<<userB.age()<<std::endl;std::cout<<userB.sex()<<std::endl;}return 0;
}
3
zhang san-3
26
1
重要的是-学会看**.h**里面的函数
相关文章:
施磊老师rpc(一)
文章目录 mprpc项目**项目概述**:深入学习到什么**前置学习建议**:核心内容其他技术与工具**项目特点与要求**:**环境准备**: 技术栈集群和分布式理论单机聊天服务器案例分析集群聊天服务器分析分布式系统介绍多个模块的局限引入分…...
视觉问答大模型速递:Skywork-R1V2-38B
Skywork-R1V2-38B速读 一、模型概述 Skywork-R1V2-38B是一种最先进的开源多模态推理模型,在多项基准测试中表现卓越。它在MMMU测试中以73.6%的得分位居所有开源模型之首,在OlympiadBench测试中以62.6%的得分大幅领先于其他开源模型。此外,R…...
Spring Boot 中集成 Kafka 并实现延迟消息队列
在 Spring Boot 中集成 Kafka 并实现延迟消息队列,需要结合 Kafka 的基础功能与自定义逻辑来处理延迟投递。以下是完整的实现步骤和示例代码,涵盖配置、生产者、消费者、延迟队列设计和消息重试机制。 一、环境准备与依赖配置 添加依赖 在 pom.xml 中添加 Spring Kafka 依赖:…...
【算法学习】哈希表篇:哈希表的使用场景和使用方法
算法学习: https://blog.csdn.net/2301_80220607/category_12922080.html?spm1001.2014.3001.5482 前言: 在之前学习数据结构时我们就学习了哈希表的使用方法,这里我们主要是针对哈希表的做题方法进行讲解,都是leetcode上的经典…...
(51单片机)LCD显示红外遥控相关数据(Delay延时函数)(LCD1602教程)(Int0和Timer0外部中断教程)(IR红外遥控模块教程)
前言: 本次Timer0模块改装了一下,注意!!! 演示视频: 红外遥控 源代码: 如上图将9个文放在Keli5 中即可,然后烧录在单片机中就行了 烧录软件用的是STC-ISP,不知道怎么安…...
农产品园区展示系统——仙盟创梦IDE开发
<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>农业大数据平台</title><style>* {margi…...
Copilot:您的AI伴侣-微软50周年系列更新
回顾微软五十年来持续创新带来的深远影响,比尔盖茨当年"让每张办公桌、每个家庭都拥有电脑"的宏伟愿景至今仍激励着我们。微软AI团队正秉承同样的精神,打造属于每个人的AI伙伴——Copilot。 这意味着什么?它是什么模样?…...
【人工智能】深入探索Python中的自然语言理解:实现实体识别系统
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 自然语言理解(NLU)是人工智能(AI)领域中的重要研究方向之一,其目标是让计算机理解和处理人类语言。在NLU的众多应用中,实体识别(Nam…...
Steam安装下载及新手注册
📢博客主页:肩匣与橘 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! 📢本文由肩匣与橘编写,首发于CSDN🙉 📢生活依旧是美好而又温柔的,你也…...
Gradio全解20——Streaming:流式传输的多媒体应用(1)——流式传输音频:魔力8号球
Gradio全解20——Streaming:Streaming:流式传输的多媒体应用(1)——流式传输音频:魔力8号球 前言本篇摘要20. Streaming:流式传输的多媒体应用20.1 流式传输音频:魔力8号球20.1.1 工作原理20.1.…...
Netflix系统架构解析
Netflix系统架构解析 Netflix架构旨在高效可靠地同时为数百万用户提供内容。以下是其特性和组件的详细分析。 是否曾好奇Netflix如何让您目不转睛地享受无中断的流畅播放体验?幕后功臣正是Netflix架构,它负责提供吸引全球观众的无缝流媒体体验。Netflix的…...
宝塔面板运行docker的jenkins
1.在宝塔面板装docker,以及jenkins 2.ip:端口访问jenkins 3.获取密钥(点击日志) 4.配置容器内的jdk和maven环境(直接把jdk和maven文件夹放到jenkins容器映射的data文件下) 点击容器-->管理-->数据存储卷--.把相…...
【计算机视觉】目标检测:深度解析Detectron2:Meta开源目标检测与图像分割框架实战指南
深度解析Detectron2:Meta开源目标检测与图像分割框架实战指南 技术架构与设计哲学核心设计理念关键技术组件 环境配置与安装硬件建议配置详细安装步骤 实战流程详解1. 自定义数据集准备2. 模型配置与训练3. 模型评估与推理 核心功能扩展1. 自定义模型架构2. 混合精度…...
Notepad编辑器实现换行符替换
在不同的Note编辑器中,批量把换行替换为空的方法有所不同,以下是常见编辑器的操作方法: Notepad 打开文件后,按CtrlH打开“查找和替换”对话框,在“查找”字段中输入\r\n,在“替换为”字段中输入一个空格…...
【数据通信完全指南】从物理层到协议栈的深度解析
目录 1. 通信技术演进与核心挑战1.1 从电报到5G的技术变迁1.2 现代通信系统的三大瓶颈 2. 通信系统架构深度解构2.1 OSI七层模型运作原理2.2 TCP/IP协议栈实战解析 3. 物理层关键技术实现3.1 信号调制技术演进路线3.2 信道复用方案对比 4. 数据传输可靠性保障4.1 CRC校验算法数…...
SpringBoot多工程项目微服务install时如何不安装到本地仓库
在 Spring Boot 微服务项目中,比如各业务微服务模块由于不存在相互依赖度的问题,因此执行maven install时无需安装到本地仓库,但仍然需要参与构建(如 mvn compile 或 mvn package)。公共模块(如辅助工具…...
强化学习_Paper_2017_Curiosity-driven Exploration by Self-supervised Prediction
paper Link: ICM: Curiosity-driven Exploration by Self-supervised Prediction GITHUB Link: 官方: noreward-rl 1- 主要贡献 对好奇心进行定义与建模 好奇心定义:next state的prediction error作为该state novelty 如果智能体真的“懂”一个state,那…...
iview内存泄漏
iview在升级到view-design之前,是存在严重的内存泄漏问题的,而如果你在项目中大量使用了iview组件,就可能面临大量的升级工作要做,因为样式很多是不兼容的。 我们今天就看一下iview的源码,看看到底问题在哪里ÿ…...
【Hive入门】Hive高级特性:事务表与ACID特性详解
目录 1 Hive事务概述 2 ACID特性详解 3 Hive事务表的配置与启用 3.1 启用Hive事务支持 3.2 创建事务表 4 Hive事务操作流程 5 并发控制与隔离级别 5.1 Hive的锁机制 5.2 隔离级别 6 Hive事务的限制与优化 6.1 主要限制 6.2 性能优化建议 7 事务表操作示例 7.1 基本…...
Modbus转PROFIBUS网关:电动机保护新突破!
Modbus转PROFIBUS网关:电动机保护新突破! 在现代工业自动化领域,Modbus RTU和PROFIBUS DP是两种常见且重要的通讯协议。它们各自具有独特的优势和应用场景,但在实际工程中,我们常常需要将这两种不同协议的设备进行互联…...
大数据应用开发和项目实战-Seaborn
设计目标 seaborn 建立在 matplotlib 之上,专注于统计数据可视化,简化绘图过程,提供高级接口和美观的默认主题 Seaborn的安装: 1.pip install seaborn -i 2.conda install seaborn (清华源:https://pypi.t…...
弹窗探索鸿蒙之旅:揭秘弹窗的本质与奥秘
嘿,小伙伴们!👋 今天我们要一起探索那些在日常应用中无处不在的小精灵——弹窗!💬 🤔 弹窗到底是什么? 简单来说,弹窗就是应用程序中突然冒出来的交互元素,它们像…...
“技术创新+全球视野”良性驱动,首航新能的2025新征程正式起航
撰稿 | 行星 来源 | 贝多财经 近日,备受瞩目的“2025年光伏第一股”深圳市首航新能源股份有限公司(301658.SZ,下称“首航新能”)对外发布了上市后的首份年报,交出了一份量质齐升的业绩答卷,构筑更加强大的…...
黑群晖Moments视频无缩略图,安装第三方ffmpeg解决
黑群晖Moments视频无缩略图,安装第三方ffmpeg解决 1. 设置套件来源 黑群晖Moments视频无缩略图,安装第三方ffmpeg解决 基于这个文章,补充一下: 1. 设置套件来源 设置套件来源时(http://packages.synocommunity.com),…...
工业控制「混合架构」PK大战 —— 神经网络 + MPC vs 模糊 PID+MPC 的场景选型与实战指南
1. 引言 在工业控制领域,传统的 PID 控制器因其结构简单、稳定性好而被广泛应用,但面对复杂非线性系统时往往力不从心。模型预测控制(MPC)作为一种基于模型的先进控制策略,能够有效处理多变量、多约束问题,…...
树莓派智能摄像头实战指南:基于TensorFlow Lite的端到端AI部署
引言:嵌入式AI的革新力量 在物联网与人工智能深度融合的今天,树莓派这一信用卡大小的计算机正在成为边缘计算的核心载体。本文将手把手教你打造一款基于TensorFlow Lite的低功耗智能监控设备,通过MobileNetV2模型实现实时物体检测࿰…...
OpenCV 图形API(73)图像与通道拼接函数-----执行 查找表操作图像处理函数LUT()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 对矩阵执行查找表变换。 函数 LUT 使用来自查找表中的值填充输出矩阵。输入矩阵中的值作为查找表的索引。也就是说,函数对 src 中的…...
【MySQL】增删改查(CRUD)
目录 一. CRUD是什么 二. Create(新增数据) 2.1 单行数据全列插入 2.2 单行数据指定列插入 2.3 多行数据指定列插入 三. Retrieve (检索/查询) 3.1 全列查询 3.2 指定列查询 3.3 查询字段为表达式 3.4 为查询结果指定别名 3…...
iview 如何设置sider宽度
iview layout组件中,sider设置了默认宽度和最大宽度,在css样式文件中修改无效,原因是iview默认样式设置在了element.style中,只能通过行内样式修改 样式如下: image.png image.png 修改方式: 1.官方文档中写…...
Unity URP RenderTexture优化(二):深度图优化
目录 前言: 一、定位深度信息 1.1:k_DepthStencilFormat 1.2:k_DepthBufferBits 1.3:_CameraDepthTexture精度与大小 1.4:_CameraDepthAttachment数量 二、全代码 前言: 在上一篇文章:Un…...
iview表单提交验证时,出现空值参数被过滤掉不提交的问题解决
如图所示 有时候在表单提交的时候 个别参数是空值,但是看提交接口的反馈 发现空值的参数根本没传 这是因为表单验证给过滤掉了空值,有时候如果空值传不传都不无所谓,那可以不用管,但如果就算是空值也得传的吗,那就需要…...
GEO vs SEO:从搜索引擎到生成引擎的优化新思路
随着人工智能技术的快速发展,生成引擎优化(GEO)作为一种新兴的优化策略,逐渐成为企业和内容创作者关注的焦点。与传统的搜索引擎优化(SEO)相比,GEO不仅关注如何提升内容在搜索结果中的排名&…...
Python-pandas-操作csv文件(读取数据/写入数据)及csv语法详细分享
Python-pandas-操作csv文件(读取数据/写入数据) 提示:帮帮志会陆续更新非常多的IT技术知识,希望分享的内容对您有用。本章分享的是pandas的使用语法。前后每一小节的内容是存在的有:学习and理解的关联性。【帮帮志系列文章】:每个…...
如何在Windows上实现MacOS中的open命令
在MacOS的终端中,想要快速便捷的在Finder中打开当前目录,直接使用oepn即可。 open . 但是Windows中没有直接提供类似open这样的命令,既然没有直接提供,我们就间接手搓一个实现它。 步骤1:创建open.bat echo OFF expl…...
读论文笔记-LLaVA:Visual Instruction Tuning
读论文笔记-LLaVA:Visual Instruction Tuning 《Visual Instruction Tuning》 研究机构:Microsoft Research 发表于2023的NeurIPS Problems 填补指令微调方法(包括数据、模型、基准等)在多模态领域的空白。 Motivations 人工…...
Vue3源码学习3-结合vitetest来实现mini-vue
文章目录 前言✅ 当前已实现模块汇总(mini-vue)✅ 每个模块简要源码摘要1. reactive.ts2. effect.ts3. computed.ts4. ref.ts5. toRef.ts6. toRefs.ts ✅ 下一阶段推荐目标所有核心模块对应的 __tests__ 测试文件,**带完整注释**✅ reactive.…...
K8S - 从零构建 Docker 镜像与容器
一、基础概念 1.1 镜像(Image) “软件的标准化安装包” ,包含代码、环境和配置的只读模板。 技术解析 镜像由多个层组成,每层对应一个Dockerfile指令: 应用代码 → 运行时环境 → 系统工具链 → 启动配置核心特性…...
贪心算法求解边界最大数
贪心算法求解边界最大数(拼多多2504、排列问题) 多多有两个仅由正整数构成的数列 s1 和 s2,多多可以对 s1 进行任意次操作,每次操作可以置换 s1 中任意两个数字的位置。多多想让数列 s1 构成的数字尽可能大,但是不能比…...
C++类和对象(中)
类的默认成员函数 默认成员函数就是用户没有显式实现,编译器会自动生成的成员函数。一个类,我们不写的情况下编译器会默认生成6个默认成员函数,C11以后还会增加两个默认成员函数,移动构造和移动赋值。默认成员函数 很重要&#x…...
(Go Gin)Gin学习笔记(五)会话控制与参数验证:Cookie使用、Sessions使用、结构体验证参数、自定义验证参数
1. Cookie介绍 HTTP是无状态协议,服务器不能记录浏览器的访问状态,也就是说服务器不能区分两次请求是否由同一个客户端发出Cookie就是解决HTTP协议无状态的方案之一,中文是小甜饼的意思Cookie实际上就是服务器保存在浏览器上的一段信息。浏览…...
Windows 10 环境二进制方式安装 MySQL 8.0.41
文章目录 初始化数据库配置文件注册成服务启停服务链接服务器登录之后重置密码卸载 初始化数据库 D:\MySQL\MySQL8.0.41\mysql-8.0.41-winx64\mysql-8.0.41-winx64\bin\mysqld -I --console --basedirD:\MySQL\MySQL8.0.41\mysql-8.0.41-winx64\mysql-8.0.41-winx64 --datadi…...
Day.js一个2k轻量级的时间日期处理库
dayjs介绍 dayjs是一个极简快速2kB的JavaScript库,可以为浏览器处理解析、验证、操作和显示日期和时间,它的设计目标是提供一个简单、快速且功能强大的日期处理工具,同时保持极小的体积(仅 2KB 左右)。 Day.js 的 API…...
SQL实战:05之间隔连续数问题求解
概述 最近刷题时遇到一些比较有意思的题目,之前多次遇到一些求解连续数的问题,这次遇到了他们的变种,连续数可以间隔指定的数也视为是一个完整的“连续”。针对连续数的这类问题我们之前讲的可以利用等差数列的思想来解决,然而现…...
Windows下Dify安装及使用
Dify安装及使用 Dify 是开源的 LLM 应用开发平台。提供从 Agent 构建到 AI workflow 编排、RAG 检索、模型管理等能力,轻松构建和运营生成式 AI 原生应用。比 LangChain 更易用。 前置条件 windows下安装了docker环境-Windows11安装Docker-CSDN博客 下载 Git下载…...
回归分析丨基于R语言复杂数据回归与混合效应模型【多水平/分层/嵌套】技术与代码
回归分析是科学研究特别是生态学领域科学研究和数据分析十分重要的统计工具,可以回答众多科学问题,如环境因素对物种、种群、群落及生态系统或气候变化的影响;物种属性和系统发育对物种分布(多度)的影响等。纵观涉及数…...
EasyRTC嵌入式音视频实时通话SDK技术,打造低延迟、高安全的远程技术支持
一、背景 在当今数字化时代,远程技术支持已成为解决各类技术问题的关键手段。随着企业业务的拓展和技术的日益复杂,快速、高效地解决远程设备与系统的技术难题变得至关重要。EasyRTC作为一款高性能的实时通信解决方案,为远程技术支持提供了创…...
webrtc ICE 打洞总结
要搞清webrtc ICE连接是否能成功 , 主要是搞懂NAT NAT 类型 简单来说 一 是本地的ip和端口 决定外部的 ip和端口(和目的Ip和端口无关) , (这种情况又分为 , 无限制,仅限制 ip , 限制ip和port , 也就是…...
AI开发者的Docker实践:汉化(中文),更换镜像源,Dockerfile,部署Python项目
AI开发者的Docker实践:汉化(中文),更换镜像源,Dockerfile,部署Python项目 Dcoker官网1、核心概念镜像 (Image)容器 (Container)仓库 (Repository)DockerfileDocker Compose 2、Docker 的核心组件Docker 引擎…...
4.30阅读
一. 原文阅读 Passage 7(推荐阅读时间:6 - 7分钟) In department stores and closets all over the world, they are waiting. Their outward appearance seems rather appealing because they come in a variety of styles, textures, and …...
区块链:跨链协的技术突破与产业重构
引言:区块链的“孤岛困境”与跨链的使命 区块链技术自诞生以来,凭借去中心化、透明性和安全性重塑了金融、供应链、身份认证等领域。然而,不同区块链平台间的互操作性缺失,如同“数据与价值的孤岛”,严重限制…...