Etcd 可观测最佳实践
简介
Etcd 是一个高可用的分布式键值存储系统,它提供了一个可靠的、强一致性的存储服务,用于配置管理和服务发现。它最初由 CoreOS 开发,现在由 Cloud Native Computing Foundation (CNCF) 维护。Etcd 使用 Raft 算法来实现数据的一致性,能保证数据在所有节点间保持同步。
Etcd 作为一个关键的分布式键值存储系统,广泛应用于 Docker、Kubernetes等分布式系统中,用于存储配置信息、服务发现、领导者选举等,它保证了集群数据的强一致性和高可用性。因此对 Etcd 可观测是非常重要的,尤其是在生产环境中,观测 Etcd 的运行指标可以帮助及时发现和解决潜在的问题,确保集群的稳定性和可靠性。
Etcd 自带 metrics 接口,可以通过 curl 命令访问默认的 “/metrics” 端点来查看可用的指标。如果 Etcd 集群配置了 TLS,还需要指定客户端证书和密钥等信息 。
curl http://<etcd-node-ip>:2379/metrics
观测云是一款统一的可观测平台,可实现对多云、云原生、中间件、应用等进行实时可观测。观测云数据的采集是通过 DataKit 来实现的,DataKit 自带的有 Etcd 采集器,不依赖 Prometheus,只需要安装 DataKit,开通 Etcd 采集器,配置 metrics url 、证书、密钥等信息,即可采集到 Etcd 指标到观测云。下面是在 Kubernetes 集群部署 DataKit 并开通 Etcd 采集器的示例。
操作步骤
部署 DataKit
登录观测云控制台,点击「集成」 -「DataKit」 - 「Kubernetes」,下载 datakit.yaml,拷贝第 3 步中的 token。
编辑 datakit.yaml ,把 token 粘贴到 ENV_DATAWAY 环境变量值中“token=”后面,设置环境变量 ENV_CLUSTER_NAME_K8S 的值并增加环境变量 ENV_NAMESPACE,这两个环境变量的值一般和集群名称对应,一个工作空间集群名称要唯一。
- name: ENV_NAMESPACEvalue: xxxx
把 datakit.yaml 上传到可以连接到 Kubernetes 集群的主机上,执行如下命令。
kubectl apply -f datakit.yaml
kubectl get pod -n datakit
开通 Etcd 采集
KubernetesPrometheus 是 DataKit 的一个采集器,它根据自定义配置实现自动发现 Prometheus 服务并进行采集,极大简化了采集 Kubernetes 集群中 Etcd 指标的复杂度。
apiVersion: v1
kind: ConfigMap
metadata:name: datakit-confnamespace: datakit
data:etcd.conf: |- [inputs.kubernetesprometheus] [[inputs.kubernetesprometheus.instances]]role = "pod"namespaces = ["kube-system"]selector = "component=etcd,tier=control-plane" scrape = "true"scheme = "https"port = "2379"path = "/metrics"interval = "60s"[inputs.kubernetesprometheus.instances.custom]measurement = "etcd"job_as_measurement = false[inputs.kubernetesprometheus.instances.custom.tags]node_name = "__kubernetes_node_name"cluster_name_k8s = "k8s-dev"[inputs.kubernetesprometheus.instances.auth]bearer_token_file = "/var/run/secrets/kubernetes.io/serviceaccount/token"[inputs.kubernetesprometheus.instances.auth.tls_config]insecure_skip_verify = falseca_certs = ["/rootfs/etc/kubernetes/pki/etcd/ca.crt"]cert = "/rootfs/etc/kubernetes/pki/etcd/peer.crt"cert_key = "/rootfs/etc/kubernetes/pki/etcd/peer.key"
再把 etcd.conf 挂载到 DataKit 的 /usr/local/datakit/conf.d/kubernetesprometheus/etcd.conf 下面,最后重新部署 DataKit。- mountPath: /usr/local/datakit/conf.d/kubernetesprometheus/etcd.confname: datakit-confsubPath: etcd.conf
指标
登录观测云控制台,点击「指标」 -「指标管理」,输入“etcd”,就能查询采集到的指标。
Etcd 采集器默认会把所有指标都采集到观测云,为了减少时间线,需要使用 pipeline,drop 未被使用的指标。登录观测云控制台,点击「管理」 -「新建Pipeline」,选择“指标”、“etcd”,drop_key(grpc_server_started_total) 即是不采集 grpc_server_started_total 指标。
完整解析规则如下:
drop_key(grpc_server_started_total)
drop_key(etcd_cluster_version)
drop_key(etcd_debugging_auth_revision)
drop_key(etcd_debugging_disk_backend_commit_rebalance_duration_seconds_bucket)
drop_key(etcd_debugging_disk_backend_commit_rebalance_duration_seconds_count)
drop_key(etcd_debugging_disk_backend_commit_rebalance_duration_seconds_sum)
drop_key(etcd_debugging_disk_backend_commit_spill_duration_seconds_bucket)
drop_key(etcd_debugging_disk_backend_commit_spill_duration_seconds_count)
drop_key(etcd_debugging_disk_backend_commit_spill_duration_seconds_sum)
drop_key(etcd_debugging_disk_backend_commit_write_duration_seconds_bucket)
drop_key(etcd_debugging_disk_backend_commit_write_duration_seconds_count)
drop_key(etcd_debugging_disk_backend_commit_write_duration_seconds_sum)
drop_key(etcd_debugging_lease_granted_total)
drop_key(etcd_debugging_lease_renewed_total)
drop_key(etcd_debugging_lease_revoked_total)
drop_key(etcd_debugging_lease_ttl_total_bucket)
drop_key(etcd_debugging_lease_ttl_total_count)
drop_key(etcd_debugging_lease_ttl_total_sum)
drop_key(etcd_debugging_mvcc_compact_revision)
drop_key(etcd_debugging_mvcc_current_revision)
drop_key(etcd_debugging_mvcc_db_compaction_keys_total)
drop_key(etcd_debugging_mvcc_db_compaction_last)
drop_key(etcd_debugging_mvcc_db_compaction_pause_duration_milliseconds_bucket)
drop_key(etcd_debugging_mvcc_db_compaction_pause_duration_milliseconds_count)
drop_key(etcd_debugging_mvcc_db_compaction_pause_duration_milliseconds_sum)
drop_key(etcd_debugging_mvcc_db_compaction_total_duration_milliseconds_bucket)
drop_key(etcd_debugging_mvcc_db_compaction_total_duration_milliseconds_count)
drop_key(etcd_debugging_mvcc_db_compaction_total_duration_milliseconds_sum)
drop_key(etcd_debugging_mvcc_events_total)
drop_key(etcd_debugging_mvcc_index_compaction_pause_duration_milliseconds_bucket)
drop_key(etcd_debugging_mvcc_index_compaction_pause_duration_milliseconds_count)
drop_key(etcd_debugging_mvcc_index_compaction_pause_duration_milliseconds_sum)
drop_key(etcd_debugging_mvcc_pending_events_total)
drop_key(etcd_debugging_mvcc_range_total)
drop_key(etcd_debugging_mvcc_slow_watcher_total)
drop_key(etcd_debugging_mvcc_total_put_size_in_bytes)
drop_key(etcd_debugging_mvcc_watch_stream_total)
drop_key(etcd_debugging_mvcc_watcher_total)
drop_key(etcd_debugging_server_lease_expired_total)
drop_key(etcd_debugging_snap_save_marshalling_duration_seconds_bucket)
drop_key(etcd_debugging_snap_save_marshalling_duration_seconds_count)
drop_key(etcd_debugging_snap_save_marshalling_duration_seconds_sum)
drop_key(etcd_debugging_snap_save_total_duration_seconds_bucket)
drop_key(etcd_debugging_snap_save_total_duration_seconds_count)
drop_key(etcd_debugging_snap_save_total_duration_seconds_sum)
drop_key(etcd_debugging_store_expires_total)
drop_key(etcd_debugging_store_reads_total)
drop_key(etcd_debugging_store_watch_requests_total)
drop_key(etcd_debugging_store_watchers)
drop_key(etcd_debugging_store_writes_total)
drop_key(etcd_disk_backend_defrag_duration_seconds_bucket)
drop_key(etcd_disk_backend_defrag_duration_seconds_count)
drop_key(etcd_disk_backend_defrag_duration_seconds_sum)
drop_key(etcd_disk_backend_snapshot_duration_seconds_bucket)
drop_key(etcd_grpc_proxy_cache_hits_total)
drop_key(etcd_grpc_proxy_cache_keys_total)
drop_key(etcd_grpc_proxy_cache_misses_total)
drop_key(etcd_grpc_proxy_events_coalescing_total)
drop_key(etcd_grpc_proxy_watchers_coalescing_total)
drop_key(etcd_mvcc_db_open_read_transactions)
drop_key(etcd_mvcc_delete_total)
drop_key(etcd_mvcc_hash_duration_seconds_bucket)
drop_key(etcd_mvcc_hash_duration_seconds_count)
drop_key(etcd_mvcc_hash_duration_seconds_sum)
drop_key(etcd_mvcc_hash_rev_duration_seconds_bucket)
drop_key(etcd_mvcc_hash_rev_duration_seconds_count)
drop_key(etcd_mvcc_hash_rev_duration_seconds_sum)
drop_key(etcd_mvcc_put_total)
drop_key(etcd_mvcc_range_total)
drop_key(etcd_mvcc_txn_total)
drop_key(etcd_server_apply_duration_seconds_bucket)
drop_key(etcd_server_apply_duration_seconds_count)
drop_key(etcd_server_apply_duration_seconds_sum)
drop_key(etcd_server_client_requests_total)
drop_key(etcd_server_go_version)drop_key(etcd_server_id)
drop_key(etcd_server_is_leader)
drop_key(etcd_server_is_learner)
drop_key(etcd_server_learner_promote_successes)
drop_key(etcd_server_quota_backend_bytes)
drop_key(etcd_server_slow_apply_total)
drop_key(etcd_server_slow_read_indexes_total)
drop_key(etcd_server_version)
drop_key(etcd_snap_db_fsync_duration_seconds_bucket)
drop_key(etcd_snap_db_fsync_duration_seconds_count)
drop_key(etcd_snap_db_fsync_duration_seconds_sum)
drop_key(etcd_snap_db_save_total_duration_seconds_bucket)
drop_key(etcd_snap_db_save_total_duration_seconds_count)
drop_key(etcd_snap_db_save_total_duration_seconds_sum)
drop_key(etcd_snap_fsync_duration_seconds_bucket)
drop_key(etcd_snap_fsync_duration_seconds_count)
drop_key(etcd_snap_fsync_duration_seconds_sum)
drop_key(go_gc_duration_seconds)
drop_key(go_gc_duration_seconds_count)
drop_key(go_gc_duration_seconds_sum)
drop_key(go_goroutines)
drop_key(go_info)
drop_key(go_memstats_frees_total)
drop_key(go_memstats_gc_cpu_fraction)
drop_key(go_memstats_gc_sys_bytes)
drop_key(go_memstats_heap_idle_bytes)
drop_key(go_memstats_heap_inuse_bytes)
drop_key(go_memstats_heap_objects)
drop_key(go_memstats_heap_released_bytes)
drop_key(go_memstats_heap_sys_bytes)
drop_key(go_memstats_last_gc_time_seconds)
drop_key(go_memstats_lookups_total)
drop_key(go_memstats_mallocs_total)
drop_key(go_memstats_mcache_inuse_bytes)
drop_key(go_memstats_mcache_sys_bytes)
drop_key(go_memstats_mspan_sys_bytes)
drop_key(go_memstats_next_gc_bytes)
drop_key(go_memstats_other_sys_bytes)
drop_key(go_memstats_stack_inuse_bytes)
drop_key(go_memstats_stack_sys_bytes)
drop_key(go_memstats_sys_bytes)
drop_key(go_threads)
drop_key(grpc_server_msg_received_total)
drop_key(grpc_server_msg_sent_total)
drop_key(process_resident_memory_bytes)
drop_key(process_start_time_seconds)
drop_key(process_virtual_memory_bytes)
drop_key(process_virtual_memory_max_bytes)
drop_key(promhttp_metric_handler_requests_in_flight)
drop_key(promhttp_metric_handler_requests_total)
监控视图
登录观测云控制台,点击「场景」 -「新建仪表板」,输入 “etcd”, 选择“Etcd 监控视图”,点击“确定”。
关键指标
Etcd 的监控指标主要包括 Server、Disk 和 Network 三大类。
- Server 指标:描述了 Etcd 服务器的状态,包括是否有 leader、leader 切换次数、已提交和已应用的提案总数、等待提交的提案数以及失败的提案数等。
- Disk 指标:描述了磁盘操作的状态,例如 WAL fsync 调用的延迟和后端提交操作的延迟。
- Network 指标:描述了网络状态,包括发送和接收的字节数、发送和接收失败数以及节点间的 RTT 时间等。
指标 | 描述 | 单位 |
---|---|---|
etcd_server_has_leader | 这个指标表示 Etcd 集群中是否存在 Leader。 | count |
etcd_server_health_success | etcd 服务器健康检查成功的次数 | count |
etcd_server_health_failures | etcd 服务器健康检查失败的次数 | count |
process_resident_memory_bytes | 用于表示 etcd 进程当前占用的常驻内存(resident memory)大小 | Bytes |
etcd_server_proposals_committed_total | 成功提交到 Raft 日志中的提案(proposals)总数 | count |
etcd_server_proposals_applied_total | 成功应用或执行(Apply)的提案(proposals)总数 | count |
etcd_server_proposals_pending | 当前等待处理的提案数量 | count |
etcd_server_proposals_failed_total | 失败的提案总数 | count |
etcd_mvcc_db_total_size_in_bytes | 数据库的总大小 | Bytes |
etcd_disk_wal_fsync_duration_seconds_sum | 当前日志执行 fsync 操作的总耗时 | Seconds |
etcd_disk_backend_commit_duration_seconds_sum | 后台数据库提交操作的总耗时 | Seconds |
etcd_network_client_grpc_received_bytes_total | etcd 服务器从客户端通过 gRPC 协议接收到的总字节数 | Bytes |
etcd_network_client_grpc_sent_bytes_total | etcd 服务器通过 gRPC 协议发送给客户端的总字节数 | Bytes |
etcd_server_leader_changes_seen_total | leader 的切换次数 | count |
process_open_fds | 操作系统进程当前打开的文件描述符数量 | count |
process_max_fds | 操作系统允许一个进程打开的最大文件描述符数量 | count |
提案(Proposal)
Etcd 基于 Raft 实现一致性算法。在 Raft 中,任何试图更改系统状态的动作都以提案(Proposal)的形式被提出。
etcd_server_proposals_pending 表示正在等待处理的 Proposal 数量。
etcd_server_proposals_committed_total
和 etcd_server_proposals_applied_total
:这两个指标分别表示成功提交到 Raft 日志中的提案数量和成功应用或执行(Apply)的提案数量。它们可以帮助监控集群处理请求的能力。如果提交和应用的提案数之间存在较大差异,可能表明集群正在处理大量请求,或者存在性能瓶颈。
etcd_server_proposals_failed_total
:这个指标记录了处理失败的提案数量。提案失败可能由于多种原因,包括网络问题、集群不稳定或资源限制。监控这个指标有助于及时发现和解决影响 Etcd 集群稳定性的问题。
同步时间
etcd_disk_wal_fsync_duration_seconds_bucket
和 etcd_disk_backend_commit_duration_seconds_bucket
:这两个指标反映了 Etcd 存储数据的效率,高延迟可能表明磁盘性能问题或集群过载。
WAL 日志同步时间 etcd_disk_wal_fsync_duration_seconds_bucket
,表示 WAL 日志同步到磁盘时,WAL 调用 fsync 的延迟,正常应该低于10ms,当 99 百分位的 fsync 延迟超过某个阈值(比如 100 毫秒)时触发告警。
库同步时间 etcd_disk_backend_commit_duration_seconds_bucket
,当 etcd 将其最新的增量快照提交到磁盘时,会调用 backend_commit
, 正常应该低于120ms。
Leader 是否存在
etcd_server_has_leader
:这个指标表示 Etcd 集群中是否存在 Leader。Leader 对于 Etcd 集群至关重要,因为它负责处理所有的写请求。0 表示不是,1表示是,如果这个值为 0,意味着集群中没有 Leader,这将导致写操作无法进行,整个集群不可用。因此,监控这个指标可以帮助及时发现集群是否处于正常工作状态。
Leader 切换频次
etcd_server_leader_changes_seen_total
指标,记录了 leader 的切换次数。当 Etcd 通过 Raft 协议选举出 leader 后,leader 应该是固定不变的。频繁的 Leader 切换可能是由于网络问题或集群不稳定造成的,这会影响集群的性能和稳定性。监控这个指标有助于发现潜在的网络问题或集群健康问题。生产环境如果在一个小时内发生超过三次的 leader 切换,需要触发告警。
监控器(告警)
通过合理配置监控器,可以及时处理 etcd 故障,观测云也提供了相应的模板供客户参考使用。
Leader 监控器
值为 0 触发紧急告警。
Leader 频繁切换监控
如需更多监控器可以按照实际生产需求进行配置。
总结
总之,对 Etcd 进行可观测,是确保分布式系统稳定运行的关键步骤,观测云是一款实用的可观测产品,建议把生产环境中 Etcd 接入观测云,使用观测云的监控器对重要指标进行监控告警。
相关文章:

Etcd 可观测最佳实践
简介 Etcd 是一个高可用的分布式键值存储系统,它提供了一个可靠的、强一致性的存储服务,用于配置管理和服务发现。它最初由 CoreOS 开发,现在由 Cloud Native Computing Foundation (CNCF) 维护。Etcd 使用 Raft 算法来实现数据的一致性&…...

钉钉录播抓取视频
爬取钉钉视频 免责声明 此脚本仅供学习参考,切勿违法使用下载他人资源进行售卖,本人不但任何责任! 仓库地址: GItee 源码仓库 执行顺序 poxyM3u8开启代理getM3u8url用于获取m3u8文件userAgent随机请求头downVideo|downVideoThreadTqdm单线程下载和…...

centos下面的jdk17的安装配置
文章目录 1.基本指令回顾2.jdk17的安装到这个centos上面2.1首先切换到这个root下面去2.2查看系统jdk版本2.3首先到官网找到进行下载2.4安装包的上传2.5jdk17的安装包的解压过程2.6配置环境变量2.7是否设置成功,查看版本 1.基本指令回顾 ls:list也就是列出来这个目录…...

【操作系统】——调度
🌹😊🌹博客主页:【Hello_shuoCSDN博客】 ✨操作系统详见 【操作系统专项】 ✨C语言知识详见:【C语言专项】 目录 处理机调度的概念、层次 进程调度的时机、切换与过程、方式 调度器和闲逛进程 处理机调度的概念、层…...
基于Aspose依赖添加自定义文本水印——Word、Pdf、Cell
基于Aspose依赖添加自定义文本水印——Word、Pdf、Cell 所需依赖Word水印Pdf水印——( 注意 pdf 存在找不到字体的问题)Excel水印 所需依赖 <dependency><groupId>com.aspose</groupId><artifactId>aspose-pdf</artifactId&g…...

【C++】—掌握STL string类:字符串操作的得力助手
#1024程序员节|征文# 文章目录 繁星点点映夜空,晨曦微露照前程1.string的基本概念2.标准库中的string类2.1 string类2.2 auto和范围for2.3 string类常用的接口2.4 string类对象的容量操作2.5 string类对象的访问及遍历操作2.6 string类对象的修改操作2…...
【Java笔记】第十四章:异常
一、概念【理解即可】 1. 异常:程序运行过程中,出现的非正常情况。 2. 异常的处理:当异常出现时,执行一段预先准备好的代码。 3. 异常的处理的必要性:减少用户的损失、同时减小给用户带来麻烦,也可以对用…...

Python游戏开发超详细(基础理论知识篇)
一、引导: Python游戏开发是一个非常有趣且富有挑战性的领域。通过Python,你可以利用其强大的库和框架来创建各种类型的游戏,从简单的2D游戏到复杂的3D游戏。以下是第一课的基础理论知识,帮助你入门Python游戏开发。 二、理论知识…...

Python开发日记 -- 实现bin文件的签名
目录 1.数据的不同表现形式签名值不一样? 2.Binascii模块简介 3.问题定位 4.问题总结 1.数据的不同表现形式签名值不一样? Happy Muscle试运行了一段时间,组内同事再一次提出了新的需求:需要对bin文件签名。 PS:服…...

微软运用欺骗性策略大规模打击网络钓鱼活动
微软正在利用欺骗性策略来打击网络钓鱼行为者,方法是通过访问 Azure 生成外形逼真的蜜罐租户,引诱网络犯罪分子进入以收集有关他们的情报。 利用收集到的数据,微软可以绘制恶意基础设施地图,深入了解复杂的网络钓鱼操作ÿ…...
小程序无法获取头像昵称以及手机号码的深度剖析与解决方案
在当今数字化时代,小程序以其便捷、高效的特点,成为了人们生活和工作中不可或缺的一部分。然而,有时候开发者会遇到小程序无法获取头像昵称以及手机号码的问题,这给用户体验和业务流程带来了极大的困扰。本文将深入探讨这个问题的原因,并提供相应的解决方案。 一、引言 小…...

从0到1,搭建vue3项目
一 Vite创建Vue3项目 1.1.创建Vue3项目 1.1.1.运行创建项目命令 # 使用 npm npm create vitelatest 1.1.2、填写项目名称 1.1.3、选择前端框架 1.1.4、选择语法类型 1.1.5、按提示运行代码 1.1.6浏览器问 localhost:5173 预览 1.2项目结构 1.2.1vite.config.ts 1.2.2 pac…...
Mybatis mapper文件 resultType和resultMap的区别
在 MyBatis 中,resultType 和 resultMap 都用于定义从数据库查询结果到 Java 对象的映射规则,但它们之间存在着一些关键的区别。以下是对这两者的详细说明和区别: 1. resultType 定义 resultType 是 MyBatis 查询语句中的一个属性…...

文件下载漏洞
文件安全 文件下载 常见敏感信息路径 Windows C:\boot.ini //查看系统版本 C:\Windows\System32\inetsrv\MetaBase.xml //IIS配置文件 C:\Windows\repair\sam //存储系统初次安装的密码 C:\Program Files\mysql\my.ini //Mysql配置 C:\Program Files\mysql\data\mysql\user.…...
【Flutter】状态管理:Provider状态管理
在 Flutter 开发中,状态管理是一个至关重要的部分。随着应用的规模和复杂性增加,简单的局部状态管理(如 setState() 和 InheritedWidget)可能变得难以维护和扩展。Provider 是一种推荐的、广泛使用的 Flutter 状态管理工具&#x…...
来个Oracle一键检查
启停、切换、升级、网络改造等场景下,需要对数据库有些基本检查操作,确认当前是否运行正常,主打一个简单和一键搞定。 #!/bin/bash## 实例个数 告警日志 实例状态 会话 活动会话 锁 集群状态 服务状态 磁盘空间 侦听日志 ## linux vmstat 2 …...

C语言中的分支与循环(中 1)
关系操作符 C语言用于比较的表达式,称为"关系表达式",里面使用的运算符称为关系运算符,关系运算符主要有以下6类。 > 大于运算符< 小于运算符>大于等于运算符< 小于等于运算符 相等运算符! 不相等运算符 下面是例子:…...

Git_GitLab
Git_GitLab 安装 服务器准备 安装包准备 编写安装脚本 初始化 GitLab 服务 启动 GitLab 服务 浏览器访问 GitLab GitLab 创建远程库 IDEA 集成 GitLab 安装 GitLab 插件 设置 GitLab 插件 安装 服务器准备 准备一个系统为 CentOS7 以上版本的服务器,使…...
如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)
文章目录 一、什么是 Spring Boot Starter?二、为什么要自定义 Starter?三、自定义 Starter 的基本步骤1. 创建 Maven 项目2. 配置 pom.xml3. 创建自动配置类4. 创建业务逻辑类5. 创建 spring.factories 四、使用自定义 Starter五、总结推荐阅读文章 在使…...

CSS伪元素以及伪类和CSS特性
伪元素:可以理解为假标签。 有2个伪元素 (1)::before (2)::after ::before <!DOCTYPE html> <html> <head><title></title><style type"text/css">body::before{con…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...

客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践
01技术背景与业务挑战 某短视频点播企业深耕国内用户市场,但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大,传统架构已较难满足当前企业发展的需求,企业面临着三重挑战: ① 业务:国内用户访问海外服…...

Java后端检查空条件查询
通过抛出运行异常:throw new RuntimeException("请输入查询条件!");BranchWarehouseServiceImpl.java // 查询试剂交易(入库/出库)记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...