kunhua.sh

这里那里

LGTMGo · Gin · Next.js · SQLite/Postgres · Redis · SSE · live · code

自动审查 GitHub PR 的助手,已部署上线,可注册为 GitHub App 。除 diff 外还会读取 CI 状态与仓库自身的约定文档,已实现仓库级RAG。

  • 上下文构建:只把 diff 交给模型会得到脱离项目背景的评论,为此在审查前先拉取 PR 元数据、CI 状态与仓库自身的约定文档,一并作为上下文
  • 三阶段流水线:单次调用产出的长文本难以定位与复用,为此拆成变更摘要、风险清单、修改建议三个阶段,每阶段可指定不同模型、可单独重试,输出为结构化数据并锚定到具体文件行
  • 流式返回:完整审查耗时较长,前端空等体验差,为此自建 SSE 协议,摘要逐段推送,风险与建议在各自阶段完成时整体更新
  • GitHub App 集成:以 OAuth 登录,webhook 在新 PR 或 push 时自动触发审查,结果作为行内建议回写到 PR
  • 缓存与幂等:同一 PR 重复触发会造成无谓的模型调用,为此以 SQLite/Postgres 持久化配 Redis 缓存,并对 webhook 做幂等处理
  • 国际化:界面语言与模型输出语言需一致,为此自建 locale 层同时驱动两者;PR 评论固定英文,保证仓库维护者只读一种语言
  • 部署:前端部署在 Vercel,Go 后端容器化跑在 Fly.io,持久层可在 SQLite 与 Postgres 间切换
BetterScrobblerC++17 · Objective-C++ · Go · CGo · macOS MediaRemote · code

运行于 macOS 的 Last.fm scrobbler,可记录任何来源的播放。

  • 系统级采集:macOS 没有可靠的系统级 scrobbler,Apple Music 不内置、旧插件方案已废弃,为此直接读取系统的 now-playing 状态,使 Spotify、Apple Music、YouTube 与浏览器中的播放都能记录,再通过可配置的解析规则跳过非音乐内容
  • 私有框架调用:now-playing 状态只能从 Apple 未公开的 MediaRemote 框架取得。C++ 版在 Objective-C++ 中自行声明其私有接口,CMake 以 -F/System/Library/PrivateFrameworks 链接;Go 版则通过 CGo 桥接,需在 C 边界两侧做类型编组
  • 计分判定:并非每次播放都应计入,为此将引擎拆成 stream、track、scrobble 三个 manager 加一个 timer,由 timer 依 Last.fm 的规则判定一次 scrobble 何时成立
  • 兜底来源:MediaRemote 覆盖不到的播放源以 AppleScript 与浏览器音频检测补齐
  • 请求签名:Last.fm 要求对请求签名,为此手写实现——参数排序后拼接 secret 取 md5
  • 凭据存储:认证信息存入 macOS Keychain
  • 终端界面:以 Bubble Tea 实现终端 UI,带 LRC 同步歌词滚动,并支持后台守护进程模式
RPCinGoGo · TCP · etcd · Protobuf · code

基于 TCP 的 demo 级 RPC 框架,支持服务注册发现、负载均衡、连接复用等核心能力。

  • 协议与编解码设计:设计自定义二进制协议(固定长度 Header + 可变 Body),支持 JSON / Protobuf 编解码切换,降低序列化开销
  • 多路复用与连接池:高并发下频繁建连引发延迟抖动;单 TCP 连接上通过 requestID 实现并发请求多路复用,支持服务端乱序返回时的正确响应路由;维护连接池复用空闲连接,消除每次调用的 TCP 握手开销
  • 性能定位:32 并发压测下吞吐从 25K QPS 提升到 74K,p99 从 6.7ms 降到 2.0ms。瓶颈在热路径日志造成的磁盘 I/O,单次压测写出 190 万行;同时把序列化从 JSON 换成 Protobuf。另修复了多 goroutine 并发写同一连接导致的帧交错,改由单独的写协程串行化出站帧
  • 容错与限流:下游故障时持续重试会耗尽资源并触发级联故障;实现基于滑动窗口的熔断机制,当错误率超过阈值时拒绝请求;实现令牌桶与滑动窗口两种限流算法
  • 服务发现与负载均衡:微服务动态扩缩容时客户端需实时感知节点变更并合理分配流量;客户端基于 etcd Watch 维护服务列表并实现多种负载均衡策略
  • 拦截器链与可观测性:设计客户端与服务端双侧拦截器链,内置 Recovery、Logging、Prometheus Metrics、Retry、OpenTelemetry Tracing 等中间件
GorderGo · gRPC · RabbitMQ · MySQL · MongoDB · Redis · code

基于 Go 的 demo 级订单系统,将逻辑拆分为四个服务,支持从下单到履约的完整流程。

  • 服务拆分与通信设计:订单流程横跨下单、库存、支付、处理订单多个业务域,为此拆分为四个服务,按实时性选择 gRPC 同步或 RabbitMQ 异步通信
  • 库存并发与秒杀:订单统一通过 MySQL 事务内的库存预留表和 CAS 防止超卖;秒杀入口额外使用 Redis Lua 原子脚本进行校验、一人一单与预扣,入口削峰后异步落真实库存,减少数据库热点竞争
  • 支付超时取消:用户下单后若长期未支付,轮询检测成本高且实时性差,为此基于 RabbitMQ TTL + 死信队列实现订单超时自动取消,订单服务消费该事件后撤销订单状态并回补库存
  • 订单状态控制:状态流转错误会引发资金损失或库存泄漏,为此设计订单状态流转规则,在服务内部实现状态校验,并通过事件机制触发退款与库存回补。订单存储使用 MongoDB,通过 MongoDB Session + 事务原子执行,防止状态跳跃
  • 链路追踪落地:多服务部署后日志分散、难以还原完整调用路径,为此接入 OpenTelemetry + Jaeger 实现跨服务链路追踪;通过自定义 MQ header 解决异步调用 trace 丢失问题
  • 服务治理与监控:使用 Consul 实现服务注册与健康检查,Prometheus + Grafana 采集接口耗时与调用次数,定位慢请求问题
EGOS-2000C · RISC-V 汇编 · QEMU

在 RISC-V 教学操作系统中实现内核子系统:信号、调度、虚拟内存、用户级线程。

  • 信号投递:信号需在进程下次被调度时生效而非立即打断内核,为此以位掩码记录 pending 信号,并把投递挂在 kernel_entry 恢复上下文之前;投递时将 mepc 与 32 个寄存器存入进程的 saved_signal_ctx,改写 mepc 指向处理函数,把信号编号放入 a0、trampoline 地址放入 ra
  • 用户态返回路径:处理函数返回后需回到被中断的位置,而用户态无法直接恢复内核保存的上下文,为此在用户程序中放置一段 RISC-V 汇编 trampoline,向系统调用参数页写入 SYS_SIGRETURNecall,由内核完成恢复
  • 默认处理与不可捕获信号SIGKILL 与默认处理不走上述路径,直接将 mepc 改写为程序的 exit 入口,使其无法被用户代码拦截
  • MLFQ 调度:CPU 密集型进程会饿死交互型进程,为此按累计 CPU 时间三级降级(一个时间片内留高优先级、两个时间片内进中优先级、之后进低优先级),系统进程固定在高优先级队列,另设独立 sleep 队列
  • 虚拟内存:实现 Sv32 两级页表,walk() 按需分配 L2 页表页并返回 PTE 指针供直接修改权限位,切换后以 sfence.vma 刷新,另建立恒等映射区域
  • 内存保护:以 PMP 将 0x802000000x80400000 设为 NAPOT 区域并开放用户态 r/w/x,直接写 pmpaddr0pmpcfg0 两个 CSR
  • 用户级线程:实现 TCB、FIFO 就绪队列与 thread_create / thread_yield / thread_exit;线程不能在自己的栈上释放自己,为此将回收延迟到下一次 create 或 yield
FUSE File SystemC · FUSE · Python · code

用户态实现的类 Unix 文件系统,读写完整。

  • 盘上格式设计:自定义 4096 字节块布局,超级块以 magic 校验;inode 占满一整个块,uid/gid/mode/ctime/mtime/size 之后接 1019 个直接块指针;目录项固定 32 字节,含 1 位有效标志、31 位 inode 号与 28 字节文件名
  • 块分配:以位图管理空闲块并常驻内存,由 bit_set / bit_clear / bit_test 三个操作维护,创建、写入、截断时同步更新
  • 路径解析:分两步完成,parse 将路径切成分量数组,translate 逐级查目录把它转换为 inode 号,供其余操作复用
  • 文件系统操作:实现 16 个 FUSE 回调,覆盖 getattrreaddircreatemkdirunlinkrmdirrenamechmodutimetruncatereadwritestatfs,读写均完整
  • 截断与重命名truncate 需按新长度回收或补足数据块并同步位图;rename 需处理跨目录移动时两侧目录项的增删
  • 工具链:配套三个 Python 工具,gen-disk.py 依描述文件生成磁盘镜像、read-img.py 转储镜像内容、diskfmt.py 负责格式化