Nginx 日志切割终极指南:logrotate 完全配置手册
日志管理,是每一位后端开发者和运维工程师都绕不开的必修课。今天,我们就来聊聊Nginx 日志管理的最佳实践——logrotate。 为什么 logrotate 是业界标准?在众多日志管理方案中,logrotate 之所以能成为最主流、最推荐的选择,主要得益于以下几点: 稳定可靠:logrotate 是 Linux 系统自带的日志轮转工具,经过几十年的生产环境考验,成熟度极高,能自动完成切割、压缩和清理的全流程。 无性能损耗:与某些基于 Nginx 第三方模块或脚本的方案不同,logrotate 在日志轮转时对 Nginx 的请求处理不产生额外计算开销。 配置灵活:可以精细控制轮转周期、保留份数、是否压缩、权限设置等,满足各种运维需求。 核心配置详解在主机的 /etc/logrotate.d/ 目录下为 Nginx 日志创建配置文件(如 /etc/logrotate.d/nginx)。配置生效后,系统的 cron 服务会每日自动触发 logrotate 运行,实现全程无人值守。 1234567891011121314/var/log/nginx/*.log { ...
Trojan + Clash 搭建代理,科学上网
Trojan是一款比较流行的代理工具,支持代理流量和伪装网站共用443端口,不支持搭配CDN使用。 Trojan可以将科学上网流量伪装为HTTPS网页浏览,相比Shadowsocks/SSR/V2ray等其它工具,Trojan因为有真实的网页做为掩护,因此伪装效果更好,更不容易被封锁。从这一点来说,Trojan与V2ray的WS+TLS模式非常相似,两者的使用效果也很接近。 Trojan的优点: 使用TLS协议加密,安全性有保证。 使用真实网站伪装流量,不容易被封锁。 由于被认为是网站流量,基本不会被QOS限速,科学上网速度更快、更稳定。 由于Trojan的开发目的很明确,所以参数更少,配置更简单。 Trojan的不足: 出于实现原理,Troian的搭建,需要购买一个域名指向伪装网站。 需要在VPS服务器建立一个伪装网站并申请SSL证书。 ⚠说明以下内容仅作为技术学习,请科学上网 准备工作 一台境外 VPS:并已安装 Ubuntu 20.04 / 22.04 等 Linux 系统,拥有 root 权限 一个域名:并将域名的 A ...
Redis通关手册(三):Redis Geo实现地理位置检索
做业务开发时,我们经常遇到这类需求: ✅ 同城筛选附近门店、外卖骑手匹配✅ 社交APP附近的人、同城动态✅ 网约车就近派单、地理位置打卡 面对这些地理位置检索场景,无需引入笨重的专业GIS引擎,Redis自带的GEO地理空间索引是一个轻量、高性能的方案。 Redis GeoRedis Geo 没有创造新结构,完全基于有序集合 Sorted Set(ZSet)实现,底层核心组合:GeoHash 编码 + Sorted Set 索引。简单来说就是:把二维的经纬度坐标,通过算法压缩成一维整数分值,利用ZSet天然的排序、范围检索能力,实现高效的地理位置查询。 Key:地理集合名(如 stores:location 门店位置集合) Member:位置唯一标识(店铺ID、用户ID、设备ID) Score:经纬度编码后的52位GeoHash整数(排序、检索的核心) GeoHash 编码GeoHash的核心价值:将二维经纬度,转化为可排序、可比对的一维字符串。相近的地理位置,会拥有高度相似的编码前缀,这也是“附近查询”能够高效实现的根本原因。 GeoHash编码流程: 区间划分:针对地球...
Redis通关手册(二):概率数据结构
Redis的概率数据结构提供对计数、频率和排名等统计量的近似值,而不是精确值。使用近似的优点是它们对于许多常见用途来说是足够的,但计算起来却更加高效。它们有时还有其他优点,例如模糊处理时间、位置和其他敏感数据。 Bloom filter布隆过滤器是一种概率性数据结构,用于检查一个元素是否在集合中。 布隆过滤器是 Redis 开源中的一个概率性数据结构,它允许你使用一个非常小的固定大小的内存空间来检查一个元素是否在集合中。布隆过滤器不是存储集合中的所有元素,而是只存储元素的哈希表示。这种设计以牺牲部分精度为代价,换来了极高的空间效率和查询速度。 布隆过滤器有一个重要特性:它可以保证“元素不在集合中”的判断是绝对正确的;但对“元素在集合中”的判断,只能给出一个估计值——也就是说,每 N 个“存在”的回答中,可能会有 1 个是错误的。 虽然这种不确定性听起来有点奇怪,但在计算机科学中非常实用。因为否定回答能阻止许多昂贵的后续操作。例如: 检查用户名是否已被占用 检查信用卡号是否被报告为被盗 检查用户是否已经看过某条广告 应用场景检查用户名是否已被占用(SaaS、内容发布平台) 用户...
Redis通关手册(一):基本数据类型
Redis 是一个数据结构服务器。其核心是提供了一系列原生数据类型,可帮助您解决从缓存、队列到事件处理等各种各样的问题。以下是对常用的数据类型的简要描述,并提供指向更详细概述和命令参考的链接。 StringsRedis的字符串类型是最基本的数据类型,字符串存储字节序列,包括文本、序列化的对象和二进制数组。它们通常用于缓存,但还支持额外的功能,比如可以使用string实现计数器并执行位运算。 使用 SET 和 GET 命令是我们设置和检索字符串值的方式。请注意,如果键已经存在,即使键关联的是非字符串值, SET 也会替换任何已经存储在键中的值。所以 SET 执行的是赋值操作。 12345> SET bike:1 DeimosOK> GET bike:1"Deimos" 值可以是各种类型的字符串(包括二进制数据),例如你可以在一个值中存储一个 jpeg 图像。值的大小不能超过 512 MB。 SET 命令有一些有趣的选项,这些选项作为附加参数提供。例如,我可以要求 SET 如果键已存在则失败,或者相反,只有当键已存在时才成功: 1234> s...
踩坑实录:接口正常Feign调用字段值为空
Feign字段取不到值问题解析Postman直接调用接口时数据正常,但通过Feign调用时字段值却为null。起初怀疑是Feign配置问题,经过排查后才发现问题出在字段命名上——mName这类单字母驼峰命名被Jackson按规范推断为MName,导致大小写不匹配。 这种约定冲突比技术难点更难防范,耗费了半小时才搞清楚原因。 问题现象接口返回的客户信息如下: 1234{ "mName": "51石雷", "cAddr": "张东路1387号"} 对应的实体类定义为: 12345@Datapublic class CustomerInfo { private String mName; private String cAddr;} 从表面上看,字段名与JSON中的键值一一对应,似乎没有问题。然而,实际测试发现mName和cAddr的值始终为null,而其他字段则正常。 问题排除首先排除了接口本身的问题。通过Postman直接调用接口,数据...
踩坑实录:读写分离导致批量删除逻辑问题
最近在帮同事review代码时,发现一段逻辑看似正常但执行结果却不符合预期的代码,特此记录问题排查过程。 原始代码实现12345678910111213141516171819202122@Overridepublic void clearExpireOrder(LocalDate expireDate) { log.info("开始清理过期订单, 过期日期: {}", expireDate); int batchSize = 200; long totalDeletedCount = 0; while (true) { List<ExposureOrder> expireOrders = this.list(Wrappers.<ExposureOrder>lambdaQuery() .select(ExposureOrder::getId).le(ExposureOrder::getAdEndDate, expireDate.a...
Java应用启动慢、接口超时、频繁Full GC?别再把锅甩给JVM了!
💡TIP一次线上扩容实验,揭开隐藏在@RefreshScope背后的性能杀手 问题现场:扩容反而引发告警风暴最近,我们的服务在业务高峰进行一次常规扩容,新增了两个POD。本以为能平滑分担流量,结果启动后不久,P1级别接口超时告警和频繁Full GC告警接连爆发。 从监控图可以清晰看到: 新启动的POD在刚接收流量的前几分钟,接口平均耗时飙升到秒级; JVM的Full GC次数陡增,Old区几乎被打满; 运行几分钟后,一切又逐渐恢复正常。 这种现象并非第一次出现,我们注意到应用启动时也会出现类似的现象。扩容或者重启变成“陪葬”,到底是谁在作祟? 结论先行:@RefreshScope的滥用团队没有止步于表象,而是深入Spring Cloud源码,并结合Demo进行复现,最终锁定了“真凶”——**@RefreshScopel滥用**。 @RefreshScope的初始化“陷阱”在我们的应用中,大量Controller、Service类上都标注了@RefreshScope,初衷是为了实现Nacos配置的热更新。然而,这个注解的初始化行为却暗藏玄机: 普通Bean:...
零代码经验,我用Claude Code搓出的生产力工具
SmartScribe:一个让AI自动帮你整理笔记的Obsidian插件。支持6大AI平台,一键生成标题、标签、分类、摘要,还能智能优化写作。 这个项目的特殊之处不在于功能——在于它的代码100%由Claude Code生成。作者是一个后端程序员,一行前端代码都没写。 为什么要做这个项目痛点:笔记整理是道坎我用Obsidian写了3年笔记,积累了很多篇文章。但整理成了最大的负担: 标签混乱:今天用 #工作,明天用 #work,后天用 #项目,搜索时永远不全 分类困难:一篇笔记该放哪个文件夹?纠结5分钟,最后扔根目录 标题随意:随手记的笔记,标题经常是”临时记录”、”想法”,过两周自己都不记得是什么 摘要缺失:长篇笔记没有摘要,笔记发布博客时总结摘要很烦 试过手动整理,坚持不了一周。也试过其他插件,要么功能太死,要么功能不能完全支持我的需求。 契机:AI能读懂我的笔记了我开始尝试让AI帮我整理单篇笔记——把内容贴过去,让它生成标题、标签、分类、摘要。 效果出奇地好。AI不仅能理解内容,还能根据已有笔记的命名习惯给出建议。 但流程太麻烦:复制 → 打开浏览器 → 粘贴到对话框 →...
容器化后内存告警不断?日志“写爆”了Page Cache!
💡Tip服务在虚拟机上跑得好好的,容器化上 K8s 后却频繁触发内存超限告警,甚至 OOM Kill?堆内存才用了不到 10%,Pod 内存却飙到 80% 以上,到底是什么情况?本文将层层拆解,揭开容器内存暴涨的真相。 诡异的现象:JVM 很健康,Pod 却要“撑爆”了Java 服务容器化部署到 Kubernetes 后,Pod 内存使用率持续缓慢上升,频繁超过 80%,甚至触发 OOM 导致 Pod 重启。 资源配置如下: 123456789resources: requests: memory: 2200Mi cpu: 1000m limits: memory: 3000Mi cpu: 3000m JAVA_OPTS='-Xmx2000m' 按理说,JVM 堆内存只占 2000Mi,Pod limit 给了 3000Mi,还有近 1G 的空间给堆外、Metaspace 等,应该足够富裕。可为什么内存会超限呢? 排查过程:堆内存正常,堆外也正常,那内存去哪了?首先排查 JVM 堆内存进入容器,用 jhsd...
Harness Engineering 究竟是什么
💡TIPHarness Engineering 究竟是什么?不是又一个AI营销概念,而是AI从能说会道迈向能干成事的关键分水岭!本期深度拆解AI工程演进的三层核心:Prompt Engineering(让模型听懂你)、Context Engineering(让模型看到该看的信息)、Harness Engineering(让模型按目标完成任务)。为什么调用同样的模型,不同的AI Agent表现却天差地别?答案不在模型参数中,而在包裹模型的那套工程框架,这就是Harness Engineering ,它不是锦上添花的优化,而是决定AI能否落地生产的基础设施。 AI系统落地过程中,一个日益凸显的核心问题是:Agent的稳定性不仅取决于模型本身。真正决定AI Agent能否稳定工作的因素,往往不是模型,而是包裹模型的工程系统。 大语言模型的本质是什么?——高维概率预测说白了,大语言模型就是一个巨大的参数文件,平时它静静的躺在硬盘中,只有你将它加载到显存里,套上一层API再加一个聊天界面,它才会变成ChatGPT、Claude或者某种AI编程助手,无论它被包装成什么产品,...
Claude Code 通关手册(七):推荐 5 个 Hooks,代码质量提升 3 倍
💡TIP这是Claude Code通关手册的第八篇,推荐5个实用的Hook,代码质量提升 3 倍 上周三下午,我让 Claude Code 帮我重构一个老模块。 它干得挺快,噼里啪啦一顿输出。我切出去喝了口水,回来一看——它正准备把我一个还没有提交git的源文件直接覆盖掉。 手抖着点了“拒绝”,后背全是冷汗。 那一刻我突然意识到:不是 Claude 坏,是我太信任它了。 每次它问“我可以执行这个命令吗?”我都点“允许”,点多了就麻了。它要 rm -rf 我也点,它要改 .env 我也点——我把 AI 当成了不会犯错的神,但它只是个能力很强的实习生。 我翻了一遍 Claude Code 的文档,又刷了创始人 Boris 的 X。他分享了自己在用的几个 hooks,我全抄下来,砍掉一半,最后剩下 5 个。装上之后,Claude 还是那个 Claude,但我再也没怕过它。 Hook 到底是什么?3 秒钟理解你每次让 Claude 跑命令、改文件,它都会弹窗问你“行不行?”——这就是最后一道防线。 Hook 就是在弹窗之前或之后,自动跑一段你写好的脚本。 你想让它自动...








