文章目录
- [1. MeterRegistry 源码解读](#1. MeterRegistry 源码解读)
-
- [1.1 静态常量](#1.1 静态常量)
- [1.2 实例成员字段](#1.2 实例成员字段)
- [1.3 内部类 & 内部接口](#1.3 内部类 & 内部接口)
-
- [1.3.1 Config](#1.3.1 Config)
- [1.3.2 More](#1.3.2 More)
- [1.3.3 NewMeterSupplier</M extends Meter/>](#1.3.3 NewMeterSupplier</M extends Meter/>)
- [1.4 抽象工厂方法](#1.4 抽象工厂方法)
- [1.5 public 方法](#1.5 public 方法)
-
- [1.5.1 获取指标](#1.5.1 获取指标)
- [1.5.2 删除、清空](#1.5.2 删除、清空)
- [1.5.3 生命周期](#1.5.3 生命周期)
- [1. 5.4 返回 Config 内部实例](#1. 5.4 返回 Config 内部实例)
- [1.6 核心私有流程方法](#1.6 核心私有流程方法)
-
- [1.6.1 registerMeterIfNecessary()](#1.6.1 registerMeterIfNecessary())
- [1.6.2 getOrCreateMeter()](#1.6.2 getOrCreateMeter())
- [1.6.3 mapId(Meter.Id id)](#1.6.3 mapId(Meter.Id id))
- [1.6.4 accept(Meter.Id id)](#1.6.4 accept(Meter.Id id))
- [1.6.5 checkAndWarnAboutDoubleRegistration()](#1.6.5 checkAndWarnAboutDoubleRegistration())
- [1.6.6 isStaleId / unmarkStaleId](#1.6.6 isStaleId / unmarkStaleId)
- [2. SimpleMeterRegistry 实例化流程](#2. SimpleMeterRegistry 实例化流程)
-
- [2.1 步骤 1:进入 SimpleMeterRegistry() 无参构造器](#2.1 步骤 1:进入 SimpleMeterRegistry() 无参构造器)
- [2.2 步骤 2:解析两个入参](#2.2 步骤 2:解析两个入参)
-
- [2.2.1 SimpleConfig.DEFAULT](#2.2.1 SimpleConfig.DEFAULT)
- [2.2.2 Clock.SYSTEM](#2.2.2 Clock.SYSTEM)
- [2.3 步骤 3:进入双参构造器](#2.3 步骤 3:进入双参构造器)
- [2.4 步骤 4:执行 super (clock)](#2.4 步骤 4:执行 super (clock))
- [2.5 步骤 5:执行配置校验](#2.5 步骤 5:执行配置校验)
- [2.6 步骤 6:保存 config 引用到成员变量](#2.6 步骤 6:保存 config 引用到成员变量)
- [3. 添加到全局复合注册器](#3. 添加到全局复合注册器)
-
- [3.1 代码示例](#3.1 代码示例)
- [3.2 Metrics 源码](#3.2 Metrics 源码)
1. MeterRegistry 源码解读
MeterRegistry 是 Micrometer 的核心抽象基类,SimpleMeterRegistry、PrometheusMeterRegistry、CompositeMeterRegistry 都是它的实现类。所有 Counter、Timer、Gauge、DistributionSummary 等 Meter(度量器)全部由 MeterRegistry 创建、存放、管理。
源码要点:
- 负责
Meter的注册、过滤、去重、监听、删除生命周期; - 定义抽象工厂方法,交给子类实现具体
Meter实例; - 处理
MeterFilter过滤、ID映射(过滤前后两套ID映射); - 线程安全设计:
ConcurrentHashMap+meterMapLock对象锁; - 关闭之后返回
Noop*空实现,指标埋点调用无副作用。
1.1 静态常量
| 静态字段 | 作用 |
|---|---|
doubleRegistrationLogger |
重复注册告警日志器,Gauge/FunctionCounter/FunctionTimer重复注册输出警告 |
BASE_TIME_UNIT_STRING_CACHE |
EnumMap<TimeUnit,String>,时间单位字符串缓存,避免重复toString,性能优化 |
1.2 实例成员字段
| 字段 | 修饰符 | 类型 | 说明 |
|---|---|---|---|
clock |
protected final |
Clock |
时钟,提供时间戳,Timer/LongTaskTimer依赖;构造器传入,子类提供实现 |
meterMapLock |
private final |
Object |
全局对象锁;新增、删除、修改元数据都要synchronized(this.meterMapLock);读操作大多无锁,追求高并发性能 |
filters |
private volatile |
MeterFilter[] |
meter过滤器数组,volatile保证多线程可见;config.meterFilter()追加,数组拷贝生成新数组,不可变 |
meterAddedListeners |
private final |
CopyOnWriteArrayList<Consumer<Meter>> |
Meter新增事件监听器集合 |
meterRemovedListeners |
private final |
CopyOnWriteArrayList<Consumer<Meter>> |
Meter删除事件监听器集合 |
meterRegistrationFailedListeners |
private final |
CopyOnWriteArrayList<BiConsumer<Meter.Id,String>> |
注册失败监听器 |
config |
private final |
Config |
内部配置类实例,config()对外返回 |
more |
private final |
More |
内部类实例,封装不常用指标API(LongTaskTimer、FunctionCounter等) |
meterMap |
private final |
ConcurrentHashMap<Meter.Id,Meter> |
过滤之后的Meter存储Map(mappedId → Meter) 。对外getMeters()读取来源于此;CHM保证迭代不会并发修改异常 |
preFilterIdToMeterMap |
private final |
HashMap<Meter.Id,Meter> |
原始ID(过滤前)映射Meter ,key=未经过MeterFilter处理的原始Meter.Id;写操作受meterMapLock保护,读无锁 |
meterToPreFilterIdMap |
private final |
HashMap<Meter,Meter.Id> |
反向映射 Meter →原始Id;删除Meter时根据Meter快速找到原始pre‑filter id;锁保护 |
stalePreFilterIds |
private final |
HashSet<Meter.Id> |
过期原始Id集合 :当MeterFilter晚于meter注册时,旧注册的原始id标记为stale;再次注册时重新执行filter映射 |
syntheticAssociations |
private final |
HashMap<Meter.Id,Set<Meter.Id>> |
维护合成指标关联关系;删除主Meter时,把关联的合成指标一起删除;锁保护 |
closed |
private final |
AtomicBoolean |
注册表关闭标记;关闭后不再新建Meter,全部返回Noop实现;close()CAS设置true |
pauseDetector |
private |
PauseDetector |
协调遗漏补偿检测器,默认NoPauseDetector.INSTANCE;用于Timer停顿补偿 |
highCardinalityTagsDetector |
private @Nullable |
HighCardinalityTagsDetector |
高基数标签检测器,检测标签爆炸风险,可选开启 |
namingConvention |
private |
NamingConvention |
命名转换器,默认snakeCase;把meter id转换为监控后端识别的名字 |
📌两套ID概念:
- pre‑filter Id :业务传入原始
Meter.Id(注册时传入)- mappedId :经过全部
MeterFilter.map()处理之后的Id,存储到meterMap。
Micrometer 维护两套映射,是为了支持注册 Meter 之后再添加 MeterFilter 的场景(不推荐,但兼容)。
1.3 内部类 & 内部接口
1.3.1 Config
通过meterRegistry.config()获取;用于配置 Registry 行为,流式 API。
核心方法:
commonTags():全局通用标签,底层调用meterFilter(MeterFilter.commonTags())meterFilter(MeterFilter filter):追加过滤器。⚠️如果此时已经注册过Meter,打印警告日志,同时把所有已注册原始id加入stalePreFilterIds集合。onMeterAdded / onMeterRemoved / onMeterRegistrationFailed:注册事件监听器namingConvention():设置/获取命名规范clock():获取注册表时钟pauseDetector():设置停顿检测器withHighCardinalityTagsDetector():开启高基数标签爆炸检测。
内部私有方法 logWarningAboutLateFilter() :当 filter 在 meter 注册之后添加,打印 warn日志,同时输出堆栈(debug 级别)。
1.3.2 More
通过meterRegistry.more()获取,封装低频指标类型,避免主 API 臃肿:
longTaskTimer():长耗时任务计时器counter():FunctionCounter函数式计数器timer():FunctionTimer函数计时器timeGauge():TimeGauge时间型Gauge
1.3.3 NewMeterSupplier</M extends Meter/>
私有函数式接口,内部使用 ,注册 Meter 的 lambda 回调。
java
M create(MeterRegistry registry, Meter.Id id,
DistributionStatisticConfig distributionStatisticConfig,
PauseDetector pauseDetector);
用于把创建 Meter 的逻辑封装,在registerMeterIfNecessary统一处理重复注册、过滤、noop 分支。
1.4 抽象工厂方法
模板方法模式:父类 MeterRegistry 做注册、过滤、去重逻辑;真正创建 Meter 实例交给子类实现。
java
protected abstract <T> Gauge newGauge(Meter.Id id, @Nullable T obj, ToDoubleFunction<T> valueFunction);
protected abstract Counter newCounter(Meter.Id id);
protected abstract Timer newTimer(Meter.Id id, DistributionStatisticConfig distributionStatisticConfig,PauseDetector pauseDetector);
protected abstract DistributionSummary newDistributionSummary(Meter.Id id,DistributionStatisticConfig distributionStatisticConfig, double scale);
protected abstract Meter newMeter(Meter.Id id, Meter.Type type, Iterable<Measurement> measurements);
protected abstract <T> FunctionTimer newFunctionTimer(Meter.Id id, T obj,ToLongFunction<T> countFunction,ToDoubleFunction<T> totalTimeFunction, TimeUnit totalTimeFunctionUnit);
protected abstract <T> FunctionCounter newFunctionCounter(Meter.Id id, T obj, ToDoubleFunction<T> countFunction);
protected abstract TimeUnit getBaseTimeUnit();
protected abstract DistributionStatisticConfig defaultHistogramConfig();
newLongTaskTimer存在废弃重载,做向后兼容;newTimeGauge不是abstract,提供默认实现:内部封装Gauge,包装成TimeGauge匿名类。
1.5 public 方法
1.5.1 获取指标
counter() / timer() / summary() / gauge()多重载:支持可变tags、Iterable、Tags对象,构建Meter.Id,调用内部注册逻辑。more()返回More内部类实例。getMeters()返回不可修改的meter列表;底层meterMap.values().toArray()。forEachMeter()遍历所有meter。find(String name):Search,查找meter,找不到返回null。get(String name):RequiredSearch,找不到抛MeterNotFoundException。
1.5.2 删除、清空
remove(Meter meter):删除meter,使用mappedId。remove(Meter.Id mappedId):删除过滤后的Id;同时清理3张map,处理syntheticAssociations合成指标级联删除,触发meterRemovedListeners。removeByPreFilterId(Meter.Id preFilterId):按原始未过滤Id删除。clear():循环调用remove删除全部meter。
1.5.3 生命周期
close():CAS设置closed=true;关闭所有meter,关闭高基数检测器;关闭之后新建meter全部返回Noop空实现。isClosed():返回关闭状态。
1. 5.4 返回 Config 内部实例
java
config()
1.6 核心私有流程方法
1.6.1 registerMeterIfNecessary()
整个 MeterRegistry 最核心入口,所有 meter 注册都会走到这里。两个重载版本。
职责:
- 调用
getOrCreateMeter()完成meter查找/创建; - 校验:同一个
MeterId不能注册不同类型Meter,否则抛出IllegalArgumentException。
1.6.2 getOrCreateMeter()
完整注册流程:
- 根据原始
pre‑filter id查preFilterIdToMeterMap,命中并且不是stale,直接返回已存在meter,做重复注册警告。 - 调用
mapId()执行全部MeterFilter.map()得到mappedId,查meterMap;命中则返回,做重复注册警告。 - 判断注册表是否
losed→ 返回Noop*空Meter。 - 进入
synchronized(meterMapLock)临界区:双重检查锁再次判断meterMap是否存在该mappedId。 - 调用
accept(mappedId)执行MeterFilter.accept();如果返回DENY,返回Noop。 - 如果是
Timer/Summary类型,执行MeterFilter.configure()修改DistributionStatisticConfig配置,和defaultHistogramConfig()合并。 - 调用
NewMeterSupplier.create()回调,执行子类的newXXX()抽象工厂,创建真正Meter实例。 - 处理
syntheticAssociation合成指标关联。 - 触发
meterAddedListeners监听器。 - 写入三张
map:meterMap、preFilterIdToMeterMap、meterToPreFilterIdMap;清除stale标记。
1.6.3 mapId(Meter.Id id)
遍历所有filters,调用filter.map(id)完成 id 转换。
1.6.4 accept(Meter.Id id)
遍历 MeterFilter ,判断该 Meter 是否允许注册(ACCEPT / DENY / NEUTRAL)。
1.6.5 checkAndWarnAboutDoubleRegistration()
对 Gauge、FunctionCounter、FunctionTimer 做重复注册警告;普通Counter/ Timer重复注册不会告警(幂等,直接返回已存在实例)。
1.6.6 isStaleId / unmarkStaleId
staleId 机制,解决先注册 meter,后设置 MeterFilter 的兼容场景。
2. SimpleMeterRegistry 实例化流程
SimpleMeterRegistry 是 Micrometer 内置最小实现,主要用于单元测试,不对接任何监控后端,内存内保存所有 meter 数据。
调用入口:
java
SimpleMeterRegistry registry = new SimpleMeterRegistry();
2.1 步骤 1:进入 SimpleMeterRegistry() 无参构造器
java
// SimpleMeterRegistry.java 行37-39
public SimpleMeterRegistry() {
this(SimpleConfig.DEFAULT, Clock.SYSTEM); // → 委托到双参构造器
}
此时 JVM 堆分配了对象内存,所有实例字段置默认值 null:

2.2 步骤 2:解析两个入参
2.2.1 SimpleConfig.DEFAULT
是一个 lambda 实现 SimpleConfig 接口,get(key) 永远返回 null :
java
SimpleConfig DEFAULT = k -> null;
2.2.2 Clock.SYSTEM
系统时钟实现:
wallTime():System.currentTimeMillis()纪元毫秒,用于step周期边界判断monotonicTime():System.nanoTime()单调纳秒,用于计算耗时 (Timer)
java
// Clock.java 行19-27
Clock SYSTEM = new Clock() {
@Override
public long wallTime() {
return System.currentTimeMillis(); // 挂钟时间(ms),用于时间戳和 step 边界计算
}
@Override
public long monotonicTime() {
return System.nanoTime(); // 单调递增时间(ns),用于测量时间间隔
}
};
2.3 步骤 3:进入双参构造器
java
// SimpleMeterRegistry.java 行41-46
public SimpleMeterRegistry(SimpleConfig config, Clock clock) {
super(clock); // → 步骤4:调用父类 MeterRegistry(Clock) 构造器
config.requireValid(); // → 步骤5:校验 SimpleConfig 有效性
this.config = config; // → 步骤6:存储 config 引用
}
2.4 步骤 4:执行 super (clock)
父类 MeterRegistry 构造器:
java
// MeterRegistry.java 行154-157
protected MeterRegistry(Clock clock) {
requireNonNull(clock); // 断言 clock 非 null,否则抛 NPE
this.clock = clock; // 保存 clock 引用(Clock.SYSTEM 实例)
}
super (clock) 进入到父类构造器中时,会先把父类所有实例字段初始化完,此时 MeterRegistry 中已初始化的字段:

接着执行父类构造方法体:
java
requireNonNull(clock); // 断言 clock 非 null,否则抛 NPE
this.clock = clock; // 保存 clock 引用(Clock.SYSTEM 实例)
2.5 步骤 5:执行配置校验
调用 SimpleConfig#validate(),校验 step、mode 参数合法性;默认配置不会抛异常。
java
// MeterRegistryConfig.java 行44-46
default void requireValid() throws ValidationException {
validate().orThrow(); // → 先调 validate(),若无效则抛异常
}
SimpleConfig.DEFAULT.validate() 内部逻辑:
java
// SimpleConfig.java 行38-41
default Validated<?> validate() {
return checkAll(this,
check("step", SimpleConfig::step), // 校验 "simple.step" 属性
check("mode", SimpleConfig::mode) // 校验 "simple.mode" 属性
);
}
校验 step():
java
// SimpleConfig.java 行32-34
default Duration step() {
return getDuration(this, "step").orElse(Duration.ofMinutes(1));
}
// getDuration(this, "step") → 从 DEFAULT(k->null) 中查 "simple.step" → 返回 null
// .orElse(Duration.ofMinutes(1)) → 回退到默认值 **60 秒**
校验 mode():
java
// SimpleConfig.java 行41-43
default CountingMode mode() {
return getEnum(this, CountingMode.class, "mode").orElse(CountingMode.CUMULATIVE);
}
// getEnum(this, CountingMode.class, "mode") → 从 DEFAULT(k->null) 中查 "simple.mode" → 返回 null
// .orElse(CountingMode.CUMULATIVE) → 回退到默认值 **CUMULATIVE(累积模式)**
2.6 步骤 6:保存 config 引用到成员变量
✅ 到此 new SimpleMeterRegistry () 对象实例化完成。
⚠️注意:此时还没有任何指标 (Meter),registry 只是空容器。指标是后续调用Counter.builder()...register(registry) 才会被创建并注册进 registry。
此时 SimpleMeterRegistry 构造完毕,关键状态:
this.config=SimpleConfig.DEFAULTthis.clock=Clock.SYSTEMthis.getBaseTimeUnit()=TimeUnit.SECONDSthis.meterMap= 空的ConcurrentHashMap

3. 添加到全局复合注册器
3.1 代码示例
通常,一个应用只有一个 MeterRegistry 入口,可以使用 CompositeMeterRegistry 包含多个子 Registry ,实现一次埋点、到处上报 。
代码示例:
java
Metrics.addRegistry(registry)
new JvmMemoryMetrics().bindTo(Metrics.globalRegistry);
new JvmGcMetrics().bindTo(Metrics.globalRegistry);
new JvmThreadMetrics().bindTo(Metrics.globalRegistry);
new ProcessorMetrics().bindTo(Metrics.globalRegistry);
CompositeMeterRegistry:复合模式,当你往它注册一个 Meter,它会把这个 Meter 同步注册到它内部持有的所有子 registry。
3.2 Metrics 源码
Metrics 是 Micrometer 的静态全局工具门面类。
java
public static final CompositeMeterRegistry globalRegistry = new CompositeMeterRegistry();
public static void addRegistry(MeterRegistry registry) {
globalRegistry.add(registry);
}
CompositeMeterRegistry(复合注册器)本身不存储指标,内部维护一个List<MeterRegistry>列表,可以把多个实际的 registry(SimpleMeterRegistry / PrometheusMeterRegistry)装进去。