深入实战:使用C++开发高性能RESTful API
🧑 博主简介:CSDN博客专家、CSDN平台优质创作者,高级开发工程师,数学专业,10年以上C/C++, C#, Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C++、C#等开发语言,熟悉Java常用开发技术,能熟练应用常用数据库SQL server,Oracle,mysql,postgresql等进行开发应用,熟悉DICOM医学影像及DICOM协议,业余时间自学JavaScript,Vue,qt,python等,具备多种混合语言开发能力。撰写博客分享知识,致力于帮助编程爱好者共同进步。欢迎关注、交流及合作,提供技术支持与解决方案。
技术合作请加本人wx(注明来自csdn):xt20160813
深入实战:使用C++开发高性能RESTful API
随着互联网应用的快速发展,RESTful API(Representational State Transfer)成为构建分布式系统和微服务架构的主要方式之一。虽然C++以其卓越的性能和资源控制能力在系统编程中占据重要地位,但相比于其他高级语言(如Python、Java、Go),在RESTful API开发上的应用相对较少。本文将深入探讨如何在C++中开发高性能的RESTful API,解决实际项目中的应用问题,并通过详尽的示例代码,帮助开发者掌握C++ RESTful开发的核心技巧。
目录
- RESTful API基础概念
- 什么是RESTful API
- RESTful API的特点
- C++在RESTful API开发中的优势与挑战
- 常用C++ RESTful框架与库
- CppRESTSDK(Casablanca)
- Pistache
- Crow
- restbed
- 选择合适的框架
- 环境搭建与项目初始化
- 安装必要的工具与库
- 创建C++ RESTful项目结构
- 实战案例:构建一个简易的C++ RESTful API
- 需求描述
- 使用Crow框架实现API
- 详细代码讲解
- 测试API
- 性能优化策略
- 多线程与异步处理
- 高效的内存管理
- 负载均衡与水平扩展
- 使用缓存提升响应速度
- 最佳实践与常见问题
- 设计良好的API接口
- 错误处理与日志记录
- 安全性考虑
- 常见问题及解决方案
- 总结与展望
- 参考资料
RESTful API基础概念
什么是RESTful API
RESTful API是基于REST(Representational State Transfer)架构风格构建的应用程序接口。REST由Roy Fielding在其博士论文中提出,强调通过无状态的通信协议(通常是HTTP)来管理和交换资源。RESTful API利用HTTP协议的动词(如GET、POST、PUT、DELETE)来操作资源,具有简单、可扩展和易于维护的特点。
RESTful API的特点
- 无状态性:每个请求都是独立的,服务器不保留客户端的状态信息。所有必要的信息都包含在每个请求中。
- 统一接口:通过标准化的接口简化系统架构,提升组件之间的独立性。
- 资源导向:将系统中的实体抽象为资源,通过URI(统一资源标识符)进行标识和访问。
- 多种表现形式:支持JSON、XML等多种数据格式,以满足不同客户端的需求。
- 客户端-服务器架构:客户端和服务器分离,互相独立,提升系统的灵活性和可维护性。
C++在RESTful API开发中的优势与挑战
优势:
- 高性能:C++具有接近硬件的执行效率,适用于对性能要求极高的网络应用。
- 资源控制:精细的内存管理和资源控制能力,适合构建资源受限环境下的应用。
- 广泛的库支持:丰富的第三方库和框架支持,助力快速开发。
挑战:
- 开发复杂度:相比于高级语言,C++在内存管理、并发编程等方面的复杂性更高。
- 生态系统:虽然C++生态日益丰富,但在RESTful API开发方面的工具和框架相比其他语言仍略显不足。
- 学习曲线:需要深入理解C++的底层机制及高级特性,学习曲线较陡。
常用C++ RESTful框架与库
在C++中,有多种框架和库可以用于开发RESTful API。以下是几种常用的框架:
CppRESTSDK(Casablanca)
简介:由微软开发的跨平台C++ REST SDK(简称CppRESTSDK或Casablanca),提供了丰富的HTTP通信、JSON处理、异步编程接口。
特点:
- 跨平台支持(Windows、Linux、macOS)。
- 内置JSON解析与生成。
- 支持异步操作,提升性能。
- 良好的文档与社区支持。
安装方式:
可以通过包管理器(如vcpkg)安装:
vcpkg install cpprestsdk
Pistache
简介:Pistache是一个轻量级的C++ REST框架,支持快速开发高性能的RESTful服务。
特点:
- 简单易用的API。
- 高效的HTTP服务器实现。
- 支持多线程处理。
安装方式:
需要从GitHub源码编译安装:
git clone https://github.com/oktal/pistache.git
cd pistache
mkdir build && cd build
cmake ..
make
sudo make install
Crow
简介:Crow是一个轻量级的C++微框架,借鉴了Python的Flask,支持路由、模板和JSON处理。
特点:
- 类似Flask的API设计,易于上手。
- 内置路由系统。
- 支持多线程和异步处理。
安装方式:
Crow是一个头文件库,只需包含相应的头文件即可使用。
// 示例:包含Crow头文件
#include "crow_all.h"
可以通过GitHub获取最新版本:Crow GitHub
restbed
简介:restbed是一个现代化的C++ RESTful框架,支持异步I/O、SSL、路由等功能。
特点:
- 高性能异步网络编程。
- 丰富的功能支持(如认证、CORS)。
- 易于扩展和定制。
安装方式:
需要从GitHub源码编译安装:
git clone https://github.com/Corvusoft/restbed.git
cd restbed
mkdir build && cd build
cmake ..
make
sudo make install
选择合适的框架
选择合适的C++ RESTful框架应根据项目需求、团队熟悉度和框架的特点来定。对于需要跨平台支持和丰富功能的项目,CppRESTSDK是一个不错的选择;而对于追求简洁和快速开发的项目,Crow或Pistache更为适合。
环境搭建与项目初始化
在开始开发C++ RESTful API之前,需要搭建开发环境并初始化项目。
安装必要的工具与库
- C++编译器:推荐使用支持C++11及以上标准的编译器,如GCC、Clang或MSVC。
- CMake:跨平台的构建工具,用于管理项目构建过程。
- 所选框架的依赖库:根据选择的框架,可能需要安装Boost、OpenSSL等库。
以Crow为例,安装步骤如下:
-
安装C++编译器和CMake:
sudo apt-get update sudo apt-get install build-essential cmake
-
获取Crow库:
Crow是一个头文件库,可以直接下载或使用包管理器:
git clone https://github.com/CrowCpp/Crow.git cd Crow # 将crow_all.h复制到项目中 cp single_include/crow_all.h /path/to/your/project/include/
创建C++ RESTful项目结构
建议采用清晰的项目结构,便于维护和扩展。
my_restful_api/
├── CMakeLists.txt
├── include/
│ └── crow_all.h
├── src/
│ └── main.cpp
└── build/
CMakeLists.txt示例:
cmake_minimum_required(VERSION 3.5)
project(MyRestfulAPI)set(CMAKE_CXX_STANDARD 14)# 包含Crow头文件目录
include_directories(include)# 添加源文件
add_executable(my_restful_api src/main.cpp)
实战案例:构建一个简易的C++ RESTful API
需求描述
构建一个简单的用户管理API,支持以下操作:
- 获取用户列表(GET /users)
- 获取单个用户信息(GET /users/{id})
- 创建新用户(POST /users)
- 更新用户信息(PUT /users/{id})
- 删除用户(DELETE /users/{id})
假设用户数据存储在内存中,使用JSON作为数据交换格式。
使用Crow框架实现API
Crow框架以其简洁的API设计,非常适合快速开发RESTful服务。以下是详细的代码实现。
详细代码讲解
// src/main.cpp
#include "crow_all.h"
#include <unordered_map>
#include <mutex>struct User {int id;std::string name;std::string email;
};// 全局用户存储
std::unordered_map<int, User> users;
std::mutex users_mutex;
int current_id = 1;int main()
{crow::SimpleApp app;// 获取用户列表CROW_ROUTE(app, "/users").methods("GET"_method)([](){crow::json::wvalue result;{std::lock_guard<std::mutex> lock(users_mutex);for (const auto& pair : users) {crow::json::wvalue user;user["id"] = pair.second.id;user["name"] = pair.second.name;user["email"] = pair.second.email;result["users"].push_back(user);}}return crow::response(result);});// 获取单个用户信息CROW_ROUTE(app, "/users/<int>").methods("GET"_method)([](int id){crow::json::wvalue result;{std::lock_guard<std::mutex> lock(users_mutex);auto it = users.find(id);if (it != users.end()) {result["id"] = it->second.id;result["name"] = it->second.name;result["email"] = it->second.email;return crow::response(result);}}return crow::response(404, "User not found");});// 创建新用户CROW_ROUTE(app, "/users").methods("POST"_method)([](const crow::request& req){auto x = crow::json::load(req.body);if (!x)return crow::response(400, "Invalid JSON");if (!x.has("name") || !x.has("email"))return crow::response(400, "Missing fields");User new_user;{std::lock_guard<std::mutex> lock(users_mutex);new_user.id = current_id++;new_user.name = x["name"].s();new_user.email = x["email"].s();users[new_user.id] = new_user;}crow::json::wvalue result;result["id"] = new_user.id;result["name"] = new_user.name;result["email"] = new_user.email;return crow::response(201, result);});// 更新用户信息CROW_ROUTE(app, "/users/<int>").methods("PUT"_method)([](int id, const crow::request& req){auto x = crow::json::load(req.body);if (!x)return crow::response(400, "Invalid JSON");std::lock_guard<std::mutex> lock(users_mutex);auto it = users.find(id);if (it == users.end()) {return crow::response(404, "User not found");}if (x.has("name")) {it->second.name = x["name"].s();}if (x.has("email")) {it->second.email = x["email"].s();}crow::json::wvalue result;result["id"] = it->second.id;result["name"] = it->second.name;result["email"] = it->second.email;return crow::response(result);});// 删除用户CROW_ROUTE(app, "/users/<int>").methods("DELETE"_method)([](int id){std::lock_guard<std::mutex> lock(users_mutex);auto it = users.find(id);if (it != users.end()) {users.erase(it);return crow::response(200, "User deleted successfully");}return crow::response(404, "User not found");});// 运行服务器app.port(18080).multithreaded().run();
}
代码解释:
-
引入Crow和必要的库:
#include "crow_all.h" #include <unordered_map> #include <mutex>
crow_all.h
:包含Crow框架的所有功能。unordered_map
:用于存储用户数据的哈希表。mutex
:用于线程安全的同步控制。
-
定义用户结构体:
struct User {int id;std::string name;std::string email; };
用于表示用户信息,包括ID、姓名和邮箱。
-
全局用户存储与同步控制:
std::unordered_map<int, User> users; std::mutex users_mutex; int current_id = 1;
users
:存储用户信息的哈希表,键为用户ID。users_mutex
:用于保护users
数据结构,确保线程安全。current_id
:用于生成唯一的用户ID。
-
定义RESTful路由与处理逻辑:
-
获取用户列表(GET /users):
CROW_ROUTE(app, "/users").methods("GET"_method)([](){crow::json::wvalue result;{std::lock_guard<std::mutex> lock(users_mutex);for (const auto& pair : users) {crow::json::wvalue user;user["id"] = pair.second.id;user["name"] = pair.second.name;user["email"] = pair.second.email;result["users"].push_back(user);}}return crow::response(result); });
遍历所有用户,构建JSON响应返回。
-
获取单个用户信息(GET /users/{id}):
CROW_ROUTE(app, "/users/<int>").methods("GET"_method)([](int id){crow::json::wvalue result;{std::lock_guard<std::mutex> lock(users_mutex);auto it = users.find(id);if (it != users.end()) {result["id"] = it->second.id;result["name"] = it->second.name;result["email"] = it->second.email;return crow::response(result);}}return crow::response(404, "User not found"); });
根据用户ID查找用户信息,若存在则返回JSON响应,否则返回404错误。
-
创建新用户(POST /users):
CROW_ROUTE(app, "/users").methods("POST"_method)([](const crow::request& req){auto x = crow::json::load(req.body);if (!x)return crow::response(400, "Invalid JSON");if (!x.has("name") || !x.has("email"))return crow::response(400, "Missing fields");User new_user;{std::lock_guard<std::mutex> lock(users_mutex);new_user.id = current_id++;new_user.name = x["name"].s();new_user.email = x["email"].s();users[new_user.id] = new_user;}crow::json::wvalue result;result["id"] = new_user.id;result["name"] = new_user.name;result["email"] = new_user.email;return crow::response(201, result); });
解析请求体中的JSON数据,创建新的用户并返回其信息。
-
更新用户信息(PUT /users/{id}):
CROW_ROUTE(app, "/users/<int>").methods("PUT"_method)([](int id, const crow::request& req){auto x = crow::json::load(req.body);if (!x)return crow::response(400, "Invalid JSON");std::lock_guard<std::mutex> lock(users_mutex);auto it = users.find(id);if (it == users.end()) {return crow::response(404, "User not found");}if (x.has("name")) {it->second.name = x["name"].s();}if (x.has("email")) {it->second.email = x["email"].s();}crow::json::wvalue result;result["id"] = it->second.id;result["name"] = it->second.name;result["email"] = it->second.email;return crow::response(result); });
根据用户ID查找并更新用户信息,返回更新后的数据。
-
删除用户(DELETE /users/{id}):
CROW_ROUTE(app, "/users/<int>").methods("DELETE"_method)([](int id){std::lock_guard<std::mutex> lock(users_mutex);auto it = users.find(id);if (it != users.end()) {users.erase(it);return crow::response(200, "User deleted successfully");}return crow::response(404, "User not found"); });
根据用户ID删除用户,返回操作结果。
-
-
运行服务器:
// 运行服务器 app.port(18080).multithreaded().run();
配置服务器监听端口18080,启用多线程模式,启动服务。
编译与运行
CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(MyRestfulAPI)set(CMAKE_CXX_STANDARD 14)# 包含Crow头文件目录
include_directories(include)# 添加源文件
add_executable(my_restful_api src/main.cpp)
编译步骤:
mkdir build
cd build
cmake ..
make
运行服务器:
./my_restful_api
服务器启动后,将监听18080端口,准备接受客户端请求。
测试API
可以使用curl
或Postman等工具测试API。
-
创建新用户:
curl -X POST -H "Content-Type: application/json" -d '{"name":"Alice","email":"alice@example.com"}' http://localhost:18080/users
响应:
{"id": 1,"name": "Alice","email": "alice@example.com" }
-
获取用户列表:
curl http://localhost:18080/users
响应:
{"users": [{"id": 1,"name": "Alice","email": "alice@example.com"}] }
-
获取单个用户信息:
curl http://localhost:18080/users/1
响应:
{"id": 1,"name": "Alice","email": "alice@example.com" }
-
更新用户信息:
curl -X PUT -H "Content-Type: application/json" -d '{"email":"alice_new@example.com"}' http://localhost:18080/users/1
响应:
{"id": 1,"name": "Alice","email": "alice_new@example.com" }
-
删除用户:
curl -X DELETE http://localhost:18080/users/1
响应:
User deleted successfully
性能优化策略
在实际项目中,为了确保C++ RESTful API的高性能,需要对系统进行多层次的优化。以下是常见的性能优化策略:
多线程与异步处理
策略:
- 利用多线程或异步I/O模型处理并发请求,充分利用多核CPU资源。
- 使用线程池管理线程,避免频繁创建和销毁线程带来的开销。
实现方法:
- 线程池:如前述实战案例中使用的
ThreadPool
类。 - 异步框架:使用Boost.Asio等异步网络库,实现非阻塞I/O和事件驱动模型。
高效的内存管理
策略:
- 使用内存池等内存管理技术,减少动态内存分配和释放的频率。
- 避免不必要的内存拷贝和对象创建,提升内存利用效率。
实现方法:
- 内存池:前述案例中的
MemoryPool
模板类。 - 使用智能指针:如
std::shared_ptr
和std::unique_ptr
,自动管理内存生命周期,防止内存泄漏。
负载均衡与水平扩展
策略:
- 将请求分配到多个服务器实例,分担负载,提升系统的并发处理能力。
- 使用反向代理(如Nginx、HAProxy)实现负载均衡,提升系统的可用性和扩展性。
实现方法:
- 配置Nginx作为反向代理,均衡分配请求到多个C++ RESTful服务器实例。
- 实现服务注册与发现机制,自动管理服务器实例的动态变化。
使用缓存提升响应速度
策略:
- 对频繁访问的数据进行缓存,减少数据库查询或复杂计算的次数,提升响应速度。
- 使用内存缓存(如Redis)或本地缓存机制,减轻后端负载。
实现方法:
- 内存缓存:在C++应用中使用内存数据结构(如
std::unordered_map
)存储缓存数据。 - 分布式缓存:集成Redis等分布式缓存系统,通过网络访问提升缓存容量和灵活性。
使用零拷贝技术
策略:
- 通过零拷贝技术减少数据在用户态与内核态之间的拷贝次数,提升数据传输效率。
实现方法:
- sendfile:在Linux中使用
sendfile
系统调用,从文件描述符直接传输数据到Socket,减少不必要的数据拷贝。off_t offset = 0; ssize_t bytesSent = sendfile(clientSockfd, fileFd, &offset, fileSize);
- mmap:使用
mmap
将文件或共享内存映射到用户空间,直接在应用程序中访问数据,减少内存拷贝。void* mapped = mmap(NULL, dataSize, PROT_READ, MAP_PRIVATE, dataFd, 0); write(clientSockfd, mapped, dataSize); munmap(mapped, dataSize);
性能分析与调优
策略:
- 使用性能分析工具(如
perf
、Valgrind
、Intel VTune Profiler
)监测系统性能,识别瓶颈。 - 基于分析结果,针对性地优化代码和系统配置,持续提升性能。
实现方法:
- 使用
perf
分析CPU性能:perf record -g ./my_restful_api perf report
- 使用
Valgrind
检测内存问题:valgrind --tool=memcheck ./my_restful_api
- 使用
Intel VTune Profiler
进行深入分析。
最佳实践与常见问题
设计良好的API接口
- 遵循RESTful原则:确保API设计符合RESTful架构风格,使用正确的HTTP动词和状态码。
- 清晰的资源命名:资源的URI应当直观易懂,反映资源的层次结构。
GET /users - 获取用户列表 GET /users/{id} - 获取特定用户信息 POST /users - 创建新用户 PUT /users/{id} - 更新用户信息 DELETE /users/{id} - 删除用户
- 版本控制:通过URI或HTTP头部管理API版本,确保向后兼容性。
GET /v1/users
错误处理与日志记录
- 统一的错误响应:定义统一的错误响应格式,提供明确的错误信息,便于客户端处理。
{"error": {"code": 404,"message": "User not found"} }
- 详细的日志记录:记录关键操作和错误信息,辅助调试和监控。
- 日志级别:如INFO、WARNING、ERROR等,区分日志重要性。
- 日志格式:包含时间戳、日志级别、消息内容等关键信息。
安全性考虑
- 认证与授权:确保API接口的访问权限,防止未授权的访问。
- 使用OAuth2.0、JWT(JSON Web Token)等认证机制。
- 输入验证:对客户端输入进行严格验证,防止SQL注入、跨站脚本等攻击。
- 加密传输:使用HTTPS加密数据传输,保护敏感信息不被窃取。
// 使用OpenSSL配置HTTPS crow::SSLContext sslContext; sslContext.load_cert_chain("server.crt", "server.key"); app.ssl_context(sslContext);
常见问题及解决方案
-
多线程竞争导致的数据不一致:
- 解决方案:使用互斥锁(
std::mutex
)、读写锁(std::shared_mutex
)等同步机制,确保数据的线程安全访问。
- 解决方案:使用互斥锁(
-
内存泄漏:
- 解决方案:使用智能指针(
std::shared_ptr
、std::unique_ptr
)自动管理内存,避免手动分配与释放,减少内存泄漏风险。
- 解决方案:使用智能指针(
-
高并发下的性能瓶颈:
- 解决方案:采用多线程、异步I/O和高效的多路复用机制,提升系统的并发处理能力。
-
API响应时间过长:
- 解决方案:优化数据处理逻辑,使用缓存机制减少重复计算,使用零拷贝技术提升数据传输效率。
-
错误处理不当:
- 解决方案:设计统一的错误响应机制,捕获和处理所有可能的异常和错误情况,确保系统的稳定性。
总结与展望
本文通过详细的讲解和实战案例,深入探讨了如何在C++中开发高性能的RESTful API。我们从RESTful API的基础概念入手,介绍了C++常用的RESTful框架与库,并通过一个简易的用户管理API示例,展示了如何使用Crow框架实现各类API操作。随后,我们探讨了多种性能优化策略,包括多线程与异步处理、高效的内存管理、负载均衡与水平扩展、使用缓存与零拷贝技术等,帮助开发者构建高效、稳定的网络应用。
在实际开发过程中,选择合适的框架、合理设计API接口、注重性能优化和安全性,并结合持续的性能分析与调优,是确保C++ RESTful API高效运行的关键。随着C++生态系统的不断发展,未来将有更多高性能、易用的RESTful框架和工具涌现,进一步推动C++在网络应用开发中的广泛应用。
进一步学习:
- 探索其他C++ RESTful框架,如CppRESTSDK、Pistache等,了解它们的特点与适用场景。
- 学习并实践更高级的性能优化技术,如异步编程模型、GPU加速等。
- 阅读相关书籍和文档,提升C++网络编程和系统优化的知识水平。
参考资料
- Crow GitHub
- CppRESTSDK(Casablanca) GitHub
- Pistache GitHub
- restbed GitHub
- Boost.Asio 官方文档
- Beej’s Guide to Network Programming
- C++ Concurrency in Action - Anthony Williams
- Effective Modern C++ - Scott Meyers
- Intel VTune Profiler Documentation
- Google PerfTools
- C++ Reference
- C++ RESTful API Development Guide
标签
C++、RESTful API、网络编程、性能优化、多线程、异步I/O、Crow、CppRESTSDK、Pistache、restbed、微服务
版权声明
本文版权归作者所有,未经允许,请勿转载。
相关文章:
深入实战:使用C++开发高性能RESTful API
🧑 博主简介:CSDN博客专家、CSDN平台优质创作者,高级开发工程师,数学专业,10年以上C/C, C#, Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C、C#等开发语言,熟悉Java常用开…...
C++之虚函数 Virtual Function
1. 普通虚函数(Virtual Function) 定义:基类中用 virtual 声明,允许派生类 覆盖(Override)。特点: 基类可提供默认实现。派生类可选择性覆盖(若不覆盖,则调用基类版本&a…...
【java实现+4种变体完整例子】排序算法中【选择排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格
以下是选择排序的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格: 一、选择排序基础实现 原理 每一轮遍历未排序部分,找到最小元素并交换到当前起始位置,逐步构建已排序序列。 代码示例 pu…...
DNS主从同步实验
dns域名解析原理 实验步骤1、主dns要完成dns解析:192.168.21.128 [rootlocalhost ~]# yum install bind -y [rootlocalhost ~]# systemctl start named [rootlocalhost ~]# vim /etc/named.conf options { listen-on port 53 { any; }; direct…...
UIjavaScritIU
1、直接执行js脚本:document.documentElement.scrollTop1000 document.getElementById(“su”).click() 弊端: js自己带的元素定位方法不如selenium的丰富 不支持xpath css 等 定位元素操作不是很灵活。 需要借助js脚本传入 -selenium定位 js 负责执行动…...
Manus技术架构、实现内幕及分布式智能体项目实战 线上高级实训班
Manus技术架构、实现内幕及分布式智能体项目实战 线上高级实训班 模块一:解密Manus分布式多智能体工作原理和架构内幕 基于Claude和Qwen的大模型智能体Manus为何能够迅速成为全球讨论热度最高、使用体验最好、产业界最火爆的大模型智能体产品? Ma…...
Java——二维数组
一、概念 二维数组也是一种容器,不同于一维数组,该容器存储的都是一维数组容器。 二、定义格式 1.数据类型[ ] [ ] 变量名; 2.数据类型 变量名 [ ] [ ]; 3.数据类型 [ ] 变量名 [ ]; 三、动态初始化 (一)书写 1.格式 数据…...
豆瓣图书数据采集与可视化分析(一)- 豆瓣图书数据爬取
文章目录 前言一、数据爬取步骤二、豆瓣图书页面分析1. 图书分类标签页面分析2. 图书页面分析 三、数据采集实现1. 图书分类标签数据采集2. 图书数据采集3. 把多个分类的CSV数据文件整合到一个CSV文件中 前言 在当今大数据时代,数据的获取与整理对于各个领域的研…...
车载诊断新架构--- SOVD初入门(上)
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…...
test——自动化测试
目录 一概念 1自动化 2回归测试 3自动化分类 3.1接口自动化 3.2UI自动化 4自动化测试金字塔 5web自动化测试 6工作原理 二函数 1元素定位 1.1cssSelector 编辑1.2xpath 语法 2操作对象 2.1click() 2.2send_keys() 2.3clear() 2.4text 2.5get_attribu…...
Kubernetes相关的名词解释CoreDNS插件(2)
为什么需要DNS服务? service发现是k8s中的一个重要机制,其基本功能为:在集群内通过服务名对服务进行访问,即需要完成从服务名到ClusterIP的解析。 k8s主要有两种service发现机制:环境变量和DNS。没有DNS服务的时候&am…...
【记录】服务器用命令开启端口号
这里记录下如何在服务器上开启适用于外界访问的端口号。 方法 1 使用防火墙 1 su ,命令 输入密码 切换到root节点 2 开启防火墙 systemctl start firewalld3 配置开放端口 firewall-cmd --zonepublic --add-port8282/tcp --permanent4 重启防火墙 firewall-cmd…...
代码审计入门 原生态sql注入篇
前置知识: 漏洞形成的原因: 1、可控的参数 2、函数缺陷 代码审计的步骤: 1、全局使用正则搜索 漏洞函数 ,然后根据函数看变量是否可控,再看函数是否有过滤 2、根据web的功能点寻找函数,然后根据函数看…...
数据结构0基础学习堆
文章目录 简介公式建立堆函数解释 堆排序O(n logn)topk问题 简介 堆是一种重要的数据结构,是一种完全二叉树,(二叉树的内容后面会出), 堆分为大小堆,大堆,左右结点都小于根节点,&am…...
分析虚幻引擎编辑器中使用 TAA 或 TSR 时角色眨眼导致的眼睛模糊问题
1. 引言 用户反馈在使用虚幻引擎编辑器时,当抗锯齿方法设置为时间性抗锯齿 (TAA) 或时间性超级分辨率 (TSR) 时,角色的眼睛在眨眼时会出现模糊现象。时间性抗锯齿和时间性超级分辨率是现代游戏引擎(包括虚幻引擎)中常用的抗锯齿和…...
捋一遍Leetcode【hot100】的二叉树专题
二叉树专题 除了后面两个,都挺简单 二叉树的中序遍历 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int …...
【java实现+4种变体完整例子】排序算法中【堆排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格
以下是堆排序的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格: 一、堆排序基础实现 原理 基于二叉堆结构(最大堆),通过以下步骤实现排序: 构建最大堆:将…...
量化交易 - RSRS(阻力支撑相对强度)策略研究 - 源码
一、介绍 RSRS(阻力支撑相对强度)是一种基于价格阻力位与支撑位动态变化的市场择时技术指标,由光大证券在2017年提出。其核心原理是通过量化最高价与最低价之间的线性关系,预测市场趋势变化。 原理: 线性回归建模&a…...
从FPGA实现角度介绍DP_Main_link主通道原理
DisplayPort(简称DP)是一个标准化的数字式视频接口标准,具有三大基本架构包含影音传输的主要通道(Main Link)、辅助通道(AUX)、与热插拔(HPD)。 Main Link:用…...
数据库备份-docker配置主从数据库
创建 Docker Compose 文件 创建一个 docker-compose.yml 文件,定义两个 MySQL 容器(一个主库,一个从库) services:mysql:image: mysql:8.0.27container_name: mysqlports:- "3306:3306"environment:TZ: Asia/ShanghaiM…...
YOLO11改进-Backbone-使用MobileMamba替换YOLO backbone 提高检测精度
轻量化模型的技术瓶颈 CNN 的局限性:传统 CNN(如 MobileNet)依赖局部感受野,难以捕捉长距离依赖关系,在高分辨率任务(如语义分割)中需通过增加计算量提升性能,效率低下。 Transforme…...
JavaScript学习教程,从入门到精通,DOM 操作语法知识点及案例代码(20)
DOM 操作语法知识点及案例代码 一、DOM 介绍 1. 什么是 DOM DOM (Document Object Model,文档对象模型) 是 HTML 和 XML 文档的编程接口。它提供了对文档的结构化的表示,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结…...
Vue3 + TypeScript中defineEmits 类型定义解析
TypeScript 中 Vue 3 的 defineEmits 函数的类型定义,用于声明组件可以触发的事件。以下是分步解释: 1. 泛型定义 ts <"closeDialog" | "getApplySampleAndItemX"> 作用:定义允许的事件名称集合,即组…...
Git命令归纳
初始化git git config --global user.name xxx:设置全局用户名,信息记录在~/.gitconfig文件中git config --global user.email xxxxxx.com:设置全局邮箱地址,信息记录在~/.gitconfig文件中git init:先创建一个目录&am…...
Oracle Recovery Tools修复ORA-600 6101/kdxlin:psno out of range故障
数据库异常断电,然后启动异常,我接手该库,尝试recover恢复 SQL> recover database; ORA-10562: Error occurred while applying redo to data block (file# 2, block# 63710) ORA-10564: tablespace SYSAUX ORA-01110: ???????? 2: H:\TEMP\GDLISNET\SYSAUX01.DBF O…...
ISO26262-浅谈用例导出方法和测试方法
目录 1 摘要2 测试方法3 测试用例导出方法4 测试方法与用例导出方法的差异和联系5 结论 1 摘要 ISO26262定义了测试方法和用例导出方法,共同保证产品的开发质量。但在刚开始学习ISO26262的时候,又不是非常清晰地理解它俩的区别和联系。本文主要对它俩的…...
小测验——已经能利用数据集里面的相机外参调整后看到渲染图像
文章目录 .1 外try——牛的显示.2 try——衣服的显示.3 原生R,T但是部分显示.4 在.3的基础上加上可视化界面.5 调参后能看到东西的.6 能看一点东西+可视化(pytorch3d).7 自己的代码可视化——需要调整.1 外try——牛的显示 import numpy as np import matplotlib.pyplot as …...
2024期刊综述论文 Knowledge Graphs and Semantic Web Tools in Cyber Threat Intelligence
发表在期刊Journal of Cybersecurity and Privacy上,专门讲知识图谱技术和语义Web工具在网络威胁情报领域的作用,还把本体和知识图谱放在相同的地位上讨论。 此处可以明确一点:本体和知识图谱都可以用于网络威胁情报的应用,当然也…...
文件上传及验证绕过漏洞
目录 一、文件上传常见点 二、客户端--JS绕过--PASS-01 1、环境安装 2、禁用JS 3、后缀名绕过 4、修改前端代码 三、服务端黑名单绕过 1、特殊可解析后缀--PASS-03 2、大小写绕过--PASS-06 3、点绕过--PASS-08 4、空格绕过--PASS-07 5、::$DATA绕过--PASS-09 6、配…...
stack和queue的使用和模拟实现
1:stack文档 stack文档 stack的使用 2:queue文档 queue文档 queue的使用 1:队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。 2:队列作…...
基于Ubuntu2504部署OpenStack E版
OpenStack 初始化环境安装数据库、memcahe、rabbitmq等服务安装keystone服务安装glance服务安装placement服务安装nova服务安装neutron服务安装horizon服务 官网 OpenStack Epoxy 巩固了作为 VMware 替代方案的地位,增强了安全性,并改进了硬件支持 第 3…...
Jsp技术入门指南【七】JSP动作讲解
Jsp技术入门指南【七】JSP动作讲解 前言一、什么是JSP动作?二、核心JSP动作详解1. jsp:include:动态包含其他页面与<% include %>的区别 2. jsp:forward:请求转发到另一个页面3. jsp:param:为动作传递参数4. jsp:useBean&am…...
电脑 访问 github提示 找不到网页,处理方案
1、找到 本机的 host文件 例如 windows 的 一般在 C:\Windows\System32\drivers\etc\hosts 用管理员身份打开 hosts 文件 如果文件中没有 github的配置,需要自己手动添加上去; 如果有,则需要 检查 github.com 与 github.global.ssl.fastly.…...
性能比拼: Elixir vs Go
本内容是对知名性能评测博主 Anton Putra Elixir vs Go (Golang) Performance (Latency - Throughput - Saturation - Availability) 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准 对比 Elixir 和 Go 简介 许多人长期以来一直要求我对比 Elixir 和 Go。在本视频…...
动手实现文本生成模型:基于 Decoder-only Transformer (PyTorch)
1. 选择框架:PyTorch 我们选择 PyTorch 作为实现框架。PyTorch 提供了灵活的动态图,并且拥有功能强大的 nn.Transformer 模块,方便我们快速构建模型。其社区活跃,资源丰富,是进行深度学习研究和开发的优秀选择。 确保你已经安装了 PyTorch 和其他必要的库: Bash pip i…...
WSL+Ubuntu+miniconda环境配置
安装到指定目录 bash Miniconda3-latest-Linux-x86_64.sh -b -p /usr/local/miniconda3添加环境变量 echo export PATH"/usr/local/miniconda3/bin:$PATH" >> /etc/profile echo export PATH"/usr/local/miniconda3/bin:$PATH" >> ~/.bashrc…...
linux学习 5 正则表达式及通配符
重心应该放在通配符的使用上 正则表达式 正则表达式是用于 文本匹配和替换 的强大工具 介绍两个交互式的网站来学习正则表达式 regexlearn 支持中文 regexone 还有一个在线测试的网址 regex101 基本规则 符号作用示例.匹配任何字符除了换行a.b -> axb/a,b[abc]匹配字符…...
【web服务_负载均衡Nginx】三、Nginx 实践应用与高级配置技巧
一、Nginx 在 Web 服务器场景中的深度应用 1.1 静态网站部署与优化 在 CentOS 7 系统中,使用 Nginx 部署静态网站是最基础也最常见的应用场景。首先,准备网站文件,在/var/www/html目录下创建index.html文件: sudo mkdir -p…...
详解与HTTP服务器相关操作
HTTP 服务器是一种遵循超文本传输协议(HTTP)的服务器,用于在网络上传输和处理网页及其他相关资源。以下是关于它的详细介绍: 工作原理 HTTP 服务器监听指定端口(通常是 80 端口用于 HTTP,443 端口用于 HT…...
LeetCode 2563.统计公平数对的数目:排序 + 二分查找
【LetMeFly】2563.统计公平数对的数目:排序 二分查找 力扣题目链接:https://leetcode.cn/problems/count-the-number-of-fair-pairs/ 给你一个下标从 0 开始、长度为 n 的整数数组 nums ,和两个整数 lower 和 upper ,返回 公平…...
Manus技术架构、实现内幕及分布式智能体项目实战
Manus技术架构、实现内幕及分布式智能体项目实战 模块一: 剖析Manus分布式多智能体全生命周期、九大核心模块及MCP协议,构建低幻觉、高效且具备动态失败处理能力的Manus系统。 模块二: 解析Manus大模型Agent操作电脑的原理与关键API…...
基于springboot的个人财务管理系统的设计与实现
博主介绍:java高级开发,从事互联网行业六年,熟悉各种主流语言,精通java、python、php、爬虫、web开发,已经做了六年的毕业设计程序开发,开发过上千套毕业设计程序,没有什么华丽的语言࿰…...
新能源汽车动力电池热管理方案全解析:开启电车续航与安全的密码
热管理:新能源汽车的隐形守护者 在新能源汽车飞速发展的今天,热管理系统作为保障车辆核心部件稳定运行的关键,正逐渐成为行业关注的焦点。据市场研究机构的数据显示,近年来新能源汽车的销量持续攀升,而与之相伴的是热…...
Ubuntu开启自启动PostgreSQL读取HDD失败处理思路
前置文章: windows通用网线连接ubuntu实现ssh登录、桌面控制、文件共享Ubuntu挂载HDD迁移存储PostgreSQL数据 背景: 启动实体Ubuntu机器后后很大的概率PostgreSQL不会成功启动,查看日志: Ubuntu启动时间: rootPine…...
损失函数总结
目录 回归问题L1损失 平均绝对值误差(MAE)Smooth L1 LossL2损失 均方误差损失MSE 分类问题交叉熵损失KL 散度损失 KLDivLoss负对数似然损失 NLLLoss 排序MarginRankingLoss 回归问题 L1损失 平均绝对值误差(MAE) 指模型预测值f(x…...
LeetCode 热题 100:回溯
46. 全排列 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1: 输入:nums [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2: 输入ÿ…...
Jetson Orin NX 部署YOLOv12笔记
步骤一.创建虚拟环境 conda create -n yolov12 python3.8.20 注意:YOLOv12/YOLOv11/YOLOv10/YOLOv9/YOLOv8/YOLOv7a/YOLOv5 环境通用 步骤二.激活虚拟环境 conda activate yolov12 #激活环境 步骤三.查询Jetpack出厂版本 Jetson系列平台各型号支持的最高Jetp…...
『Linux_网络』 第二章 UDP_Socket编程
学习了网络的概念了,接下来我们开始实践,本次我们会通过UDP来模拟实现UDP客户端和UDP服务器之间的通信,以及在此基础上扩展几个应用。 下面,我们将使用socket,bind,htons等接口实现UDP网络通信。 v1 版本 …...
【leetcode刷题日记】lc.322-零钱兑换
目录 1.题目 2.代码 1.题目 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。 你可以认…...
从GET到POST:HTTP请求的攻防实战与CTF挑战解析
初探HTTP请求:当浏览器遇见服务器 基础协议差异可视化 # 典型GET请求 GET /login.php?username=admin&password=p@ssw0rd HTTP/1.1 Host: example.com User-Agent: Mozilla/5.0# 典型POST请求 POST /login.php HTTP/1.1 Host: example.com Content-Type: application/x…...