单体前端一旦膨胀到几十万行、十几个团队协作,技术栈升级要全员陪跑、一次发版全站停机、一个模块出错拖垮整站——这些痛点的根因是”构建时被强行打包成一个应用”。微前端的核心思路是:把一个应用拆成多个可独立开发、独立部署、运行时再组合的子应用。本文不聊某个框架的内部响应式(那部分 Vue3/React 已经写过),只聊”多应用如何共存”这件事。
一、为什么需要微前端传统 SPA 在规模变大后会出现三类典型困境:
巨石仓库:所有页面、所有团队挤在一个仓库里,依赖版本被强行统一,任何改动都要全量回归。
发布耦合:改一行也要走全站发版流程,无法做到”哪个团队改了哪个模块,就只发哪个模块”。
技术栈锁死:想从 Vue2 升级到 Vue3,或者引入 React,几乎不可能渐进式迁移,只能一次性重写。
微前端(Micro-Frontends)把”应用”拆成多个子应用,每个子应用拥有独立的技术栈、独立仓库、独立 CI/CD,在运行时由”基座(主应用)”把它们拼回一个完整的站点。
微前端 ≠ 组件库,也 ≠ 模块化打包。组件库解决的是”同一个应用内的复用”,微前端解决的是”不同团队、不同技术栈、不同生 ...
这是「Java 从入门到精通」系列的第 18 篇,也是收官篇。写到这里,语法、集合、并发、JVM 这些”知识点”其实都只是入场券——真正决定一个工程师上限的,是他能不能把代码稳定地、可复现地、可观测地交付出去。本篇按”构建 → 规范 → 测试 → 日志 → 调优 → 收官”的顺序,讲清工具背后的原理,而不是给你一份工具清单。建议配合前面的篇章一起读:知道了 HashMap 怎么扩容,才知道为什么要给集合预设初始容量;知道了 JIT 会消除死代码,才知道为什么 System.currentTimeMillis() 测出来的性能十有八九是假的。
一、工程结构与构建:从”能编译”到”可复现”1.1 坐标、依赖范围与依赖传递Maven 的一切都建立在坐标(GAV)之上。坐标不只是”下载地址”,它是构件的唯一身份;仓库(本地仓库、私服、中央仓库)本质是”坐标 → 构件文件”的映射表,而 Maven 的核心工作,就是把 POM 里声明的坐标解析成一棵依赖树,再按这棵树拼出 classpath。
真正容易被忽略、却天天在影响你的是依赖范围(scope):它决定依赖在哪些 classpath 生效、 ...
本文是「Java 从入门到精通」系列的第 17 篇,假定你已经掌握集合框架、泛型、异常与并发基础(对应本系列第(七)(十二)(十三)篇)。全文代码以 JDK 21 为准,涉及预览特性的部分会用 --enable-preview 标注。阅读建议:Lambda 与 Stream 两章请务必动手跑一遍代码,尤其是 peek 不执行、流一次性消费、toMap 键冲突这三个坑,只有亲眼见过异常栈才会真正记住。
一、版本演进全景:从 Java 8 到 Java 212014 年发布的 Java 8 是 Java 历史上最重要的分水岭:它把函数式编程正式引入 Java 语法,Lambda、Stream、默认方法、新的日期时间 API 四件套同时落地。此后 Oracle 改为六个月一个版本的发布节奏,每两年挑一个版本作为 LTS(长期支持版)。到今天,Java 8 已经全面停止免费商业支持,而 Java 21 成为新一代的主流基线。
1.1 关键特性时间线
版本
发布时间
LTS
关键特性(各取 2-3 个)
Java 8
2014-03
是
Lambda 表达式、Stream API ...
本文默认读者已掌握 Java 基础与多线程,JVM 以 HotSpot 为主,JDK 横跨 8 / 11 / 17 / 21,会明确标注版本差异——尤其是 GC 日志格式(JDK 9 前后完全两套)与默认收集器的变更。建议边读边跑第五节的日志实验与第七节的 CPU 飙高实验:调优从来不是背参数,而是”看到数据—提出假设—小步验证”的闭环。
一、GC 到底要解决什么问题1.1 为什么不是引用计数判断对象”还活着没有”,最朴素的想法是引用计数(Reference Counting):每个对象维护计数器,有人引用 +1,失效 -1,归零立刻回收。Python、PHP、Objective-C ARC 都用这套方案,实现简单、回收及时。但它有致命缺陷——无法处理循环引用,两个对象互相持有对方时计数永远不为 0;且每次赋值都要改计数器,多线程下还要保证原子性。HotSpot 因此放弃了它。
123456789101112131415161718192021/** * 演示循环引用:在引用计数方案下这两个对象永远不会被回收。 * HotSpot 使用可达性分析,因此 GC 后它们会被正常回收。 * ...
Kafka 篇讲过 Broker 元数据、HBase 篇讲过 RegionServer 上线——这两个系统背后其实都站着同一个”协调员”:ZooKeeper。分布式系统里最麻烦的不是算,而是多台机器对”谁说了算、配置改没改、锁归谁拿”达成一致。本文把 ZooKeeper 最核心的四块:ZNode 数据模型、Watch 机制、集群读写流程、ZAB 协议一次讲透,并给出分布式锁/选主的正确落地姿势与生产避坑清单。
一、为什么需要协调服务单机时代不存在的问题,到了分布式时代全冒出来了:
经典难题
具体表现
ZooKeeper 提供的原语
谁是主
主挂了,多台备机同时认为自己是主(脑裂)
临时节点 + 顺序节点 + Watch → 选主
配置同步
改一份配置要登录 N 台机器,改漏一台就出事故
ZNode 存配置 + Watch 推送变更
互斥锁
多个进程同时改同一份数据,谁先谁后?
临时顺序节点 → 分布式锁
集群成员管理
某台机器”假死”,它的任务资源怎么释放?
临时节点:会话断开自动删除
命名/寻址
服务实例动态上下线,调用方怎么感知?
顺序节点 + W ...
本篇属于 进阶向硬核内容。文中所有代码均在 JDK 17(HotSpot 64-Bit Server VM) 上验证过,涉及 JDK 8 / 11 / 21 差异的地方会单独标注。想真正吃透,请把示例代码敲一遍,尤其是对象布局与自定义类加载器那两段。
写在前面:为什么要学这一块很多同学写 Java 三五年,对 JVM 的认知停留在「堆放对象、栈放局部变量、方法区放类信息」。这三句话没错,但粗到无法支撑下面这些问题:8C16G 的容器 -Xmx 该设多大(设小了频繁 Full GC、设大了被 OOMKilled);一个 new Object() 在 64 位机器上占几个字节;为什么 -Xmx 还剩一大截却抛 Metaspace 的 OOM;Tomcat 里两个 WebApp 各引一个不同版本的 Spring 为什么不打架。答案全在运行时数据区和类加载子系统里。
一、JVM 整体架构:规范与实现的分野1.1 一个必须厘清的前提:规范不等于实现《Java Virtual Machine Specification》定义的是抽象行为契约:Class 文件格式、字节码指令集、运行时数据区、类加 ...
本文默认读者已掌握线程基础与 synchronized/volatile(可参考本系列第十二篇)。JDK 以 8/11 为主,第八节虚拟线程需 JDK 21+。文中源码片段是对 OpenJDK 真实实现的简化改写:保留了位运算、CAS、锁与循环的关键结构,删掉了异常分支与注释噪音,便于阅读但不建议直接拷贝编译。所有 Demo 均可 javac 运行,建议把第三节的位运算实验与第六节的聚合 Demo 亲手跑一遍。
并发能提升吞吐,但”每来一个请求就 new Thread()“是把并发用成了灾难。第十二篇解决了”多个线程如何正确共享数据”,本篇解决另一个维度的问题:线程本身作为一种昂贵资源,该如何被复用、被管控、被观测。从 ThreadPoolExecutor 的位运算源码,到 CompletableFuture 的回调链编排,再到 JDK 21 虚拟线程对这套模型的颠覆,是一条从”会用”到”懂原理”再到”知道何时不该用”的完整路径。
一、为什么要线程池:先把线程的成本算清楚1.1 一个线程到底有多贵JDK 21 之前,java.lang.Thread 采用的是 1:1 线程模型:一个 ...
Spring Boot 解决的是”怎么又快又好地写一个服务”,Spring Cloud 解决的是”一堆服务怎么协同、治理、不互相拖垮”。本文不重复 Spring Boot 自动装配、JVM 调优、并发编程那些已经写过的点,只聚焦”服务拆分之后那些绕不开的分布式基础设施”,并用 Spring Cloud Alibaba 这套国内最主流的落地方案串起来。
一、为什么需要微服务:从单体到分布式早期一个 war 包打天下:Controller、Service、DAO 全在一个进程里,改一行要整体重发。业务小的时候很爽,大了就有三个典型痛点。
扩展只能整体扩:下单模块 CPU 打满,却被迫连不忙的用户模块一起加机器,浪费资源。
技术栈被锁死:想用 Go 写实时推送?不行,单体是 Java 一统天下。
发布互相牵连:改个文案的手抖,可能把支付一起带崩。
微服务的核心思想就八个字:拆得开、各自治、独立发。每个服务拥有自己的进程、数据库、迭代节奏,通过 RPC/HTTP 协作。
但微服务不是银弹。它把”进程内的函数调用”变成了”跨网络的远程调用”,代价是:网络不可靠、数据要一致、链路要可观测、运 ...
本文默认读者已掌握线程生命周期、JMM 与 synchronized/volatile(系列第十二篇),JDK 以 8 为主,涉及 9 之后的变化(Unsafe 迁往 VarHandle)会单独标注。AQS 一节最硬,建议按”state 是什么 → 队列怎么排 → 线程怎么睡 → 谁把它叫醒”四步推演,读完再回头看 ReentrantLock、CountDownLatch、Semaphore,会发现它们只是同一套骨架上的不同血肉。
一、JUC 全景与定位靠 synchronized 与 volatile 能解决大部分并发问题,但它们有两个天然短板:一是不可中断——等监视器锁时无法响应 interrupt(),死锁只能重启;二是不够灵活——没有尝试加锁、没有超时、没有读写分离、也没有多个等待队列,想做”生产者只唤醒消费者”这种精细控制,wait/notify 只能 notifyAll 全量广播。
JUC(java.util.concurrent)正是为了补上这块拼图。它由 Doug Lea 主导设计,从 JDK 5 引入,核心思路是:把并发控制的公共骨架抽出来做成可复用组件,让业务代码 ...
本文默认读者已掌握 Java 基础语法与集合框架,JDK 以 8 为主,同时标注 JDK 15 之后偏向锁被废弃带来的变化。文中代码均可直接运行,建议边读边跑,尤其是第三节 i++ 复现实验与第七节死锁实验——只有亲眼看到”结果不等于 20000”和”jstack 打印出 deadlock”,抽象的内存模型概念才会落地。
一、为什么要并发:从摩尔定律失效说起过去二十年程序员享受过一段”免费的午餐”:CPU 主频从几百 MHz 涨到几 GHz,同样的代码不改一行,明年就自动变快。但 2005 年前后这条曲线断了——受制于功耗墙与散热极限,单核主频停滞在 4GHz 附近,厂商转而把晶体管堆成多核。于是”免费午餐”结束:想变快,就得自己写并发。
并发(Concurrency)与并行(Parallelism)经常被混用,但层次不同。并发指”逻辑上同时处理多件事”,强调结构与调度,单核上靠时间片轮转也能实现;并行指”物理上真正同时执行多条指令”,必须依赖多核。可以说并行是并发在硬件上的一种执行形态,是并发的子集。
维度
并发 Concurrency
并行 Parallelism
...






























