opensource4you / astraea

釋放kafka的無限潛能
Apache License 2.0
125 stars 45 forks source link

[METRICS] `MBeanRegister` might want to keep the order of the specified properties #1811

Open garyparrot opened 1 year ago

garyparrot commented 1 year ago

https://github.com/skiptests/astraea/blob/12bcb0ba8b85a173b72a416acc23c84dc9293732/app/src/main/java/org/astraea/app/performance/ConsumerThread.java#L103-L111

上面這段是出問題的程式碼,他註冊的 MBean 有兩個 property,其中 API 先宣告 type 再宣告 client-id

目前 MBeanRegister 的 property 是以一個 HashMap 來儲存

https://github.com/skiptests/astraea/blob/33a8a1a7ea4b7f0410f411965fe1ba48e7fba064/common/src/main/java/org/astraea/common/metrics/MBeanRegister.java#L82

在建立 MBeanInfo 時,這個順序會被 map 弄亂

https://github.com/skiptests/astraea/blob/33a8a1a7ea4b7f0410f411965fe1ba48e7fba064/common/src/main/java/org/astraea/common/metrics/MBeanRegister.java#L190

從 Java 的 MBean API 界面看過去他們似乎真的認為這個 properties 是無順序的。

image

但實際上最後把那個 map 轉換成要註冊的物件時,會被強加一個順序,像這邊 ConsumerThread 裡面唯一的 MBean 他的順序最後計算出來會和當初指定的顛倒。

雖然後面使用 MBeanServerConnection#getMBeanInfo 的時候,無論是

connection.getMBeanInfo(ObjectName.getInstance("org.astraea:type=consumer,client-id=5566"));
connection.getMBeanInfo(ObjectName.getInstance("org.astraea:client-id=5566,type=consumer"));

都可以查詢到那個 MBeanInfo,看起來 JVM 的實作真的是把 properties 當無關順序的處理。

但 jmx_exporter 好像不是這麼處理的,他背後可能是一個正則表達式,然後在匹配那個 ObjectName,這個行為導致只有依照那個我們沒辦法控制的 pattern 可以撈到他,比如下面的範例

# NOT OK
- pattern: org.astraea<type=consumer, client-id=(.+)><>exp-weight-by-time
  name: performance_tool_e2e_latency_ms
  type: GAUGE
  labels:
    client: "$1"

# OK
- pattern: org.astraea<client-id=(.+), type=consumer><>exp-weight-by-time
  name: performance_tool_e2e_latency_ms
  type: GAUGE
  labels:
    client: "$1"

雖然 JVM 覺得那個東西沒有順序可言,但因為 jmx_exporter 會在乎那個順序,可能我們需要不要使用那個 HashTable 版本的 ObjectName 建立函數,因為會沒辦法指定順序,可能可以考慮使用 https://docs.oracle.com/javase/8/docs/api/javax/management/ObjectName.html#getInstance-java.lang.String- 這個函數簽名的版本,剛剛測試了一下會保留我們傳入的順序。

chia7712 commented 1 year ago

Nice finding

+1 to the idea