本地开发环境慢?localhost的锅!

本地开发环境慢?localhost 的锅!

一场历时三小时的性能追杀

第一章:晴空霹雳

"后台响应速度太慢了,查询要 300ms 以上,降到 50ms。"

接到这个需求的时候,我心想:不就是几个简单的 SELECT 查询吗?加个索引、优化下 SQL,手到擒来。

太天真了。

第二章:全面围剿

三个端点,全是简单的元数据查询:

sql 复制代码
SELECT id, code, name, table_name FROM meta_entity WHERE is_deleted = 0 ORDER BY code ASC;
SELECT ... FROM meta_entity_prop WHERE parent = ? AND is_deleted = 0 ORDER BY sort ASC;
SELECT ... FROM meta_enum_item WHERE parent = ? AND is_deleted = 0 ORDER BY create_time ASC;

于是开始了一轮又一轮的优化:

第一轮:索引 ------建覆盖索引,消除全表扫描。没解决。

第二轮:SQL 改写 ------把两次查询合成一次 JOIN,减少数据库往返。没解决。

第三轮:代码级优化 ------发现 resultSetToList 里在行循环中重复调用 ResultSetMetaData.getColumnLabel(),这可是 JDBC 驱动级操作!果断提到循环外面。还是没解决。

第四轮:祭出 Arthas------发现 Arthas 跟 Dragonwell JDK + JRebel 有兼容问题,Netty term server 绑定端口后立刻 CLOSE。Arthas 阵亡。

第五轮:JDK 内置 JFR ------启动参数居然带着 -XX:TieredStopAtLevel=1!这不等于让法拉利挂一档跑高速吗?赶紧去掉。依然没解决。

第六轮:XRebel------换上 Tomcat,XRebel 终于亮了。所有请求都在 10ms 内完成。完美!

......等等。

第三章:鬼打墙

如果 XRebel 说后端只用了 10ms,那 300ms 去哪儿了?

我盯着 Chrome DevTools 的 Network 面板,陷入了沉思:

复制代码
等待服务器响应 (TTFB):  313.90 ms  ← 这 313ms 在等什么?
下载内容:                 8.95 ms   ← 后端返回后浏览器秒收

后端 10ms 完成,浏览器却等了 313ms 才收到。中间的 300ms 凭空消失了。

那一刻我想到了所有可能的原因:

  • Vite 代理层有 bug?升级 Vite,优化 proxy,装上超时处理和监控日志。
  • 前端 JS 处理太慢?检查 Vue 渲染性能。
  • 操作系统 TCP 栈有问题?检查 Windows 网络配置。
  • 服务器 HikariCP 连接池满了?调大最小连接数。

我像个无头苍蝇一样在代码里来回乱撞。每一个可能的方向都是死胡同。

第四章:真相大白

折腾了三个小时之后,我瘫在椅子上,盯着浏览器的地址栏发呆。

然后我注意到------

地址栏里赫然写着:http://localhost:3000

等等。

我之前用 curl 直接调后端的时候,用的可是 127.0.0.1:8080

一个念头闪过。我抄起 Chrome,在地址栏里敲下:

复制代码
http://127.0.0.1:3000

回车。

页面刷出来了。我点了一下设计器。操作流畅得像在本地原生应用里一样。

我不信邪,打开 Network 面板,看了下请求耗时:

「15ms」

我揉了揉眼睛。

「12ms」

「8ms」

「6ms」

终章:localhost 的诅咒

真相让人哭笑不得:

Windows 上 localhost 不是直接走 127.0.0.1 的。

localhost 是一个 DNS 名称。Windows 会先尝试解析到 IPv6 地址 ::1,连接失败后再回退到 IPv4 的 127.0.0.1。这个 IPv6 → IPv4 回退过程 每次都要耗费 200-300ms。

而我的所有优化------索引、JOIN、列名预取、升级 Vite、换 Tomcat------它们都在正确地工作着。只是被操作系统自己给坑了。

花了一百万改装一辆赛车,结果赛道入口被一块石头堵了。

每次请求都要经历:

复制代码
浏览器 → localhost (DNS解析 ::1 → 超时 → 回退 127.0.0.1) → Vite 代理 → Java 后端
         ↑ 白白浪费 300ms                         ↑ 10ms 完成

改成 127.0.0.1 后:

复制代码
浏览器 → 127.0.0.1 (直连) → Vite 代理 → Java 后端
         ↑ 0ms              ↑ 10ms 完成

教训

排查性能问题时,先看一眼浏览器的地址栏------有时候最蠢的问题隐藏在最显眼的地方。

以及,localhost127.0.0.1 在 Windows 上不是一回事。


附:解决方案

方案 操作
立竿见影 浏览器地址栏用 http://127.0.0.1:3000 替代 http://localhost:3000
一劳永逸 修改 C:\Windows\System32\drivers\etc\hosts,确保 127.0.0.1 localhost 排在 ::1 localhost 前面
终极方案 禁用 IPv6(不推荐,可能影响其他网络功能)
相关推荐
一杯奶茶¥20 小时前
基于springboot的失物招领管理系统带万字文档 校园失物招领管理系统 失物认领管理系统java springboot vue
java·vue.js·spring boot·java项目
OpenTiny社区1 天前
这次更新太良心!GenUI SDK v1.2.0 轻量化 + 稳流式 + 超强 Playground
前端·vue.js·ai编程
秃头网友小李1 天前
前端难点:Element Plus 样式覆盖 —— :deep()、CSS 变量与滚动状态类名
前端·vue.js
英勇无比的消炎药1 天前
吃透 Sender 交互逻辑:提交快捷键事件与方法实战运用
vue.js
Agatha方艺璇1 天前
VUE复习笔记
前端·vue.js
chushiyunen1 天前
vue el-pagination实现分页
javascript·vue.js·elementui
wanger611 天前
Vue学习笔记
前端·javascript·vue.js
阿猫的故乡1 天前
Vue动态组件+异步组件实战:Tab切换、按需加载、KeepAlive缓存,一次搞定
前端·vue.js·缓存
阿猫的故乡1 天前
Vue3自定义插件:封装一个全局消息提示插件,所有组件都能直接用
前端·javascript·vue.js