施磊老师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 构建编译环境在集群聊天服务器项目中已详细讲解。

技术栈

  1. 集群和分布式概念以及原理
  2. RPC远程过程调用原理以及实现
  3. Protobuf数据序列化和反序列化协议
  4. ZooKeeper分布式一致性协调服务应用以及编程
  5. muduo网络库编程
  6. conf配置文件读取
  7. 异步日志
  8. CMake构建项目集成编译环境
  9. github管理项目

代码没有集群多, 但是 知识更深入

集群和分布式理论

单机聊天服务器案例分析

服务器模块与业务:以单机聊天服务器为例,其包含用户管理、好友管理、群组管理、消息管理和后台管理五个模块。每个模块对应多项特定业务,如用户管理包括登录、注册、注销;好友管理涉及添加、删除好友等,这些业务由一个或多个相关函数实现。

性能与设计瓶颈:

  • 硬件资源限制单机服务器受硬件资源制约,例如 32 位 Linux 系统的聊天服务器,进程资源耗尽时,最多仅能支持约两万用户同时在线,难以承载更多客户端连接与服务。
  • 运维与代码编译成本高:由于模块都在同一项目运行单元,任意模块的修改(哪怕只是一行代码),都需重新编译整个项目代码(耗时约 2 小时),并重新部署(耗时约 3 小时),成本巨大。
  • 硬件资源分配不合理:不同模块对硬件资源需求不同,存在 CPU 密集型和 IO 密集型模块。但单机服务器只能采用平衡方案部署,无法针对各模块需求进行硬件资源的精准匹配。

集群聊天服务器分析

性能提升:通过水平扩展硬件资源,增加服务器数量(如三台或更多),每台独立运行聊天服务器程序,解决了单机服务器受硬件资源限制导致的用户并发量低的问题。

存在问题

  • 编译成本高:各服务器上的模块仍在同一项目中部署,运行于一个服务进程,因此任意模块修改仍需整体重新编译代码,且需多次部署到不同服务器,运维成本更高
  • 硬件资源分配不合理:集群只是简单扩展机器,无法针对不同模块(CPU 密集型或 IO 密集型)的硬件资源需求进行精准部署,存在资源浪费。例如后台管理模块并发需求低,却随整体系统在多台服务器部署 。

其他特点应用:集群部署方式简单,在高并发突发场景(如双 11)能快速通过增加服务器和负载均衡器提升服务能力

在集群中机器数量与性能并非成正比,原因如下:

  • 通信成本:机器增多使节点间通信开销增大,占用带宽与处理时间,易引发网络拥塞。
  • 分配难题:数据和任务难以在更多机器上均匀分配,易造成资源浪费。
  • 复杂故障:系统复杂度随机器数上升,故障和配置问题更易影响性能。
  • 并行局限:部分任务不适合大规模并行或并行度有限,加机器也无法提升性能。

以下任务不适合大规模集群并行处理:

  • 顺序依赖型:步骤间严格先后关联,无法拆分并行,如按序的数据清洗与分析。
  • 高通信成本型:执行中需频繁大量数据交互,易受网络带宽制约,如高频金融交易数据处理。
  • 任务粒度过小:任务简单微小,集群调度、协调开销超执行时间,如大量小文件简单格式转换。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

分布式系统介绍

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

定义与特点:将一个工程拆分为多个模块,每个模块独立部署为可运行的服务进程,多台服务器(分布式节点)协同工作构成完整系统。与集群区别在于,集群中每台服务器运行完整系统,而分布式是多台服务器共同组成一个系统 。

解决的问题

  • 并发与资源优化:可根据分布式节点的并发需求灵活扩容,如对用户管理模块所在节点增加服务器以支持更高并发,同时合理利用其他节点空闲资源,提升资源利用率。
  • 编译与部署优化模块独立部署,单个模块修改仅需重新编译和更新该模块,无需影响其他模块,大大降低编译和部署成本。
  • 硬件匹配优化:模块拆分后,可依据各模块特性(CPU 密集型或 IO 密集型)精准匹配硬件资源,实现资源的合理配置。

潜在问题与应对:分布式系统中部分节点故障可能影响整体服务,但实际生产中可通过配置主备服务器等容灾方案保障高可用性 。

多个模块的局限

模块划分困难

  • 模块之间的边界不清晰,容易出现功能重叠或代码重复。
  • 模块耦合度高,修改难、维护难。
  • 若划分不当,容易造成大量重复代码、逻辑冗余、维护成本高。

模块之间的通信复杂–重点

  • 分布式部署后,模块间通信需跨进程、跨机器
  • 函数调用从本地调用变为远程调用,需涉及:
    • 函数名、参数传输
    • 网络通信、序列化/反序列化
    • 异常处理、响应返回等机制

引入分布式 RPC 通信框架的意义

核心作用

让“跨主机远程调用函数”像“调用本地函数”一样简单透明

解决的核心问题

  1. 统一通信流程,屏蔽底层复杂性
    • 请求封装 + 网络传输 + 响应处理全部自动完成。
  2. 提高模块间调用效率与开发体验
    • 用户感知不到远程调用的差异,只需像本地函数一样使用接口。
  3. 支持参数序列化与传输
    • 使用 Protobuf 进行高效的数据结构序列化。
  4. 自动服务发现与定位
    • 通过 ZooKeeper 注册中心查找服务位置,实现动态服务绑定。

三大形态对比–重点

系统形态特点优势局限性
单机服务器所有模块在一个进程开发简单扩展性差、耦合高
集群服务器多台相同服务器水平扩展、简单粗暴不是线性扩展、资源浪费
分布式模块化系统各模块独立部署高可维护性、易扩展、低耦合设计复杂、通信困难(需RPC)

RPC 通信原理讲解整理

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为什么要使用 RPC?

  1. 为了解耦与扩展:
    • 大型系统按需模块化(不同模块对硬件/并发等要求不同),分布式部署成为必然。
    • 模块分布在不同进程、甚至不同机器上,相互之间仍需调用方法 —— 就必须跨进程/跨机器通信
  2. 屏蔽底层通信细节:
    • 本质是“远程函数调用”,但不同于本地函数调用的直接跳转和传参。
    • 不希望每个开发者都去手动处理 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被调方(如好友模块),真正执行业务方法
结果返回路径与调用路径对称,同样涉及打包、网络传输和反序列化

返回结果的组成与处理

  • 返回值通常包括:
    1. 错误码(errorCode)
    2. 错误信息(errorMessage)
    3. 业务数据(result)
  • 如果错误码为非零,说明远程执行出错,不应使用返回值,仅使用错误信息

框架的作用与实现目标

  1. 由框架来完成:
    • 参数/返回值的序列化与反序列化
    • 方法名的标识与分发
    • 网络通信(请求发送/接收)
    • 错误处理与返回机制
  2. 开发者只需写业务逻辑函数,像调用本地函数一样调用远程服务

举例巩固(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推荐用途
stringUTF-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**里面的函数

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

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

相关文章

基于LangChain构建最小智能体(Agent)实现指南

摘要 本文完整解析基于LangChain的极简Agent实现方案&#xff0c;通过26行代码构建具备网络搜索能力的对话系统&#xff0c;涵盖Agent初始化、工具集成、流式回调等核心技术要点。适用于LLM应用开发者快速入门Agent开发。(参考项目代码&#xff1a;Minimal Agent) 系统架构设计…

AWTK:一键切换皮肤,打造个性化UI

想让你的应用在不同场景下都能完美呈现吗&#xff1f;皮肤切换功能必不可少&#xff01;本文将介绍AWTK&#xff0c;一款强大的GUI框架&#xff0c;它通过内置资源管理和优化缓存&#xff0c;轻松实现皮肤切换功能。 前言 当今的UI应用中&#xff0c;为了满足不同使用场景和…

【Vagrant+VirtualBox创建自动化虚拟环境】Ansible测试Playbook

文章目录 Vagrant安装vagrant安装 VirtualBox如何使用 Ansible安装AnsiblePlaybook测试创建hosts文件创建setup.yml文件 Vagrant Vagrant是一个基于Ruby的工具&#xff0c;用于创建和部署虚拟化开发环境。它使用Oracle的开源VirtualBox虚拟化系统&#xff0c;使用 Chef创建自动…

AI在医疗领域的10大应用:从疾病预测到手术机器人

AI在医疗领域的10大应用&#xff1a;从疾病预测到手术机器人 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 AI在医疗领域的10大应用&#xff1a;从疾病预测到手术机器人摘要引言1. 医学影像诊断&#xff1a;从静态…

Win11 配置 Git 绑定 Github 账号的方法与问题汇总

目录 一、创建 Github 项目库&#xff08;远程仓库&#xff09;二、配置安装好的 Git1. 设置用户信息2. 查看已配置的信息3. 建立本地仓库4. Git 的常用命令1&#xff09;git checkout&#xff08;切换&#xff09;2&#xff09;git push&#xff08;上传&#xff09;3&#xf…

6.应用层

6. 应用层 1. 概述 应用层是计算机网络体系结构的最顶层&#xff0c;是设计和建立计算机网络的最终目的&#xff0c;也是计算机网络中发展最快的部分 早期基于文本的应用&#xff08;电子邮件、远程登录、文件传输、新闻组&#xff09;20世纪90年代将因特网带入千家万户的万维…

FPGA 100G UDP纯逻辑协议栈

随着器件等级的升高&#xff0c;高速serdes的线速率也随之提高&#xff0c;RFSOC 4x最大可支持100G&#xff0c;主流方案为RDMA方案&#xff0c;该方案相对比较复杂&#xff0c;除了需要负责逻辑端的开发&#xff0c;还需操作系统中开发RDMA的驱动&#xff0c;对于对丢包不那么…

CSS实现DIV水平与垂直居中方法总结

大家好&#xff0c;欢迎来到程序视点&#xff01;我是你们的老朋友.小二&#xff01; CSS实现DIV水平与垂直居中方法总结 一、水平居中方案 标准方法 .center-div {margin-left: auto;margin-right: auto; }关键点&#xff1a;必须声明DOCTYPE&#xff08;推荐XHTML 1.0 Tran…

Qt快速上手:QSettings高效配置读写实战指南

文章目录 前言一、QSettings初识&#xff1a;配置管理利器二、基础操作三板斧2.1 文件读写基础2.2 数据类型处理指南2.3 分组管理技巧 三、高级技巧&#xff1a;精准控制配置项3.1 监听配置变更3.2 批量操作配置项 四、避坑指南&#xff1a;那些你可能会遇到的问题4.1 键顺序重…

2025运维工程师面试题1(答案在后一张)

一、逻辑思维能力考核&#xff1a; 问题1&#xff1a; 3个人去投宿&#xff0c;一晚30元三个人每人掏了10元凑够30元交给了老板后来老板说今天优惠只要25元就够了&#xff0c;拿出5元命令服务生退还给他们&#xff0c;服务生偷偷藏起了2元&#xff0c;然后&#xff0c;把剩下…

react中封装一个预览.doc和.docx文件的组件

主要用到了mammoth这个插件,mammoth.js‌是一个JavaScript库&#xff0c;主要用于将Microsoft Word文档&#xff08;.docx格式&#xff09;转换为HTML。它可以通过Node.js环境使用&#xff0c;也可以直接在浏览器中使用。 关键代码: import mammoth from mammoth; import { u…

c#WebsocketSever

这是一个winFrom的小工具&#xff0c;用于再本机创建一个c#服务的项目。 1、将本机ip地址改为左上角Ip&#xff0c;注意没有“&#xff1a;”后的部分&#xff0c;那是端口号。 2、点击中间按钮&#xff0c;启动服务器 3、如果启动成功&#xff0c;会在下面显示启动成功&…

顶会招牌idea:机器学习+组合优化 优秀论文合集

2025深度学习发论文&模型涨点之——机器学习组合优化 机器学习&#xff08;ML&#xff09;与组合优化&#xff08;CO&#xff09;的交叉研究已成为运筹学与人工智能领域的前沿方向。传统组合优化方法&#xff08;如分支定界、动态规划&#xff09;虽在理论上有严格的性能保…

服务器硬件老化导致性能下降的排查与优化

随着企业数字化转型的深入&#xff0c;服务器作为IT基础设施的核心载体&#xff0c;其稳定性与性能直接影响业务连续性。然而&#xff0c;硬件老化导致的性能衰减问题普遍存在且易被忽视。本报告通过系统性分析服务器硬件老化现象&#xff0c;提出多维度排查方法与优化方案&…

删除k8s某命名空间,一直卡住了怎么办?

以 kubectl delete ns cert-manager 命令卡住为例&#xff0c;并且命名空间一直处于 Terminating 状态&#xff0c;说明 Kubernetes 无法完成删除操作&#xff0c;通常是因为 Finalizers 阻塞或某些资源无法正常清理。 解决方法 1. 检查命名空间状态 kubectl get ns cert-man…

【分享】变声器大师[特殊字符]乔碧萝同款变声[特殊字符]游戏变声[特殊字符]

多种变声器效果可选&#xff1a;爷爷、大叔、小孩、机器人...... 使用变声器时只需轻轻一点&#xff0c;让你成为潮人 【应用名称】&#xff1a;变声器大师 【应用版本】&#xff1a;6.1.35 【应用大小】&#xff1a;116M 【测试机型】&#xff1a;小米14 【下载链接】:https:…

【Part 2安卓原生360°VR播放器开发实战】第二节|基于等距圆柱投影方式实现全景视频渲染

《VR 360全景视频开发》专栏 将带你深入探索从全景视频制作到Unity眼镜端应用开发的全流程技术。专栏内容涵盖安卓原生VR播放器开发、Unity VR视频渲染与手势交互、360全景视频制作与优化&#xff0c;以及高分辨率视频性能优化等实战技巧。 &#x1f4dd; 希望通过这个专栏&am…

【JavaScript】相等运算符、条件运算符

1、相等运算符 &#xff08;1&#xff09;&#xff08;相等&#xff09; 相等运算符用来比较两个值是否相等&#xff0c;如果相等会返回true&#xff0c;否则返回false <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"…

OceanBase数据库-学习笔记5-用户

用户相关命令 命令描述CREATE USER ‘username’‘host’ IDENTIFIED BY ‘password’;创建用户。GRANT ALL PRIVILEGES ON database_name.* TO ‘test_user’‘%’;给用户授权所有权限。GRANT SELECT, INSERT, UPDATE ON database_name.* TO ‘test_user’‘%’;给用户授权指…

K8S Secret 快速开始

一、什么是 Secret&#xff1f; Kubernetes&#xff08;K8s&#xff09;中的 Secret 是一种用于存储和管理敏感信息&#xff08;如密码、令牌、证书、API 密钥等&#xff09;的资源对象。它避免了将敏感数据明文写入配置文件、镜像或代码中&#xff0c;提供了一种更安全的方式…