欢迎访问

专注系统底层与高性能服务开发,持续记录 Go / Rust / C++ / 云原生的一线实践。

从源码细节到线上治理,尽量少空话,多代码。

Go gRPC Streaming 的流控与内存治理

典型症状 单连接吞吐很高,但进程 RSS 持续上涨。 p99 抖动明显,GC 时间占比异常。 下游稍慢就触发级联超时。 流控设计要点 应用层窗口:限制每个 stream 的未确认消息数。 连接层隔离:大流量 stream 与普通 RPC 分离连接。 消费层背压:处理队列满时暂停读或降级。 服务端模式 type StreamState struct { inflight int64 limit int64 } func (s *StreamState) AllowRecv() bool { return atomic.LoadInt64(&s.inflight) < s.limit } 参数调优建议 MaxRecvMsgSize 不要无限放大,优先拆包。 对大对象优先走分块传输。 结合业务 ACK 做“应用级信用”控制。 观测面 每 stream inflight 数。 解码耗时与业务处理耗时拆分。 内存分配热点(pprof alloc_space)。 小结 Streaming 的本质是长期会话。想要稳,必须让发送速率服从消费能力,而不是盲目追求“尽快塞满管道”。

2026年5月4日 · 1 分钟 · BvBeJ

Go Kafka Consumer:重平衡期间的可用性设计

背景 扩缩容、实例重启、网络波动都会触发 rebalance。处理不好就会出现消费停顿、重复处理和延迟暴涨。 实践要点 处理逻辑幂等化 offset 提交时机明确 重平衡回调里做好 flush for msg := range claim.Messages() { if err := handle(msg); err == nil { session.MarkMessage(msg, "") } } 总结 消费者稳定性的上限,取决于你对 rebalance 的设计,而不是对“正常流量”的设计。 消息系统里,异常路径才是主路径。

2026年5月4日 · 1 分钟 · BvBeJ

Rust async trait 性能取舍:泛型与动态分发

背景 async_trait 大幅提升了工程可读性,但在高频路径里也可能引入额外分配和动态分发开销。 选择建议 热路径优先泛型静态分发 插件式扩展再考虑 trait object 先 benchmark 再下结论 pub trait Storage { fn get<'a>(&'a self, key: &'a str) -> Pin<Box<dyn Future<Output = Option<String>> + Send + 'a>>; } 总结 抽象不是免费的,但可维护性也有价值,关键是按热点分层。 架构取舍从来不是二选一,而是按场景分配复杂度。

2026年5月4日 · 1 分钟 · BvBeJ

Docker 供应链安全落地:从 SBOM 到 SLSA 的最小可行路径

目标先定清楚 供应链安全的核心不是“发现漏洞”,而是回答三个问题: 产物是谁构建的? 构建过程是否可复现、可验证? 已知风险是否能阻断上线? 最小可行链路 构建时生成 SBOM(CycloneDX/SPDX)。 对镜像和 SBOM 进行签名(cosign)。 在部署前做签名与策略校验(admission policy)。 流水线分层 Build:固定基础镜像 digest,避免 tag 漂移。 Attest:记录构建来源、commit、runner 信息。 Verify:发布阶段验证签名、来源、漏洞阈值。 策略示例 rules: - require_signature: true - require_sbom: true - max_critical_vulns: 0 - trusted_builders: - ci-prod-runner 常见失败点 只签镜像不签 SBOM,证据链断裂。 允许“人工例外”但不留审计记录。 漏洞阈值过严导致全线绕过,最终失去治理。 小结 把“生成证据、验证证据、阻断风险”串成默认流水线,供应链安全才会从一次性项目变成长期能力。

2026年5月3日 · 1 分钟 · BvBeJ

Kubernetes PDB:驱逐安全与发布稳定

背景 很多集群在节点升级、手动驱逐时出现服务抖动,根因常常是没配或错配 PDB。 基本配置 apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: api-pdb spec: minAvailable: 2 selector: matchLabels: app: api 总结 PDB 不是“可选增强”,而是生产集群进行维护操作的安全护栏。 维护窗口稳定与否,很多时候取决于这几行 YAML。

2026年5月3日 · 1 分钟 · BvBeJ

Vue3 路由预取:提升体感速度的低成本手段

背景 很多后台系统首屏不慢,但页面切换时常有明显等待。通常是路由组件和数据都在点击后才加载。 实用做法 鼠标悬停时预取路由 chunk 关键列表页预取首屏数据 低网速场景要可降级关闭 const UserPage = () => import('@/pages/UserPage.vue') function prefetchUserPage() { void UserPage() } 总结 预取策略要适度,目标是减少等待感,不是盲目预加载所有页面。 用户感知速度,很多时候来自“提前一步”。

2026年5月3日 · 1 分钟 · BvBeJ

C++ 自定义分配器评测:别只看平均耗时

背景 很多 allocator 优化在 micro benchmark 里很好看,上线却收益一般。原因是评测维度不完整。 建议指标 p50/p95/p99 分配耗时 长时间运行碎片率 多线程争用下吞吐波动 auto begin = std::chrono::steady_clock::now(); void* p = alloc.allocate(256); alloc.deallocate(p, 256); auto end = std::chrono::steady_clock::now(); 总结 评测方法比结果数值更重要,先保证实验可信,再比较方案优劣。 性能数据要能解释真实场景,才有决策价值。

2026年5月2日 · 1 分钟 · BvBeJ

Docker 供应链安全:SBOM 与镜像签名落地

背景 镜像漏洞扫描只是起点。上线前还需要回答:这个镜像是谁构建的,包含了什么依赖,是否被篡改。 落地步骤 构建后生成 SBOM 对镜像做签名 部署侧验证签名 syft packages ghcr.io/org/app:latest -o spdx-json > sbom.json cosign sign ghcr.io/org/app:latest cosign verify ghcr.io/org/app:latest 总结 供应链安全要形成闭环:生成、签名、验证,缺一不可。 可观测运行时,也要可追溯构建时。

2026年5月2日 · 1 分钟 · BvBeJ

Go 实现 Raft 时的日志压缩与快照传输细节

为什么会“越跑越慢” Raft 日志长期不压缩会拖慢重放与追赶;但压缩过于激进又会让慢 follower 频繁走全量快照,网络和磁盘双杀。 压缩策略建议 用“日志条目数 + 磁盘占用”双阈值触发快照。 快照频率按写入速率自适应,而不是固定分钟数。 仅在 commit index 安全推进后截断日志。 安装快照时的工程点 分块传输并带 offset 校验。 最后一块再原子切换状态机数据目录。 快照应用期间限制客户端写入峰值。 Go 侧接口设计 type SnapshotStore interface { Create(meta SnapshotMeta) (io.WriteCloser, error) Open(id string) (io.ReadCloser, SnapshotMeta, error) List(limit int) ([]SnapshotMeta, error) } 常见故障 截断日志早于快照持久化完成,导致节点重启后状态缺口。 快照元数据未纳入 WAL,断电恢复后索引错位。 对慢 follower 缺少限流,拖累 leader。 小结 Raft 的可用性不只来自选主,更来自“日志、快照、复制窗口”三者的节奏匹配。压缩策略设计得当,集群才能长期平稳运行。

2026年5月2日 · 1 分钟 · BvBeJ

Go 服务发现容错:注册中心抖动时怎么保服务

背景 微服务调用里,服务发现经常被当成理所当然的基础设施。但注册中心一旦抖动,调用链就会被放大影响。 实用策略 本地缓存上次可用实例列表 失败时指数退避刷新 查询失败时优先用“最近成功快照” type Resolver interface { Resolve(ctx context.Context, service string) ([]string, error) } type SnapshotCache struct { mu sync.RWMutex data map[string][]string } 总结 服务发现的核心目标是“可用优先”,而不是“每次都拿最新”。 基础组件会失败,容错设计要把失败当常态。

2026年5月1日 · 1 分钟 · BvBeJ