Etcd 框架
基本了解
客户端、长连接与租约的关系
客户端对象
etcd的客户端对象是用户与etcd服务进行交互的主要接口,主要功能就是存储、通知和事务等功能访问
- 键值存储:客户端通过put 和 get操作存储数据;数据存储在etcd的层级化键值数据库中
- 监听器(Watcher):客户端可以监听指定键的变化事件,如果键值发生改变,etcd会通过回调通知客户端;借助监听器可以实现动态管理配置和服务发现
- 事务:提供txn接口,允许客户端进行原子性操作
工作原理
- 客户端通过gRpc与etcd集群进行交互
- 连接时,客户端需要提供集群的地址和认证信息
- 连接建立后,客户端可以调用功能不同API完成具体功能
长连接
长连接是指客户端与etcd服务之间的持续连接,主要用于保持会话状态以及实现实时性功能
- 保持租约长期有效:租约需要客户端通过长连接向etcd定期发送心跳包,否则租约会到期
- 监听:监听功能依赖于长连接,当监听的键发生变化的时候,etcd通过长连接向客户端推送事件
- 减少开销:长连接避免了频繁的连接断开,节省了建立连接的时间和资源
工作原理
- 客户端与
etcd
集群节点通过 gRPC 建立连接 - 建立连接后,客户端发送
KeepAlive
请求以保持连接 - 如果
etcd
未在一定时间内接收到心跳,会认为连接断开
租约
etcd提供的一种机制,主要用于一段时间内绑定键值数据,并确保键值在租约有效期内有效
- 动态生存时间:键值可以绑定到租约,租约到期后,绑定的键值会自动删除
- 分布式锁:租约结合键值和keeplive实现分布式锁,确保资源的唯一占用
- Session管理:通过租约,可以熟实现分布式会话管理
工作原理
- 客户端调用
LeaseGrant
接口创建租约,并设置租期 - 将键值与租约绑定。例如,使用
Put
命令时指定租约ID - 客户端通过长连接定期向
etcd
发送心跳,续租以保持租约有效 - 如果未续约,租约到期后,绑定的键值会自动被删除
应用:服务实例向 etcd
注册自己(通过租约绑定信息),当实例下线或不可用时,租约自动到期并移除信息
基本使用
安装
框架安装
GitHub - etcd-cpp-apiv3/etcd-cpp-apiv3: The etcd-cpp-apiv3 is a C++ library for etcd's v3 client APIs, i.e., ETCDCTL_API=3.
验证动态库和相应的文件是否存在
使用
上传和获取逻辑
// get.cc#include <etcd/Client.hpp>
#include <etcd/KeepAlive.hpp>
#include <etcd/Response.hpp>
#include <etcd/Watcher.hpp>
#include <etcd/Value.hpp>
#include <thread>// 回调函数:用于处理监控到的键值变化事件
void callback(const etcd::Response &resp) {// 如果收到的事件通知无效,打印错误信息并返回if (!resp.is_ok()) {std::cout << "收到一个错误的事件通知: " << resp.error_message() << std::endl;return;}// 遍历事件列表,逐个处理每个事件for (auto const& ev : resp.events()) {// 如果事件类型是 PUT(键值被创建或修改)if (ev.event_type() == etcd::Event::EventType::PUT) {std::cout << "服务信息发生了改变:\n";std::cout << "当前的值:" << ev.kv().key() << " - " << ev.kv().as_string() << std::endl;std::cout << "原来的值:" << ev.prev_kv().key() << " - " << ev.prev_kv().as_string() << std::endl;}// 如果事件类型是 DELETE(键值被删除)else if (ev.event_type() == etcd::Event::EventType::DELETE_) {std::cout << "服务信息下线被删除:\n";std::cout << "当前的值:" << ev.kv().key() << " - " << ev.kv().as_string() << std::endl;std::cout << "原来的值:" << ev.prev_kv().key() << " - " << ev.prev_kv().as_string() << std::endl;}}
}int main(int argc, char *argv[])
{// 定义etcd服务的地址,默认使用本地运行的etcd服务std::string etcd_host = "http://127.0.0.1:2379";// 1. 实例化etcd客户端对象,用于和etcd服务交互etcd::Client client(etcd_host);// 2. 获取 "/service" 路径下的所有键值对auto resp = client.ls("/service").get(); // 同步调用获取响应if (!resp.is_ok()) {// 如果获取失败,打印错误信息并退出程序std::cout << "获取键值对数据失败: " << resp.error_message() << std::endl;return -1;}// 3. 遍历返回的键值对,打印每个键值对的信息int sz = resp.keys().size(); // 获取键值对的数量for (int i = 0; i < sz; ++i) {std::cout << resp.value(i).as_string() << " 可以提供 " << resp.key(i) << " 服务\n";}// 4. 实例化一个Watcher对象,用于监听 "/service" 路径下的键值变化// 参数说明:// - `client`: 使用前面实例化的客户端对象// - "/service": 要监听的路径// - `callback`: 监听到键值变化后调用的回调函数// - `true`: 是否递归监听路径下的子路径(true 表示递归)auto watcher = etcd::Watcher(client, "/service", callback, true);// 5. 启动Watcher,阻塞当前线程,持续监听事件,直到程序被中断watcher.Wait();// 6. 结束程序return 0;
}
//put.cc#include <etcd/Client.hpp>
#include <etcd/KeepAlive.hpp>
#include <etcd/Response.hpp>
#include <thread>int main(int argc, char *argv[])
{std::string etcd_host = "http://127.0.0.1:2379";//实例化客户端对象etcd::Client client(etcd_host);//获取租约保活对象--伴随着创建一个指定有效时长的租约auto keep_alive = client.leasekeepalive(3).get();//获取租约IDauto lease_id = keep_alive->Lease();//向etcd新增数据auto resp1 = client.put("/service/user", "127.0.0.1:8080", lease_id).get();if (resp1.is_ok() == false) {std::cout << "新增数据失败:" << resp1.error_message() << std::endl;return -1;}auto resp2 = client.put("/service/friend", "127.0.0.1:9090").get();if (resp2.is_ok() == false) {std::cout << "新增数据失败:" << resp2.error_message() << std::endl;return -1;}std::this_thread::sleep_for(std::chrono::seconds(10));return 0;
}
接口学习
基于上传和获取学习接口
etcd::Client
类
etcd::Client
是核心客户端类,用于与 etcd 服务进行交互,提供基本的键值存取和操作功能
构造函数
etcd_url
:etcd 服务地址(例如http://127.0.0.1:2379
)- 创建一个与 etcd 服务通信的客户端对象
etcd::Client client(const std::string &etcd_url);
ls()
方法
- 列出路径下所有的键值
key
:路径键,表示需要获取其子键的根路径(例如/service
)- 返回一个
std::future<etcd::Response>
,可以通过.get()
同步获取结果
std::future<etcd::Response> ls(const std::string &key);
auto resp = client.ls("/service").get();
if (resp.is_ok()) {// 获取成功,遍历键值for (const auto &key : resp.keys()) {std::cout << key << ": " << resp.value(key).as_string() << std::endl;}
} else {std::cerr << "获取失败: " << resp.error_message() << std::endl;
}
etcd::Watcher
类
用于监听指定路径下的键值变化事件,并触发回调函数处理这些事件
构造函数
client
:etcd::Client
对象,用于连接 etcd 服务。key
:要监听的路径键(例如/service
)。callback
:回调函数,当监听到键值变化时触发,参数是etcd::Response
对象。recursive
:是否递归监听子路径下的键值变化,默认为false
。- 功能:创建一个监听器对象,监听制定路径下的键值变化
etcd::Watcher watcher(etcd::Client &client, const std::string &key,std::function<void(const etcd::Response &)> callback,bool recursive = false);
Wait()
方法
- 阻塞当前线程,持续监听键值变化事件,直到被中断
auto watcher = etcd::Watcher(client, "/service", callback, true);
watcher.Wait(); // 阻塞线程等待事件
etcd::Response
类
etcd 请求或事件的响应对象,包含操作结果及相关数据
is_ok()
方法
- 判断请求是否成功:成功则返回true,失败则返回false
bool is_ok() const;
error_message()
方法
- 获取请求或者事件失败的错误信息
std::string error_message() const;
keys()
方法
- 获取路径下所有键的列表
std::vector<std::string> keys() const;
value(key)
方法
- 返回指向键的值对象
etcd::Value value(const std::string &key) const;
events()
方法
- 获取监听器捕获到的事件列表
std::vector<etcd::Event> events() const;
etcd::Value
类
etcd::Value
表示 etcd 中的键值对,包含键、值及其元数据
key()
方法
- 获取键的名称
std::string key() const;
as_string()
方法
- 获取键对应的值(字符串形式)
std::string as_string() const;etcd::Value val = resp.value(key);
std::cout << "Key: " << val.key() << ", Value: " << val.as_string() << std::endl;
二次封装
基本思想
服务注册客户端类(Registry)
主要目标
- 向etcd注册服务信息(通过键值对方式)并确保其活跃状态
- 借用租约机制保证注册信息的有效性,如果租约过期,服务注册信息回自动清除
实现逻辑
- 创建一个etcd客户端,用于与etcd进行通信
- 创建租约(Lease),为服务注册信息绑定一个动态生存空间
- 定期发送心跳保活(KeepLive),续约租约,确保服务信息不会被自动删除
- 提供一个registry方法,用于注册服务信息(键值对)
服务发现客户端类
主要目标
- 从etcd中获取指定路径下的当前服务信息
- 通过监听机制实时监控服务信息的变化(例如服务新增、服务下线)
- 使用回调函数处理服务变更事件
实现逻辑
- 创建etcd客户端用于与etcd通信
- 使用ls方法获取当前路径下所有的键值对,处理当前已有数据
- 创建Watcher对象,监听指定路径下的数据变更事件
- 在事件回调中,根据事件的类型调用对应的回调函数
具体实现
细节补充:Watcher中使用Bind进行回调的逻辑总结
- Watcher 检测到事件:
etcd::Watcher
检测到指定路径的键值发生了变化(例如新增或删除) - Watcher 调用回调函数:
Watcher
将变化事件封装为etcd::Response
对象,调用绑定后的函数对象,并将etcd::Response
作为参数传递 - 绑定的函数对象调用
callback
:其中,this
是Discovery
类的实例,resp
是etcd::Watcher
提供的事件响应 - callback 函数执行:
callback
使用resp
提供的事件信息,执行具体的业务逻辑(例如调用_put_cb
或_del_cb
)
this->callback(resp);
etcd二次封装实现
#pragma once
#include <etcd/Client.hpp>
#include <etcd/KeepAlive.hpp>
#include <etcd/Response.hpp>
#include <etcd/Watcher.hpp>
#include <etcd/Value.hpp>
#include <functional>
#include "logger.hpp"namespace mag {// 服务注册客户端类class Registry {public:using ptr = std::shared_ptr<Registry>;// 构造函数:初始化etcd客户端和租约(Lease)机制Registry(const std::string &host):_client(std::make_shared<etcd::Client>(host)), // 创建etcd客户端_keep_alive(_client->leasekeepalive(3).get()), // 创建一个3秒TTL的租约并保持续约_lease_id(_keep_alive->Lease()){} // 获取租约ID// 析构函数:取消租约续约,释放资源~Registry() { _keep_alive->Cancel(); }// 注册服务信息:将键值对存入etcd并绑定租约bool registry(const std::string &key, const std::string &val) {auto resp = _client->put(key, val, _lease_id).get(); // 绑定租约,写入键值对if (resp.is_ok() == false) {LOG_ERROR("注册数据失败:{}", resp.error_message()); // 打印错误日志return false;}return true; // 返回注册结果}private:std::shared_ptr<etcd::Client> _client; // etcd客户端对象std::shared_ptr<etcd::KeepAlive> _keep_alive; // 租约续约对象uint64_t _lease_id; // 租约ID};// 服务发现客户端类class Discovery {public:using ptr = std::shared_ptr<Discovery>;using NotifyCallback = std::function<void(std::string, std::string)>;// 构造函数:初始化etcd客户端,执行服务发现和事件监听Discovery(const std::string &host, const std::string &basedir,const NotifyCallback &put_cb,const NotifyCallback &del_cb):_client(std::make_shared<etcd::Client>(host)), // 创建etcd客户端_put_cb(put_cb), _del_cb(del_cb) // 设置回调函数{// 服务发现:获取当前路径下的已有服务数据auto resp = _client->ls(basedir).get(); // 列出路径下的所有键值if (resp.is_ok() == false) {LOG_ERROR("获取服务信息数据失败:{}", resp.error_message()); // 打印错误日志}int sz = resp.keys().size();for (int i = 0; i < sz; ++i) {if (_put_cb) _put_cb(resp.key(i), resp.value(i).as_string()); // 调用服务新增回调}// 事件监控:监听路径数据变更并调用回调处理_watcher = std::make_shared<etcd::Watcher>(*_client.get(), basedir,std::bind(&Discovery::callback, this, std::placeholders::_1), true);}// 析构函数:取消事件监听,释放资源~Discovery() {_watcher->Cancel();}private:// 事件回调函数:处理服务新增和删除事件void callback(const etcd::Response &resp) {if (resp.is_ok() == false) {LOG_ERROR("收到一个错误的事件通知: {}", resp.error_message()); // 打印错误日志return;}for (auto const& ev : resp.events()) {// 新增服务事件if (ev.event_type() == etcd::Event::EventType::PUT) {if (_put_cb) _put_cb(ev.kv().key(), ev.kv().as_string()); // 调用服务新增回调LOG_DEBUG("新增服务:{}-{}", ev.kv().key(), ev.kv().as_string()); // 打印调试信息}// 服务下线事件else if (ev.event_type() == etcd::Event::EventType::DELETE_) {if (_del_cb) _del_cb(ev.prev_kv().key(), ev.prev_kv().as_string()); // 调用服务删除回调LOG_DEBUG("下线服务:{}-{}", ev.prev_kv().key(), ev.prev_kv().as_string()); // 打印调试信息}}}private:NotifyCallback _put_cb; // 服务新增事件回调NotifyCallback _del_cb; // 服务删除事件回调std::shared_ptr<etcd::Client> _client; // etcd客户端对象std::shared_ptr<etcd::Watcher> _watcher; // 事件监听器};
}
测试注册和发现逻辑
#include "etcd.hpp"
#include <iostream>
#include <chrono>
#include <thread>// 服务新增回调
void onServiceAdded(const std::string &key, const std::string &value) {std::cout << "发现新增服务:" << key << " -> " << value << std::endl;
}// 服务下线回调
void onServiceRemoved(const std::string &key, const std::string &value) {std::cout << "服务下线:" << key << " -> " << value << std::endl;
}int main() {std::string etcd_host = "http://127.0.0.1:2379";std::string watch_dir = "/service";// 创建Discovery对象mag::Discovery::ptr discovery = std::make_shared<mag::Discovery>(etcd_host, watch_dir, onServiceAdded, onServiceRemoved);// 保持监听状态std::cout << "开始监听服务变更,按 Ctrl+C 退出..." << std::endl;std::this_thread::sleep_for(std::chrono::seconds(600));return 0;
}
#include "etcd.hpp"
#include <iostream>
#include <chrono>
#include <thread>int main() {std::string etcd_host = "http://127.0.0.1:2379";std::string key = "/service/example";std::string value = "127.0.0.1:8080";// 创建Registry对象mag::Registry::ptr registry = std::make_shared<mag::Registry>(etcd_host);// 注册服务if (registry->registry(key, value)) {std::cout << "服务注册成功:" << key << " -> " << value << std::endl;} else {std::cerr << "服务注册失败!" << std::endl;return -1;}// 保持注册信息的活跃状态std::cout << "服务正在运行,按 Ctrl+C 退出..." << std::endl;std::this_thread::sleep_for(std::chrono::seconds(600));return 0;
}
问题
编译问题慢
问题描述
多次对该文件进行编译,编译总是卡在80%左右停止,服务器环境是2核2G的云服务器
分析
经htop进行排查,发现部分服务占用了大量内存,从而导致编译写入和读取文件速度变慢
解决思路
停止占用内存较高的MySQL服务
sudo systemctl stop mysql
清理缓存和无用数据
sync; echo 3 | sudo tee /proc/sys/vm/drop_caches
删除临时文件进一步释放空间
sudo apt autoremove -y
sudo apt clean
使用两个线程对程序进行编译
make -j2
相关文章:
Etcd 框架
基本了解 客户端、长连接与租约的关系 客户端对象 etcd的客户端对象是用户与etcd服务进行交互的主要接口,主要功能就是存储、通知和事务等功能访问 键值存储:客户端通过put 和 get操作存储数据;数据存储在etcd的层级化键值数据库中监听器&a…...
在 CentOS 7 上安装 MinIO 的步骤
在 CentOS 7 上安装 MinIO 的步骤 在 CentOS 7 上安装 MinIO 的步骤1. 更新系统2. 安装依赖3. 下载 MinIO4. 赋予执行权限5. 移动 MinIO 到系统路径6. 创建 MinIO 用户7. 创建数据目录8. 创建 MinIO 服务文件9. 启动 MinIO 服务10. 设置开机自启11. 访问 MinIO12. 配置防火墙&a…...
【Linux】进程地址空间
目录 一、引入问题: 二、进程地址空间: 地址和数据总线: 三、页表: 权限: 缺页中断: 四、回到问题: 五、总结: 重新理解进程: 一、引入问题: 在C中&a…...
快速图像识别:落叶植物叶片分类
1.背景意义 研究背景与意义 随着全球生态环境的变化,植物的多样性及其在生态系统中的重要性日益受到关注。植物叶片的分类不仅是植物学研究的基础,也是生态监测、农业管理和生物多样性保护的重要环节。传统的植物分类方法依赖于人工观察和专家知识&…...
第 22 章 - Go语言 测试与基准测试
在Go语言中,测试是一个非常重要的部分,它帮助开发者确保代码的正确性、性能以及可维护性。Go语言提供了一套标准的测试工具,这些工具可以帮助开发者编写单元测试、表达式测试(通常也是指单元测试中的断言)、基准测试等…...
K8S + Jenkins 做CICD
前言 这里会做整体CICD的思路和流程的介绍,会给出核心的Jenkins pipeline脚本,最后会演示一下 实验/实操 结果 由于整体内容较多,所以不打算在这里做每一步的详细演示 - 本文仅作自己的实操记录和日后回顾用 要看保姆式教学的可以划走了&…...
http/https
1、http与https HTTPHTTPS信息明文传输加入ssl加密传输协议,可以使得报文加密传输默认端口80默认端口443连接简单TCP三次握手通信TCP三次握手后还要SSL/TLS握手过程,才可以加密报文传输无状态不安全需要到CA申请证书,身份认证,自…...
腾讯云 AI 代码助手:产品研发过程的思考和方法论
一、文章摘要 本文将详细阐述 腾讯云 AI 代码助手的历史发展形态与产品整体架构,并从技术、研发方法论的角度分别阐述了产品的研发过程。 全文阅读约 5~8 分钟。 二、产品布局 AI 代码助手产品经历了三个时代的发展 第一代诸如 Eclipse、Jetbrains、V…...
淘宝商品评论爬虫:Java实现指南
在当今的互联网时代,数据的价值日益凸显,尤其是用户生成的内容,如商品评论,对于理解消费者行为和市场趋势具有重要意义。淘宝作为中国最大的电商平台之一,拥有海量的商品评论数据。本文将介绍如何使用Java编写一个简单…...
银河麒麟v10 x86架构二进制方式kubeadm+docker+cri-docker搭建k8s集群(证书有效期100年) —— 筑梦之路
环境说明 master:192.168.100.100 node: 192.168.100.101 kubeadm 1.31.2 (自编译二进制文件,证书有效期100年) 银河麒麟v10 sp2 x86架构 内核版本:5.4.x 编译安装 cgroup v2启用 docker版本:27.x …...
【Linux】详解shell代码实现(上)
🪐🪐🪐欢迎来到程序员餐厅💫💫💫 主厨:邪王真眼 主厨的主页:Chef‘s blog 所属专栏:青果大战linux 总有光环在陨落,总有新星在闪烁 学校开始搞蓝桥的校选…...
Ruby 模块(Module)
Ruby 模块(Module) 概述 Ruby 是一种动态、开放源代码的编程语言,以其简洁明了的语法和强大的功能而闻名。在 Ruby 中,模块(Module)是一个重要的概念,它用于封装一组相关的方法和常量。模块提…...
成都睿明智科技有限公司怎么样可靠不?
在这个日新月异的数字时代,电商行业如同一股不可阻挡的洪流,席卷着每一个消费者的生活。而抖音,作为短视频与电商完美融合的典范,更是为无数商家开辟了一片全新的蓝海。在这片充满机遇与挑战的海洋中,成都睿明智科技有…...
内网安全隧道搭建-ngrok-frp-nps-sapp
1.ngrok 建立内网主机与公网跳板机的连接: 内网主机为客户机: 下载客户端执行 2.frp (1)以下为内网穿透端口转发 frp服务端配置: bindPort 为frp运行端口 服务端运行 ./frps -c frps.ini frp客户端配置…...
k8s 对外服务之 Ingress
LB ingress //Ingress 简介 service的作用体现在两个方面,对集群内部,它不断跟踪pod的变化,更新endpoint中对应pod的对象,提供了ip不断变化的pod的服务发现机制;对集群外部,他类似负载均衡器,…...
前端速通(JavaScript)
1 初识JavaScript 1 JavaScript是什么 JavaScript 是一种高层的、轻量级的、解释型的编程语言,最初由 Netscape 公司于 1995 年开发。它的特点包括: 动态性:JavaScript是动态类型语言,允许开发者灵活地操作数据。跨平台…...
Unity图形学之着色器之间传递参数
1.初始化 struct: UNITY_INITIALIZE_OUTPUT(type,name) Type: struct 名字 Name :变量的名字 struct Input{float2 uv_MainTex;float3 myColor;};half _Glossiness;half _Metallic;fixed4 _Color;void MyVertx(inout appdata_base v,out I…...
JavaScript中的this指向问题
JavaScript中的this指向问题 1.1 为什么需要this? 为什么需要this? 在常见的编程语言中,几乎都有this这个关键字(Objective-C中使用的是self),但是在JavaScript中的this和常见的面向对象语言中的this不太一样 常见面向对象的编程语言中,比…...
Qt之QWidget相关
Qt概述 Qt 是一个跨平台的 C 开发框架。 跨平台支持:可以用于开发 Windows、macOS、Linux、Android、iOS 等多种操作系统下的应用程序。这意味着开发者使用 Qt 编写的代码,在经过适当的编译和配置后,能够在不同平台上运行,减少了…...
Ease Monitor 会把基础层,中间件层的监控数据和服务的监控数据打通,从总体的视角提供监控分析
1. 产品定位 Ease Monitor 有如下的产品定位: 关注于整体应用的SLA。 主要从为用户服务的 API 来监控整个系统。 关联指标聚合。 把有关联的系统及其指示聚合展示。主要是三层系统数据:基础层、平台中间件层和应用层。 快速故障定位。 对于现有的系统…...
苹果MacOS 调用自编译opencv的Dylib显示一个图片程序的步骤
前言 为了测试自编译的opencv库是否能在苹果MacOS系统下使用,需要写一个简单的测试程序。这个测试程序写起来不难,麻烦的是一些配置。网上的办法很多,里面因为版本的问题有一些坑。特此写了一个建立步骤,供大家参考。 1、新建一个…...
网页中调用系统的EXE文件,如打开QQ
遇到一个实际的问题,需要在网页中打开本地的某个工业软件。 通过点击exe文件就可以调用到程序。 比如双击qq的exe就可以启动qq的程序。 那么问题就变成了如何加载exe程序呢? 可以通过Java的 Process process Runtime.getRuntime().exec(command);通过…...
在 Ubuntu 系统上安装 npm 环境以及 nvm(Node Version Manager)
在 Ubuntu 系统上安装 npm 环境以及 nvm(Node Version Manager) 步骤 1: 更新系统包步骤 2: 安装 nvm步骤 3: 安装 Node.js 和 npm步骤 4: 设置默认 Node.js 版本(可选)总结 在 Ubuntu 系统上安装 npm 环境以及 nvm(No…...
Linux环境开启MongoDB的安全认证
文章目录 1. MongoDB安全认证简介1.1 访问控制1.2 角色1.3 权限 2. MongoDB中的常见角色3. MongoDB Shell3.1 下载MongoDB Shell3.2 通过MongoDB Shell连接MongoDB 4. 创建管理员用户5. 为具体的数据库创建用户6. 开启权限认证7. 重启MongoDB服务8. 连接MongoDB9. MongoDB数据库…...
实现了两种不同的图像处理和物体检测方法
这段代码实现了两种不同的图像处理和物体检测方法:一种是基于Canny边缘检测与轮廓分析的方法,另一种是使用TensorFlow加载预训练SSD(Single Shot Multibox Detector)模型进行物体检测。 1. Canny边缘检测与轮廓分析: …...
经典工具 | 使用SIFT预测错义突变的有害性
SIFT 用计算机替代人预测复杂事件的影响,是我们这个时代最令人兴奋的科学进展之一。SIFT就是这样一个应用于基因组学研究的经典工具。 SIFT可预测多种生物体的基因组变异,主要是错义突变的影响与效应,最大的特点是物种丰富,是一个…...
如何给 Apache 新站点目录配置 SELinux ?
在 web 服务器管理领域,确保服务器环境的安全性至关重要。SELinux (Security-Enhanced Linux) 是保护 Linux 服务器最有效的工具之一,它是一种强制访问控制 (MAC mandatory access control) 安全机制。当使用最流行的 web 服务器 Apache 提供 web 内容时…...
RTSP播放器EasyPlayer.js播放器分辨率高的视频在设置container的宽高较小时,会出现锯齿状的画面效果
流媒体播放器的核心技术及发展趋势展现了其在未来数字生活中的无限潜力。随着技术的不断进步和市场的持续发展,流媒体播放器将在内容创新、用户体验优化以及跨平台互通等方面取得新的突破。对于从业者而言,把握这些趋势并积极应对挑战将是实现成功的关键…...
云讷科技Kerloud无人飞车专利发布
云讷科技Kerloud无人飞车获得了“一种室内外两用的四旋翼无人飞车”的实用新型专利证书,作为科教社区第一款四旋翼飞车,这项技术结合了无人机和无人车的优势,提供了一种能够在多种环境下使用的多功能飞行器。 这项设计的优势如下ÿ…...
快速识别模型:simple_ocr,部署教程
快速识别图片中的英文、标点符号、数学符号、Emoji, 模型会输出图片中文字行的坐标位置、最低得分、识别结果。当前服务用到的模型:检测模型、数字识别、英文符号识别。 一、部署流程 1.更新基础环境 apt update2.安装miniconda wget https://repo.anaconda.com/…...
Qt交叉编译x86和arm心得
最近一直在Linux上开发qt程序,主要工作是在x86的Ubuntu上开发编译调试程序,确定没有问题后交叉编译到arm的linux系统上运行 1.环境 Qt的交叉编译环境厂家已经提供了,嵌入式的同事帮我安装调试的,具体就是装了厂家给的gcc编译套件…...
用CAXA CAD电子图板导入图框、标题栏并导出pdf的方法
1.导入图框: 点击调入图框->出现读入图框文件 一个一个点击,选择合适的图框 然后点击导入 2.导入标题栏: 调入标题栏->出现读入标题栏文件 一个一个点击,选择合适的标题栏,然后点击导入 3.导出pdf&#x…...
在 Ubuntu/Debian 上安装 Go
使用官方二进制文件安装(推荐) Go 提供了官方的二进制安装包,适用于大多数 Linux 发行版,包括 Ubuntu 和 Debian。步骤如下: 更新包索引: bash sudo apt update 安装依赖(如果尚未安装&#…...
设计模式之策略模式-工作实战总结与实现
文章目录 应用场景存在问题解决方案继续延伸 应用场景 假设有这样的业务场景,大数据系统把文件推送过来,根据不同类型采取不同的解析方式。多数的小伙伴就会写出以下的代码: public class Question {public static void main(String[] args…...
自动语音识别(ASR)与文本转语音(TTS)技术的应用与发展
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
实验十三 生态安全评价
1 背景及目的 生态安全是生态系统完整性和健康性的整体反映,完整健康的生态系统具有调节气候净化污染、涵养水源、保持水土、防风固沙、减轻灾害、保护生物多样性等功能。维护生态安全对于人类生产、生活、健康及可持续发展至关重要。随着城市化进程的不断推进&…...
【MySQL实战45讲笔记】基础篇——redo log 和 binlog
系列文章 基础篇——MySQL 的基础架构 目录 系列文章1. 重要的日志模块:redo log 和 binlog1.1 redo log1.2 binlog1.3 执行器和 InnoDB 引擎内部如何执行更新语句 1. 重要的日志模块:redo log 和 binlog 前面系统的了解了一个查询语句的执行流程&…...
Java 基于SpringBoot+vue框架的老年医疗保健网站
大家好,我是Java徐师兄,今天为大家带来的是Java Java 基于SpringBootvue框架的老年医疗保健网站。该系统采用 Java 语言开发,SpringBoot 框架,MySql 作为数据库,系统功能完善 ,实用性强 ,可供大…...
Java集合分页
一、前言 在Java开发中,若单次展示的数据量太大,会造成程序响应缓慢,就需要用到分页功能,每一页展示一定量的数据,分多次展示 ... 那么在List集合中,如何实现分页功能呢? 本文将以3种方式&…...
python语言基础-5 进阶语法-5.5 上下文管理协议(with语句)
声明:本内容非盈利性质,也不支持任何组织或个人将其用作盈利用途。本内容来源于参考书或网站,会尽量附上原文链接,并鼓励大家看原文。侵删。 5.5 上下文管理协议(with语句)(参考链接࿱…...
周志华深度森林deep forest(deep-forest)最新可安装教程,仅需在pycharm中完成,超简单安装教程
1、打开pycharm 没有pycharm的,在站内搜索安装教程即可。 2、点击“文件”“新建项目” 3、创建项目,Python版本中选择Python39。如果没有该版本,选择下面的Python 3.9下载并安装。 4、打开软件包,搜索“deep-forest”软件包&am…...
技术美术百人计划 | 《2.1 色彩空间介绍》笔记
总览 一、色彩发送器 色彩认知: 光源是出生点,光源发射出光线,光线通过直射反射折射等路径最终进入人眼。 但人眼接收到光线后,人眼的细胞产生了一系列化学反应。 由此把产生的信号传入大脑,最终大脑对颜色产生了认…...
设计模式:6、装饰模式(包装器)
目录 0、定义 1、装饰模式包含的四种角色 2、装饰模式的UML类图 3、示例代码 0、定义 动态地给对象添加一些额外的职责。就功能来说装饰模式相比生成子类更为灵活。 1、装饰模式包含的四种角色 抽象组件(Component):抽象组件是一个抽象…...
vue-office:word(.docx)、pdf、excel(.xlsx,.xls)格式文件预览
vue-office:word(.docx)、excel(.xlsx,.xls)格式文件预览 组件安装 // docx文档预览组件 npm install vue-office/docx vue-demi0.14.6// excel文档预览组件 npm install vue-office/excel vue-demi0.14.…...
简单工厂模式
简单工厂模式详解 定义 简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,用于创建对象的实例。通过一个工厂类来决定实例化哪一个具体类,降低客户端与具体类之间的耦合。 对于长switch或者长if、else,且…...
得物彩虹桥架构演进之路-负载均衡篇
文 / 新一 一、前言 一年一更的彩虹桥系列又来了,在前面两期我们分享了在稳定性和性能2个层面的一些演进&优化思路。近期我们针对彩虹桥 Proxy 负载均衡层面的架构做了一次升级,目前新架构已经部署完成,生产环境正在逐步升级中…...
【大数据学习 | Spark-Core】spark-shell开发
spark的代码分为两种 本地代码在driver端直接解析执行没有后续 集群代码,会在driver端进行解析,然后让多个机器进行集群形式的执行计算 spark-shell --master spark://nn1:7077 --executor-cores 2 --executor-memory 2G sc.textFile("/home/ha…...
macos 使用 nvm 管理 node 并自定义安装目录
系统环境:MacOS Version 参考文章: Github 地址:https://github.com/nvm-sh/nvm 安装的方式是很简单的,直接执行下面的命令即可: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bas…...
MongoDB分片集群搭建
什么是分片 分片是一种跨多台机器分布数据的方法。MongoDB 使用分片来支持超大数据集和高吞吐量操作的部署。什么情况下使用分片 存储容量受单机限制,即磁盘资源遭遇瓶颈。读写能力受单机限制,可能是CPU、内存或者网卡等资源遭遇瓶颈,导致读…...
MySQL数据库基础
1.数据库的操作 1.1 显示当前数据库 show databses; 1.2 创建数据库 create database [if not exist] db_name; 创建名为db_test1的数据库 create database db_test1; 说明:当我们创建数据库没有指定字符集和校验规则时,系统使用默认字符集;utf8,校验规则是 utf8_general_c…...