Java 后端开发者理解 Vue:从 Controller 思维到响应式 UI

Java 后端开发者理解 Vue:从 Controller 思维到响应式 UI 如果你已经会 Java,熟悉 Spring、Controller、Service、DTO、Repository、拦截器、配置文件和请求响应链路,那么你看 Vue 代码时,大概率不是“完全看不懂”。你能看懂变量、函数、条件判断、数组遍历,也大概知道 <div>、<span>、class、@click、:disabled 在页面上会产生某些效果。 真正的问题通常不在“语法完全陌生”,而在于:你会不自觉用后端的心智模型去解释前端。 你可能会把 .vue 文件里的 <template> 当成类似 Spring XML、JSP、Thymeleaf 的配置或模板;会把 props 理解成 DTO 字段;会把 emit() 想成直接调用父组件方法;会把 v-model 想成子组件直接修改父组件变量;会把页面更新理解成“重新请求一次接口然后刷新页面”。这些直觉有一部分能帮你入门,但在 Vue 的核心机制上会误导你。 本文的目标不是泛泛讲 Vue,而是站在 Java/Spring 后端开发者的视角,把最容易困惑的部分拆开:Vue 页面为什么会自动刷新、ref() 和 .value 到底是什么、v-model 双向绑定是不是魔法、:xxx 和 @xxx 为什么不是普通 XML 属性、组件之间为什么要 props 向下 emit 向上,以及 Element Plus 组件、插槽、scoped CSS、:deep() 这些东西应该如何理解。 1. 先纠正一个根本误区:Vue 页面不是一次请求生成一次响应 后端开发者最熟悉的链路通常是: HTTP 请求 -> Controller -> Service -> Repository / Mapper -> 返回 JSON 或 HTML -> 本次请求结束 这个模型的核心是“一次请求,一次处理,一次响应”。 ...

2026年5月5日 · 11 分钟

Java 性能问题定位:从系统指标到应用排查

Java 性能问题定位:从系统指标到应用排查 参考阿里云大佬的博客,大佬写的非常好 本文整理 Java 应用在实际线上环境中进行性能问题定位时常见的分析思路,主要从业务代码、CPU、线程、内存、GC、磁盘 I/O、网络 I/O 以及常用命令几个角度展开。 性能问题往往不是单一指标异常导致的,而是系统层、组件层和应用层相互影响后的结果。因此,排查时建议先从应用层入手,再结合系统指标进行验证。 性能优化工具图谱 ├── 系统层 │ ├── CPU │ │ ├── 🚩 CPU利用率(top/vmstat/sar/dstat) │ │ ├── 🚩 CPU平均负载(top/uptime) │ │ └── 上下文切换次数(pidstat/vmstat/dstat) │ ├── 内存 │ │ ├── 全局内存使用 │ │ │ ├── 🚩 已用/剩余/可用内存(free/vmstat/sar) │ │ │ └── 缓冲区/缓存(pcstat/cachestat/cachetop) │ │ └── 进程内存使用 │ │ ├── 🚩 虚拟内存/常驻内存/共享内存(top/ps/pidstat) │ │ ├── 🚩 SWAP 内存使用/换入换出速度(top/free/vmstat/sar) │ │ ├── 缺页异常(ps/pidstat) │ │ └── 内存分布(pmap/jmap) │ ├── 磁盘 │ │ ├── 空间容量(df/du) │ │ ├── 🚩 吞吐量/磁盘 I/O 使用率(iostat/dstat/sar) │ │ └── 缓冲区/缓存(pcstat/cachestat/cachetop) │ └── 网络 │ ├── 🚩 吞吐量(sar) │ ├── 网络延迟(ping) │ ├── 🚩 网络连接数/错误数(netstat/ss/sar) │ └── 网络抓包(tcpdump/wireshark) ├── 组件层 │ ├── 数据库 │ │ ├── SQL 调优 │ │ ├── 🚩 索引调优 │ │ └── 连接池配置 │ ├── 网络 IO │ │ ├── I/O 调度模型 │ │ ├── 序列化框架 │ │ └── 线程调度模型 │ ├── Web 容器 │ │ └── 线程池配置 │ └── 缓存/MQ…… └── 应用层 ├── 线程 │ ├── 死锁检查(jstack/arthas) │ ├── 🚩 线程状态分布(jstack/arthas) │ ├── 锁竞争分布(jstack/arthas) │ ├── 🚩 代码执行热点(jprofiler/zprofiler) │ ├── 🚩 占用 CPU 较重的线程(top + pidstat + jstack) │ └── 代码追踪(btrace/housemd/greys/arthas) ├── 内存 │ ├── 内存分配 │ │ ├── 常驻内存/虚拟内存(top) │ │ ├── 对象分配热点(jprofiler/zprofiler) │ │ ├── 🚩 堆内对象分布(jmap/zprofiler/MAT) │ │ ├── 类加载相关(jstat/greys/arthas) │ │ ├── 🚩 内存泄漏(gperf/MAT/zprofiler) │ │ └── 堆外内存(jmap + MAT + NMT + gdb + perf) │ └── 垃圾回收 │ ├── GC 线程使用(jinfo) │ ├── 对象晋升年龄(gclog) │ ├── 🚩 GC 的频率和时间(jstat/gclog) │ ├── 垃圾回收器类型/JVM 参数(jinfo/jcmd) │ └── 🚩 堆大小设置及分区大小(jinfo/jstat) ├── 网络 │ ├── 带宽使用 │ ├── 流量异动 │ └── 网络分区 └── ★ 业务(日志、监控…) ├── 🚩 代码逻辑 ├── 远程调用 └── 架构设计 CPU&&线程 和 CPU 相关的指标主要有以下几个。常用的工具有 top、 ps、uptime、 vmstat、 pidstat等。 ...

2026年5月3日 · 8 分钟

大语言模型的可观测性应该有哪些

LLM可观测性 与传统微服务应用所关注的黄金三指标(请求数,错误,耗时)类比,我们认为 AI 应用的黄金三指标可能是 Token,Error,Duration。 耗时主要关注的是模型推理延迟,也就是在推理过程中我们通常需要关注模型的首包延迟,即 TTFT(Time to first token),这个指标反映了相应的速度,还有像 TPOT (Time Per Output Token) 反映生成的效率和流畅度。另外一个比较重要的指标就是吞吐率。吞吐率可以衡量我们这个模型本身,能够同时去支撑多少个推理请求。所以这几个指标是需要进行一些平衡的,三个指标不可能同时满足得特别好。 Token 可能是 AI 应用最重要的一个指标,所以每次请求会记录 Token 的消耗情况,甚至我们需要精确地区分 Input Token 和 Output Token 的消耗,因为大家知道模型的定价里面 Input Token 和 Output Token 是不一样的,我们在成本核算的时候,会将输入 Token 和输出 Token 分别进行统计。 不同卡的负载情况也是不一样的,这个也应该上报,并在扛不住的时候,自动熔断降级(比如用其他的卡) 耗时耗在哪? ==> 全链路追踪 问答质量 我们要解决模型回答得好不好,每次模型的升级和优化,都需要建立一个基线,并且确保模型的迭代满足这个基线,否则回答的质量会导致用户体验受损。为此,我们把模型的 input/output 全部都采集到日志平台中,接下来我们可以筛选出一批记录,通过数据加工,引用外部的裁判员模型,对当前这个模型回答的输入输出结果进行一个评估。 要把Trajectory做好 Trajectory 直译是:轨迹、路径、运行过程。 在 LLM Agent / AI Agent 里,Trajectory 通常指: Agent 为了完成一个任务,从接收用户问题开始,到最终输出答案为止,中间经历的完整执行过程。 它不只是最终答案,而是包括中间所有步骤。 例如用户问: “帮我查一下某个法规,并总结适用条件。” 一个 Agent 的 trajectory 可能是: 1. 接收用户问题 2. 判断用户意图:法规查询 + 条件总结 3. 改写检索 query 4. 调用知识库检索工具 5. 读取召回的法规条文 6. 判断哪些条文相关 7. 再次调用工具补充查询 8. 组织答案 9. 输出最终回答 这些步骤合起来,就叫一条 Agent trajectory。 ...

2026年4月25日 · 9 分钟

AI 时代个人的一些思考(持续更新)

技术一定是向着降低技术的门槛发展的,比如AI coding,降低了写代码的门槛,但也其实只是降低写代码这件事情本身,很多系统性的思考,系统设计的思想,AI是不能脑控你的,你得要自己理解why。 AI时期泡沫已经来了,不确定是不是泡沫的最高点,但是泡沫终会散去,怎么在这个时期保全自己? 苦练基本功 把自己的能力与AI红利摘除,你不能是因为吃了AI红利而强,与AI强绑定的话,可能就完蛋了。 这一点其实也和上面绑定,也就是一致。 初稿:2026-04-25。若你读到与当下实践不一致的句子,以你现场约束为准;欢迎留言或 PR 指出可改进之处。

2026年4月25日 · 1 分钟

MySQL 与 Elasticsearch 双写一致性

场景引入 如果你设计了一个类似 B 站的视频网站中的搜索系统,或许在初期 MySQL 的 like 模糊搜已经能满足你对视频的标题、简介的搜索需求。 SELECT * FROM videos WHERE title LIKE '%'||:search_term||'%' OR description LIKE '%'||:search_term||'%'; 如果后期系统视频的量级上来了,对性能有一定要求了,你或许已经开始考虑 ES 了。后面如果你还想让与搜索关键词相关的创作者名称、视频评论、关联标签也能级联视频搜出来,甚至弄一个各种业务维度的融合公式,那么 ES 这样的搜索引擎再适合不过了! 但是,如果数据写一份 MySQL,还要落一份 ES 来支撑筛选/搜索,要怎么写入两个异构的存储系统、并保证它们的一致性呢? Note 如果你有更好的场景欢迎提出/补充~ 方案一:同步双写 优点 简单粗暴 ES 同步写入快 缺点 业务耦合,扩展性差,代码侵入性强(要在写 MySQL 的地方后写 ES 的代码,要在代码设计上做好收敛) 影响性能,写入两个存储,响应时间变长(本来 MySQL 的写入性能不是很高,再加一个 ES,系统的性能必然会下降),吞吐也会下降 存在双写失败丢数据风险(比如写完MySQL,ES 就挂了) 方案二:异步双写 优点 性能高 不易出现数据丢失问题,主要基于 MQ 消息的消费保障机制,比如 ES 宕机或者写入失败,还能重新消费 MQ 消息 多源写入之间相互隔离(业务侧只管发消息),解耦数据生产者和消费者,便于扩展更多的数据源写入 缺点 同样存在业务耦合的问题,写完 DB 之后,还需要发个 MQ(代码设计上做好收敛,也可以关注一下所用 orm 框架有没有 hook 之类的能力,支持你“写后 xxx”) 接入新的数据源需要实现新的消费者代码 系统复杂度增加,引入了消息中间件 MQ是异步消费模型,存在延迟问题 Tip MQ 可以缓冲和 DB 的负载能力不一致问题 ...

2025年11月17日 · 1 分钟

Redis 大 key 问题

大 key 标准 在一般的业务场景下(并发和容量要求都不大): 单个string的value>1MB 容器ds元素数量超过10000 在高并发且低延迟的场景中:(互联网上看到比较多的版本) 单个string的value>10KB 容器ds元素数量超过5000或整体value>10MB 阿里云的云版本Redis: Key本身的数据量过大:一个String类型的Key,它的值为5MB Key中的成员数过多:一个ZSET类型的Key,它的成员数量为10000个 Key中成员的数据量过大:一个Hash类型的Key,它的成员数量虽然只有1000个但这些成员的Value(值)总大小为100MB 但其实Redis大key问题的定义及评判准则并非一成不变,没有固定的判别标准,还是要根据Redis在实际业务中的使用来综合评估。(注意边界问题) 大 key 影响 读取成本高 时延(执行命令时间更长) 带宽(大 key 消耗更多的带宽,从而影响相关服务) 大key的写操作容易阻塞,从而导致无法正常响应 慢查询 主从同步异常 占更多的存储空间,从而导致逐出,甚至是 OOM(Out Of Memory) 集群架构下,某个数据分片的内存使用率远超其他数据分片,即数据分片的内存资源不均衡 根本原因 Redis 是单线程! 大 key 产生原因 业务设计不合理。这是最常见的原因,不经过合理拆分,就直接把大json塞在一个key中;甚至塞二进制文件数据。 没有处理好value的动态增长问题。如果一直添加value数据,没有定期的删除机制、合理的过期机制或者卡量,大key只是早晚的问题。(例如:微博明星的粉丝列表、热门评论、直播弹幕等) 程序bug。某些异常情况导致某些key的生命周期超出预期,或者value数量异常增长。比如LIST的业务消费侧发生代码故障,造成对应Key的成员只增不减。 找到大 key bigkeys 参数 参考官方文档:https://redis.io/docs/latest/develop/connect/cli/#scanning-for-big-keys 使用redis-cli命令客户端,连接Redis服务的时候,加上 --bigkeys 参数,可以以遍历的方式分析Redis实例中的所有Key,并返回Key的整体统计信息与每个数据类型中Top1的大Key。(原理是基于SCAN) $ redis-cli --bigkeys # Scanning the entire keyspace to find biggest keys as well as # average sizes per key type. You can use -i 0.01 to sleep 0.01 sec # per SCAN command (not usually needed). [00.00%] Biggest string found so far 'key-419' with 3 bytes [05.14%] Biggest list found so far 'mylist' with 100004 items [35.77%] Biggest string found so far 'counter:__rand_int__' with 6 bytes [73.91%] Biggest hash found so far 'myobject' with 3 fields -------- summary ------- Sampled 506 keys in the keyspace! Total key length in bytes is 3452 (avg len 6.82) Biggest string found 'counter:__rand_int__' has 6 bytes Biggest list found 'mylist' has 100004 items Biggest hash found 'myobject' has 3 fields 504 strings with 1403 bytes (99.60% of keys, avg size 2.78) 1 lists with 100004 items (00.20% of keys, avg size 100004.00) 0 sets with 0 members (00.00% of keys, avg size 0.00) 1 hashs with 3 fields (00.20% of keys, avg size 3.00) 0 zsets with 0 members (00.00% of keys, avg size 0.00) 总结 优点:方便、快速、安全。 缺点:分析结果不可定制化,准确性与时效性差。 Redis RDB Tools工具 使用支持定制化分析的开源工具Redis RDB Tools,分析RDB文件,扫描出Redis大key。可以根据自己的精细化需求,全面地分析Redis实例中所有Key的内存占用情况,同时也支持灵活地分析查询。 ...

2025年3月15日 · 2 分钟

计算模型与主定理

例题 使用主定理 主定理是一个强大的工具,用于解决递归关系式,通常用于分析某些递归算法的时间复杂度。当递归关系式具有以下形式时: ...

2024年3月16日 · 2 分钟

Java 设计模式笔记

设计模式 举个例子,比如我们有个导出功能,按照不同的格式导出数据,比如 CSV、Excel、JSON 等;比如我们需要导入 execl 文件,需要解析文件内容,针对不同的格式,需要不同的解析方式;再比如我们有一个给用户发送邮件功能,有可能需要用 gmail, qq, 163 等邮箱服务商,手机验证码服务也是如此。如果我们使用 if-else 或者 switch-case 来实现,代码会变得很臃肿,而且扩展性很差,多一个导出为其他格式的需求,就需要大量修改代码。 处理之前的代码可能长这样: /** * @param filePath 文件路径(含文件名) * * 导出 CSV 和 Excel 的需求 */ public void export(String filePath) { String fileType = filePath.substring(filePath.lastIndexOf(".") + 1); if ("csv".equals(fileType)) { // 导出 CSV 的具体代码,以下省略100行 } else if ("excel".equals(fileType)) { // 导出 Excel 的具体代码,以下省略100行 } else { throw new IllegalArgumentException("不支持的文件类型:" + fileType); } } 策略模式 策略模式的主要作用是用来提升一些代码的复用性的,或者解决代码中出现很多 if-else 语句的问题。 ...

2024年1月21日 · 4 分钟