🏠 HomeLab:中年男人之友
未读中年男人的三大爱好:充电头、NAS、软路由。这三大爱好不仅为我们的生活带来了便利,也成为了我们生活的一部分(🤡)。 作为一个软件开发者,我一直梦想着拥有自己的服务器,而 NAS 和软路由则是我通往这个梦想的桥梁。 自从购买了我的第一台 NAS 以来,便打开了一扇新世界的大门。NAS,即网络附加存储(Network Attached Storage),它不仅提供了一个安全的数据存储解决方案,还让我能够实现数据的备份和共享。随着时间的推移,我陆续购买了其他硬件产品,如软路由器、服务器等,逐步搭建起了属于我的 HomeLab。 今天,我想和大家分享一下我搭建 HomeLab 的过程,希望能够帮助到那些同样有志于搭建 HomeLab 的朋友。在接下来的博客文章中,我将详细介绍如何选购合适的 NAS 设备、软路由器以及服务器,并分享我在搭建过程中遇到的挑战和解决方案。 HomeLab 并非遥不可及,只要我们用心去探索和实践,就能开启属于自己的个人云端实验室之旅。让我们一起学习、交流和成长,共同打造一个属于我们的数字王国。 前提说明虽然关于 HomeLab 的文章已经很多了,但我还是想记录下自 ...
背景随着业务不断扩展,系统服务数量和访问压力持续增长,当前整体架构已逐步暴露出性能瓶颈与资源竞争等问题,影响了核心业务的稳定性和扩展性。系统采用微服务架构,目前共计 17 个微服务,分布在多个业务域中,运行一段时间后主要暴露出以下典型问题: 部分核心服务资源占用高,影响其他服务的稳定运行; 统计类服务存在大量复杂查询,导致数据库压力集中,查询响应缓慢; 存在分布式事务、大事务与表锁并发问题,在高峰期容易造成请求阻塞或死锁; 缺乏读写分离、异步化、缓存等优化手段,导致部分非关键路径也占用大量系统资源; 系统在监控、限流、容灾等方面存在不足,缺乏针对高并发场景的应对策略。 为全面提升系统性能与稳定性,我们计划从架构优化、数据库治理、慢 SQL 缓解、中间件调优、Spring Boot 优化、连接池/线程池、异步请求等多个方面,逐步推进整改工作,以提高系统稳定性与高并发要求。 项目基础情况技术架构: Spring Cloud Alibaba 微服务架构基础框架: RuoYi 微服务框架核心业务: 用工需求发布、派工管理、支付结算、数据统计 技术架构技术栈 后端: Spri ...
🧱 后端开发与架构
未读验证码是用来干什么的验证码的核心作用就一个:提高自动化滥用的成本。 让机器不能以极低成本去暴力枚举。说白了就是让非法的请求尽早被拦截,不要让它打到数据库。 这个定义反过来也成立:如果一个验证码实现,不能在前置阶段拦截非法请求,而是让请求先查一次数据库再校验验证码,那它就没起到验证码的作用。 不幸的是,我们的验证码实现就是这样。 先查数据库,再校验验证码验证码校验逻辑在网关的一个 Filter 中实现。简化的流程是这样的: 123收到登录请求 → 判断用户名是不是手机号 → 是:跳过用户查询,直接用手机号校验验证码 否:先通过用户名查询用户信息(DB 查询!) → 再校验验证码 关键代码(脱敏后): 1234567891011121314151617if (!Validator.isMobile(username)) { // 通过帐号查询手机号(登陆名不一定是手机号) CompletableFuture<Response<LoginUser<?>>> completableFuture = Comple ...
🧱 后端开发与架构
未读从零开始:怎么实现一套应用层加解密在讲实际项目之前,先把问题简化:假设你有一个前后端分离的 Web 应用,已经部署了 HTTPS,但现在要求在应用层再做一层加密。你会怎么设计? 为什么是混合加密先想一个问题:能不能全用对称加密(比如 AES)? 可以。前端和后端约定一个固定的 AES 密钥,请求和响应都用它加解密。但问题是——密钥写在前端代码里,浏览器 Sources 面板一搜就有。密钥泄露后,所有人都能解密所有流量。而且这个密钥没法换——一换,所有前端代码都要重新构建部署。 那全用非对称加密(比如 RSA、SM2)呢? 也可以。前端用公钥加密数据,后端用私钥解密。公钥泄露无所谓,没有私钥解不开。但问题是——非对称加密很慢。RSA-2048 加密 1KB 数据的时间能做几百次 AES 加密,而且非对称加密对数据长度有限制(RSA-2048 最多加密 245 字节)。你要加密一个 JSON 请求体,可能几 KB 甚至几十 KB,根本塞不进非对称加密的明文长度上限。 所以业界标准做法是混合加密——用非对称加密保护对称密钥,用对称密钥加密业务数据: sequenceDiagram ...
bootstrap.yml 为什么不在了我在第五篇文章里写了 @Value 到 @ConfigurationProperties 的迁移。那是配置管理的”内容”层面——配置怎么写、怎么校验、怎么分类。这篇文章说的是配置管理的”机制”层面——配置文件本身是怎么被加载的,以及从一个机制迁移到另一个机制时要面对的坑。 先说背景:Spring Cloud 2020+(对应 Spring Boot 2.4+)废弃了 bootstrap.yml。 很多人可能都没注意到这件事。因为如果你的项目是那之前创建的,你的 bootstrap.yml 还在正常工作——Spring Cloud 还保留着向后兼容的能力。但如果你从 Spring Boot 2.3 跳到 3.x,或者像我一样在做架构迁移,就会发现 bootstrap.yml 被官方标记为”不推荐使用”。 为什么要废弃?官方的理由有三条: 额外的上下文。 bootstrap.yml 和 application.yml 是两个独立的 ApplicationContext。bootstrap.yml 先加载,形成一个”引导上下文”(Bootstrap ...
🔥 效能提升
未读前言这篇我想聊一下最近折腾博客发布流程的过程。 不是那种“我写了一个脚本,所以效率提升了”的记录,而是从一个很实际的问题开始:我发现自己写文章的时间还好,发布文章反而越来越烦。 我的博客主站是 Hexo,另外还有一个 dev-site。文章写完之后,并不是点一下发布就结束了。我要补 front matter、生成列表页封面、处理正文头图、同步到 dev-site、转换图片、检查路径、跑构建。每一步都不难,但每一步都容易漏。 一开始我想的是:那就写脚本吧。后来发现,脚本只能解决一部分问题。再后来我开始把 AI 加进来,让它不只是“帮我写正文”,而是参与整个发布流程。最后这套东西慢慢固化成几个 skill,再用一个总控 skill 串起来。 这篇文章就按这个脉络写:我遇到了什么痛点,中间尝试过哪些方案,为什么最后会变成多个 skill 协作,以及这套流程最后带来了什么收益。 痛点:发布文章比写文章还容易出错先说我原来的发布方式。 一篇文章写完后,我通常会按这个顺序处理: 手动补 front matter:title、abbrlink、description、keywords、t ...
🖥️ 基础设施与运维
未读前言因为现在的机场都不太稳定,而且还有 IP 污染这个坑,最近我在用 Claude Code 和 Codex 的时候总觉得有封号风险。折腾来折腾去,我索性在 GCP 买了一台虚拟机,准备自己搭个节点玩玩儿。 这篇记录就是我在 macOS 上配置 GCP 实例 SSH 登录时走的一遍完整流程,目标很简单:不依赖临时密钥,直接用本地固定私钥登录 Compute Engine。 为了方便后面复用,我把关键命令和排查点都整理到一篇里,照着走基本可以一次打通。 环境信息 项目 值 GCP Project ID <your-gcp-project-id> Zone us-west1-b Instance Name <your-instance-name> External IP <your-instance-external-ip> 本地公钥 ~/.ssh/dev/gcp.pub 本地私钥 ~/.ssh/dev/gcp Google 账号 <your-google-account-email> OS Lo ...
缘起:一根涨价的内存条前段时间 DDR 内存又开始涨价。不是那种温吞吞的 5%、10%,是肉眼可见的”今天不买,明天再贵 15%”的涨法。我盯着家里那台常年挂在客厅角落的 x86 服务器看了一会儿:48G 内存、二手 Intel U、跑着几个不痛不痒的小服务,功耗一天十几度电。 算了下账: 这台服务器里的内存、硬盘、平台,按现在的行情出掉正好能贴一台 Mac Studio M2 Ultra 的钱; 一台 Mac Studio 的待机功耗不到原服务器的三分之一; 更关键的是,M2 Ultra 能跑 32B / 70B 的大模型,我那台 x86 不行。 于是冲动下单了。拆机、清灰、寄出、到款、拿新机,全流程一周搞定。 拆完之后盘点了一下现状,家里现在一共有 3 台 Mac: 机器 用途 大致算力 Mac Studio M2 Ultra(新到) 主力推理 24 核 GPU,70B 级别量化模型能流畅跑 Mac mini M4 Pro 常驻开发 + 备用推理 7B–32B 小模型毫无压力 Mac mini M2 跑各种乱七八糟的小服务 3B–7B 够用 ...
🧱 后端开发与架构
未读一个奇怪的现象上一篇讲到版本兼容性验证。等我把 Spring Boot 3.4.7 和 Spring Cloud 的版本问题解决之后,开始仔细看原来 2.1.0 微服务架构中的 Feign 接口关系,发现了一个让我困惑的现象。 同一套架构里,Feign 接口有两种完全不同的实现方式。一部分 Feign 接口由服务提供方维护,通过独立 jar 包对外发布——比如 sctelcp-user-api-starter,里面封装了 UserApiService 这个 Feign 接口以及相关的 DTO、枚举、常量。业务方引入这个依赖就能直接注入使用。这是第一种方式,很标准的”契约优先”做法。 另一部分 Feign 接口由业务方自己写——比如 sctelcp-infrastructure-service 自己维护了一个 UserApiService,用于调用用户服务的接口。同一个 UserApiService,在不同的服务里有不同的实现,甚至类名都一样。 于是我问了自己一个问题:为什么不全部用第一种方式? 答案是”以前出现过业务方乱调用 Feign 接口的情况,出了问题第一时间找架构组,所以就同 ...
关掉检查就行了吗前八篇文章写了研发底座的架构全景、工程规范、Response 设计、缓存重构、配置管理、代码质量、MyBatis 组件化、网关性能调优。这些内容基本上是在同一个架构底座上逐步优化出来的。但现在我们要聊一个更底层的变动——从单体架构再切回微服务架构。 先交代一下背景。这不是一个从零开始的设计。研发底座最早是微服务架构(v2.1.0),后来因为某些项目场景需要,把它改造成了一个单体架构(代号 cirrus-1.0.0)——主要就是把原来的 Feign 远程调用改成了 JVM 内部调用,用一个聚合组件收敛依赖。然后到了 9 月,业务上又有微服务的需求了,于是我们从单体架构出发,再做一次微服务化改造,版本定为 v3.1.0。 问题是,这中间的 Spring Boot 版本变了。 单体架构改造时,根据业务方需求选择了 Spring Boot 3.4.7。这个版本号本身没问题——它是当时可用的最新稳定版。但当我们想在这个版本上加入 Spring Cloud 依赖时,启动直接炸了: 123456789101112131415***************************AP ...
🖥️ 基础设施与运维
未读从一个错误日志说起某天下午,前端同事反馈”页面加载很慢,偶尔直接白屏”。切到服务器上看 Nginx 日志,刷屏的是: 123452025/09/15 17:57:48 [crit] 24950#24950: *4354733 connect() to 127.0.0.1:9090 failed (99: Cannot assign requested address) while connecting to upstream, client: 192.168.0.184, server: _, request: "GET /api/user/api/resource/list/tree HTTP/1.1", upstream: "http://127.0.0.1:9090/user/api/resource/list/tree", host: "192.168.0.10:3000" Cannot assign requested address。这个错误的意思是——没有可用的本地端口了。 当时的 Nginx 配置是这样的: ...
🏠 HomeLab:中年男人之友
未读背景:运维账到了该清的时候这个博客我折腾着折腾着,已经变成一个”小站点、大后台”的状态了。 主站是 Hexo 静态页面,听上去很轻,但后面挂了一堆支撑服务:评论、搜索、统计、访问计数、AI 摘要、TTS、GitHub 贡献热力图、朋友圈聚合、短链、API 聚合……一数吓一跳,加起来有三四十个大大小小的进程。 这些服务过去分散在 好几台 PVE 节点上跑,分工大概是这样: A 节点跑数据库一类的基础设施 B 节点跑博客主系统和反向代理 C 节点跑一些 Node.js 的小微服务 D 节点跑监控、AI 平台之类的东西 听起来挺合理——按职责拆机器。但实际用下来,运维账越算越难看: 一次例行升级要 SSH 四五台机器,每台的 Docker Compose 文件风格都不一样 备份脚本有四五套,谁新增了服务我都得同步去改 服务之间的依赖关系横跨节点,数据库在 A,应用在 B,出问题排查要跨机器看日志 任何一台 PVE 节点挂了,我都得跑去柜子前面插显示器排障 功耗也不低,四台机器常年 7×24 开着,电费肉眼可见 同期我新上了一台 Mac Studio M2 Ultra 给 AI ...
🧱 后端开发与架构
未读第一个坑:XML 去哪了最先踩的坑很基础——MyBatis 的 Mapper XML 文件在打包成 jar 后消失了。 背景是我们在做一个日志组件,里面包含了 dao 接口和对应的 XML: 1234src/main/java/com/xxx/log/service/dao/├── LogDao.java└── xml/ └── LogDao.xml 有同事把 XML 和 dao 接口放在同一个包路径下,理由是”方便对照”。开发阶段一切正常,mvn spring-boot:run 跑起来 SQL 也能加载。但打包成 jar 给业务方引用时,运行提示 Invalid bound statement (not found)。 原因很简单:Maven 编译时只处理 src/main/java 下的 .java 文件,.xml 文件不会被拷贝到 target/classes。打包成 jar 后自然也没有。 修法有两种。第一种,把 XML 挪到 src/main/resources 下,保持相同包路径: 12src/main/java/com/xxx/log/service/dao/L ...
🧱 后端开发与架构
未读推行代码检查,最难的不是技术代码质量保障是个经典话题。Checkstyle 做格式检查,PMD 做逻辑缺陷检查,SonarQube 做全方位的代码质量度量——这三件套怎么用,网上文档很全。 但真正的挑战从来不是”怎么配置这些工具”,而是**怎么让一个已经运行了两年的、代码量不小的、团队成员流动频繁的项目接受”强制代码检查”**。 想象一下这个场景:你在 CI 管道里加上了 Checkstyle,规则用的是 Google Java Style。第二天,所有 MR 都挂了——不是代码逻辑有问题,而是缩进不对、命名不规范、缺少 Javadoc。开发 leader 来找你:”能不能先关掉,这个需求很急。”你说不能。他说那就先降级为 warn。 然后这个 warn 就永远是 warn 了。没人看 warn。 这不是假设,这就是大部分项目型组织中推行代码质量工具的真实路径。所以我花了大量时间思考的不是”选哪个工具”,而是”怎么让别人愿意用”。 工具分工:各干各的,互相补充先简单过一下三件套的定位。 Checkstyle 管格式。缩进是 4 个空格还是 tab?大括号是同行还是换行?类名是大驼峰还 ...




















