This is an automated email from the ASF dual-hosted git repository.

nicholasjiang pushed a commit to branch branch-0.4
in repository https://gitbox.apache.org/repos/asf/incubator-celeborn.git


The following commit(s) were added to refs/heads/branch-0.4 by this push:
     new 3eb2c4552 [CELEBORN-1182][0.4] Support application dimension 
ActiveConnectionCount metric to record the number of registered connections for 
each application
3eb2c4552 is described below

commit 3eb2c4552ce1c845d64e1c60573f418587ba46c8
Author: SteNicholas <[email protected]>
AuthorDate: Fri Feb 2 20:59:31 2024 +0800

    [CELEBORN-1182][0.4] Support application dimension ActiveConnectionCount 
metric to record the number of registered connections for each application
    
    ### What changes were proposed in this pull request?
    
    Cherry pick #2167.
    
    `WorkerSource` supports application dimension `ActiveConnectionCount` 
metric to record the number of registered connections for each application.
    
    ### Why are the changes needed?
    
    `ActiveConnectionCount` metric records the number of registered connections 
at present. It's recommended to support dimension ActiveConnectionCount metric 
to record the number of registered connections for each application in Worker. 
Application dimension `ActiveConnectionCount` metric could provide users with 
the actual number of registered connections for each application.
    
    ### Does this PR introduce _any_ user-facing change?
    
    No.
    
    ### How was this patch tested?
    
    Internal tests.
    
    Closes #2280 from SteNicholas/CELEBORN-1182-0.4.
    
    Authored-by: SteNicholas <[email protected]>
    Signed-off-by: SteNicholas <[email protected]>
---
 .../common/metrics/source/AbstractSource.scala     |  2 +
 .../metrics/source/ResourceConsumptionSource.scala |  2 -
 .../celeborn/service/deploy/master/Master.scala    |  4 +-
 .../deploy/worker/storage/CreditStreamManager.java | 22 ++++++++--
 .../service/deploy/worker/FetchHandler.scala       | 39 +++++++++++++-----
 .../service/deploy/worker/PushDataHandler.scala    |  7 +++-
 .../celeborn/service/deploy/worker/Worker.scala    | 10 ++++-
 .../service/deploy/worker/WorkerSource.scala       | 47 ++++++++++++++++++++++
 .../worker/storage/CreditStreamManagerSuiteJ.java  | 11 +++--
 9 files changed, 119 insertions(+), 25 deletions(-)

diff --git 
a/common/src/main/scala/org/apache/celeborn/common/metrics/source/AbstractSource.scala
 
b/common/src/main/scala/org/apache/celeborn/common/metrics/source/AbstractSource.scala
index 8d76414c1..301d991a2 100644
--- 
a/common/src/main/scala/org/apache/celeborn/common/metrics/source/AbstractSource.scala
+++ 
b/common/src/main/scala/org/apache/celeborn/common/metrics/source/AbstractSource.scala
@@ -67,6 +67,8 @@ abstract class AbstractSource(conf: CelebornConf, role: 
String)
   val staticLabels: Map[String, String] = conf.metricsExtraLabels + roleLabel
   val staticLabelsString: String = MetricLabels.labelString(staticLabels)
 
+  val applicationLabel = "applicationId"
+
   protected val namedGauges: JQueue[NamedGauge[_]] = new 
ConcurrentLinkedQueue[NamedGauge[_]]()
 
   def addGauge[T](
diff --git 
a/common/src/main/scala/org/apache/celeborn/common/metrics/source/ResourceConsumptionSource.scala
 
b/common/src/main/scala/org/apache/celeborn/common/metrics/source/ResourceConsumptionSource.scala
index 88a4b9858..df33310bb 100644
--- 
a/common/src/main/scala/org/apache/celeborn/common/metrics/source/ResourceConsumptionSource.scala
+++ 
b/common/src/main/scala/org/apache/celeborn/common/metrics/source/ResourceConsumptionSource.scala
@@ -33,6 +33,4 @@ object ResourceConsumptionSource {
   val HDFS_FILE_COUNT = "hdfsFileCount"
 
   val HDFS_BYTES_WRITTEN = "hdfsBytesWritten"
-
-  val APPLICATION_LABEL = "applicationId"
 }
diff --git 
a/master/src/main/scala/org/apache/celeborn/service/deploy/master/Master.scala 
b/master/src/main/scala/org/apache/celeborn/service/deploy/master/Master.scala
index ad35ae005..cca9047d2 100644
--- 
a/master/src/main/scala/org/apache/celeborn/service/deploy/master/Master.scala
+++ 
b/master/src/main/scala/org/apache/celeborn/service/deploy/master/Master.scala
@@ -813,7 +813,7 @@ private[celeborn] class Master(
       appId: String): Unit = {
     resourceConsumptionSource.removeGauge(
       resourceConsumptionName,
-      ResourceConsumptionSource.APPLICATION_LABEL,
+      resourceConsumptionSource.applicationLabel,
       appId)
   }
 
@@ -893,7 +893,7 @@ private[celeborn] class Master(
       applicationId: String = null): Unit = {
     val resourceConsumptionLabel =
       if (applicationId == null) userIdentifier.toMap
-      else userIdentifier.toMap + (ResourceConsumptionSource.APPLICATION_LABEL 
-> applicationId)
+      else userIdentifier.toMap + (resourceConsumptionSource.applicationLabel 
-> applicationId)
     resourceConsumptionSource.addGauge(
       ResourceConsumptionSource.DISK_FILE_COUNT,
       resourceConsumptionLabel) { () =>
diff --git 
a/worker/src/main/java/org/apache/celeborn/service/deploy/worker/storage/CreditStreamManager.java
 
b/worker/src/main/java/org/apache/celeborn/service/deploy/worker/storage/CreditStreamManager.java
index e3fb43aa1..b2981a763 100644
--- 
a/worker/src/main/java/org/apache/celeborn/service/deploy/worker/storage/CreditStreamManager.java
+++ 
b/worker/src/main/java/org/apache/celeborn/service/deploy/worker/storage/CreditStreamManager.java
@@ -76,6 +76,7 @@ public class CreditStreamManager {
   public long registerStream(
       Consumer<Long> notifyStreamHandlerCallback,
       Channel channel,
+      String shuffleKey,
       int initialCredit,
       int startSubIndex,
       int endSubIndex,
@@ -110,7 +111,7 @@ public class CreditStreamManager {
                 }
               }
               initializeStreamStateAndPartitionReader(
-                  channel, startSubIndex, endSubIndex, fileInfo, streamId, v);
+                  channel, shuffleKey, startSubIndex, endSubIndex, fileInfo, 
streamId, v);
               return v;
             });
     if (exception.get() != null) {
@@ -128,12 +129,14 @@ public class CreditStreamManager {
 
   private void initializeStreamStateAndPartitionReader(
       Channel channel,
+      String shuffleKey,
       int startSubIndex,
       int endSubIndex,
       FileInfo fileInfo,
       long streamId,
       MapDataPartition mapDataPartition) {
-    StreamState streamState = new StreamState(channel, 
fileInfo.getBufferSize(), mapDataPartition);
+    StreamState streamState =
+        new StreamState(channel, shuffleKey, fileInfo.getBufferSize(), 
mapDataPartition);
     streams.put(streamId, streamState);
     mapDataPartition.setupDataPartitionReader(startSubIndex, endSubIndex, 
streamId, channel);
   }
@@ -182,6 +185,10 @@ public class CreditStreamManager {
     return streams;
   }
 
+  public String getStreamShuffleKey(Long streamId) {
+    return streams.get(streamId).getShuffleKey();
+  }
+
   private void startRecycleThread() {
     synchronized (lock) {
       if (recycleThread == null) {
@@ -241,12 +248,17 @@ public class CreditStreamManager {
 
   protected class StreamState {
     private Channel associatedChannel;
+    private String shuffleKey;
     private int bufferSize;
     private MapDataPartition mapDataPartition;
 
     public StreamState(
-        Channel associatedChannel, int bufferSize, MapDataPartition 
mapDataPartition) {
+        Channel associatedChannel,
+        String shuffleKey,
+        int bufferSize,
+        MapDataPartition mapDataPartition) {
       this.associatedChannel = associatedChannel;
+      this.shuffleKey = shuffleKey;
       this.bufferSize = bufferSize;
       this.mapDataPartition = mapDataPartition;
     }
@@ -255,6 +267,10 @@ public class CreditStreamManager {
       return associatedChannel;
     }
 
+    public String getShuffleKey() {
+      return shuffleKey;
+    }
+
     public int getBufferSize() {
       return bufferSize;
     }
diff --git 
a/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/FetchHandler.scala
 
b/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/FetchHandler.scala
index dc8cbe61f..ebdb1af65 100644
--- 
a/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/FetchHandler.scala
+++ 
b/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/FetchHandler.scala
@@ -100,9 +100,9 @@ class FetchHandler(
   override def receive(client: TransportClient, msg: RequestMessage): Unit = {
     msg match {
       case r: BufferStreamEnd =>
-        handleEndStreamFromClient(r.getStreamId)
+        handleEndStreamFromClient(client, r.getStreamId)
       case r: ReadAddCredit =>
-        handleReadAddCredit(r.getCredit, r.getStreamId)
+        handleReadAddCredit(client, r.getCredit, r.getStreamId)
       case r: ChunkFetchRequest =>
         handleChunkFetchRequest(client, r.streamChunkSlice, r)
       case unknown: RequestMessage =>
@@ -137,9 +137,12 @@ class FetchHandler(
           openStream.getReadLocalShuffle,
           callback)
       case bufferStreamEnd: PbBufferStreamEnd =>
-        handleEndStreamFromClient(bufferStreamEnd.getStreamId, 
bufferStreamEnd.getStreamType)
+        handleEndStreamFromClient(
+          client,
+          bufferStreamEnd.getStreamId,
+          bufferStreamEnd.getStreamType)
       case readAddCredit: PbReadAddCredit =>
-        handleReadAddCredit(readAddCredit.getCredit, readAddCredit.getStreamId)
+        handleReadAddCredit(client, readAddCredit.getCredit, 
readAddCredit.getStreamId)
       case chunkFetchRequest: PbChunkFetchRequest =>
         handleChunkFetchRequest(
           client,
@@ -205,6 +208,7 @@ class FetchHandler(
       isLegacy: Boolean,
       readLocalShuffle: Boolean = false,
       callback: RpcResponseCallback): Unit = {
+    workerSource.recordAppActiveConnection(client, shuffleKey)
     workerSource.startTimer(WorkerSource.OPEN_STREAM_TIME, shuffleKey)
     try {
       var fileInfo = getRawFileInfo(shuffleKey, fileName)
@@ -275,6 +279,7 @@ class FetchHandler(
           creditStreamManager.registerStream(
             creditStreamHandler,
             client.getChannel,
+            shuffleKey,
             initialCredit,
             startIndex,
             endIndex,
@@ -345,23 +350,33 @@ class FetchHandler(
     
rpcResponseCallback.onFailure(ExceptionUtils.wrapIOExceptionToUnRetryable(ioe))
   }
 
-  def handleEndStreamFromClient(streamId: Long): Unit = {
-    handleEndStreamFromClient(streamId, StreamType.CreditStream)
+  def handleEndStreamFromClient(client: TransportClient, streamId: Long): Unit 
= {
+    handleEndStreamFromClient(client, streamId, StreamType.CreditStream)
   }
 
-  def handleEndStreamFromClient(streamId: Long, streamType: StreamType): Unit 
= {
+  def handleEndStreamFromClient(
+      client: TransportClient,
+      streamId: Long,
+      streamType: StreamType): Unit = {
     streamType match {
       case StreamType.ChunkStream =>
         val (shuffleKey, fileName) = 
chunkStreamManager.getShuffleKeyAndFileName(streamId)
+        workerSource.recordAppActiveConnection(client, shuffleKey)
         getRawFileInfo(shuffleKey, fileName).closeStream(streamId)
       case StreamType.CreditStream =>
+        workerSource.recordAppActiveConnection(
+          client,
+          creditStreamManager.getStreamShuffleKey(streamId))
         creditStreamManager.notifyStreamEndByClient(streamId)
       case _ =>
         logError(s"Received a PbBufferStreamEnd message with unknown type 
$streamType")
     }
   }
 
-  def handleReadAddCredit(credit: Int, streamId: Long): Unit = {
+  def handleReadAddCredit(client: TransportClient, credit: Int, streamId: 
Long): Unit = {
+    workerSource.recordAppActiveConnection(
+      client,
+      creditStreamManager.getStreamShuffleKey(streamId))
     creditStreamManager.addCredit(credit, streamId)
   }
 
@@ -372,6 +387,10 @@ class FetchHandler(
     logDebug(s"Received req from 
${NettyUtils.getRemoteAddress(client.getChannel)}" +
       s" to fetch block $streamChunkSlice")
 
+    workerSource.recordAppActiveConnection(
+      client,
+      
chunkStreamManager.getShuffleKeyAndFileName(streamChunkSlice.streamId)._1)
+
     maxChunkBeingTransferred.foreach { threshold =>
       val chunksBeingTransferred = chunkStreamManager.chunksBeingTransferred 
// take high cpu usage
       if (chunksBeingTransferred > threshold) {
@@ -436,12 +455,12 @@ class FetchHandler(
   /** Invoked when the channel associated with the given client is active. */
   override def channelActive(client: TransportClient): Unit = {
     logDebug(s"channel active ${client.getSocketAddress}")
-    workerSource.incCounter(WorkerSource.ACTIVE_CONNECTION_COUNT)
+    workerSource.connectionActive(client)
     super.channelActive(client)
   }
 
   override def channelInactive(client: TransportClient): Unit = {
-    workerSource.incCounter(WorkerSource.ACTIVE_CONNECTION_COUNT, -1)
+    workerSource.connectionInactive(client)
     creditStreamManager.connectionTerminated(client.getChannel)
     logDebug(s"channel inactive ${client.getSocketAddress}")
   }
diff --git 
a/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/PushDataHandler.scala
 
b/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/PushDataHandler.scala
index 82d48bf18..5584a29b5 100644
--- 
a/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/PushDataHandler.scala
+++ 
b/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/PushDataHandler.scala
@@ -110,6 +110,7 @@ class PushDataHandler(val workerSource: WorkerSource) 
extends BaseMessageHandler
   override def receive(client: TransportClient, msg: RequestMessage): Unit =
     msg match {
       case pushData: PushData =>
+        workerSource.recordAppActiveConnection(client, pushData.shuffleKey)
         val callback = new SimpleRpcResponseCallback(
           client,
           pushData.requestId,
@@ -133,6 +134,7 @@ class PushDataHandler(val workerSource: WorkerSource) 
extends BaseMessageHandler
           },
           callback)
       case pushMergedData: PushMergedData =>
+        workerSource.recordAppActiveConnection(client, 
pushMergedData.shuffleKey)
         val callback = new SimpleRpcResponseCallback(
           client,
           pushMergedData.requestId,
@@ -828,6 +830,7 @@ class PushDataHandler(val workerSource: WorkerSource) 
extends BaseMessageHandler
     val requestId = rpcRequest.requestId
     val (pbMsg, msg, isLegacy, messageType, mode, shuffleKey, 
partitionUniqueId, checkSplit) =
       mapPartitionRpcRequest(rpcRequest)
+    workerSource.recordAppActiveConnection(client, shuffleKey)
     handleCore(
       client,
       rpcRequest,
@@ -1293,7 +1296,7 @@ class PushDataHandler(val workerSource: WorkerSource) 
extends BaseMessageHandler
    * Invoked when the channel associated with the given client is active.
    */
   override def channelActive(client: TransportClient): Unit = {
-    workerSource.incCounter(WorkerSource.ACTIVE_CONNECTION_COUNT)
+    workerSource.connectionActive(client)
     super.channelActive(client)
   }
 
@@ -1302,7 +1305,7 @@ class PushDataHandler(val workerSource: WorkerSource) 
extends BaseMessageHandler
    * No further requests will come from this client.
    */
   override def channelInactive(client: TransportClient): Unit = {
-    workerSource.incCounter(WorkerSource.ACTIVE_CONNECTION_COUNT, -1)
+    workerSource.connectionInactive(client)
     super.channelInactive(client)
   }
 }
diff --git 
a/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/Worker.scala 
b/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/Worker.scala
index 5f87d2a52..ed9149914 100644
--- 
a/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/Worker.scala
+++ 
b/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/Worker.scala
@@ -464,6 +464,7 @@ private[celeborn] class Worker(
         commitThreadPool.shutdownNow()
         asyncReplyPool.shutdownNow()
       }
+      workerSource.appActiveConnections.clear()
       partitionsSorter.close(exitKind)
       storageManager.close(exitKind)
       memoryManager.close()
@@ -541,7 +542,7 @@ private[celeborn] class Worker(
       applicationId: String = null): Unit = {
     var resourceConsumptionLabel = userIdentifier.toMap
     if (applicationId != null)
-      resourceConsumptionLabel += (ResourceConsumptionSource.APPLICATION_LABEL 
-> applicationId)
+      resourceConsumptionLabel += (resourceConsumptionSource.applicationLabel 
-> applicationId)
     resourceConsumptionSource.addGauge(
       ResourceConsumptionSource.DISK_FILE_COUNT,
       resourceConsumptionLabel) { () =>
@@ -591,6 +592,7 @@ private[celeborn] class Worker(
           // When the running applications does not contain the application 
corresponding to expired shuffle key,
           // resource consumption source should remove lose application gauges.
           removeAppResourceConsumption(applicationId)
+          removeAppActiveConnection(applicationId)
         }
         logInfo(s"Cleaned up expired shuffle $shuffleKey")
       }
@@ -621,10 +623,14 @@ private[celeborn] class Worker(
       applicationId: String): Unit = {
     resourceConsumptionSource.removeGauge(
       resourceConsumptionName,
-      ResourceConsumptionSource.APPLICATION_LABEL,
+      resourceConsumptionSource.applicationLabel,
       applicationId)
   }
 
+  private def removeAppActiveConnection(applicationId: String): Unit = {
+    workerSource.removeAppActiveConnection(applicationId)
+  }
+
   override def getWorkerInfo: String = {
     val sb = new StringBuilder
     sb.append("====================== WorkerInfo of Worker 
===========================\n")
diff --git 
a/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/WorkerSource.scala
 
b/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/WorkerSource.scala
index fbc4b7d40..edcfc63c4 100644
--- 
a/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/WorkerSource.scala
+++ 
b/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/WorkerSource.scala
@@ -17,13 +17,25 @@
 
 package org.apache.celeborn.service.deploy.worker
 
+import java.util
+import java.util.concurrent.ConcurrentHashMap
+
+import scala.collection.JavaConverters._
+
+import com.google.common.collect.Sets
+
 import org.apache.celeborn.common.CelebornConf
 import org.apache.celeborn.common.metrics.MetricsSystem
 import org.apache.celeborn.common.metrics.source.AbstractSource
+import org.apache.celeborn.common.network.client.TransportClient
+import org.apache.celeborn.common.util.{CollectionUtils, JavaUtils, Utils}
 
 class WorkerSource(conf: CelebornConf) extends AbstractSource(conf, 
MetricsSystem.ROLE_WORKER) {
   override val sourceName = "worker"
 
+  val appActiveConnections: ConcurrentHashMap[String, util.Set[String]] =
+    JavaUtils.newConcurrentHashMap[String, util.Set[String]]
+
   import WorkerSource._
   // add counters
   addCounter(OPEN_STREAM_SUCCESS_COUNT)
@@ -69,6 +81,41 @@ class WorkerSource(conf: CelebornConf) extends 
AbstractSource(conf, MetricsSyste
     val metricNameWithLabel = metricNameWithCustomizedLabels(metricsName, 
Map.empty)
     namedCounters.get(metricNameWithLabel).counter.getCount
   }
+
+  def connectionActive(client: TransportClient): Unit = {
+    appActiveConnections.putIfAbsent(
+      client.getChannel.id().asLongText(),
+      Sets.newConcurrentHashSet[String]())
+    incCounter(ACTIVE_CONNECTION_COUNT, 1)
+  }
+
+  def connectionInactive(client: TransportClient): Unit = {
+    appActiveConnections.remove(client.getChannel.id().asLongText())
+    incCounter(ACTIVE_CONNECTION_COUNT, -1)
+  }
+
+  def recordAppActiveConnection(client: TransportClient, shuffleKey: String): 
Unit = {
+    val applicationIds = 
appActiveConnections.get(client.getChannel.id().asLongText())
+    val applicationId = Utils.splitShuffleKey(shuffleKey)._1
+    if (CollectionUtils.isNotEmpty(applicationIds) && 
!applicationIds.contains(applicationId)) {
+      applicationIds.add(applicationId)
+      addGauge(ACTIVE_CONNECTION_COUNT, Map(applicationLabel -> 
applicationId)) { () =>
+        appActiveConnections.asScala.count { case (_, applicationIds) =>
+          applicationIds.contains(applicationId)
+        }
+      }
+    }
+  }
+
+  def removeAppActiveConnection(applicationId: String): Unit = {
+    appActiveConnections.asScala.foreach { case (_, applicationIds) =>
+      if (applicationIds.contains(applicationId)) {
+        applicationIds.remove(applicationId)
+        removeGauge(ACTIVE_CONNECTION_COUNT, Map(applicationLabel -> 
applicationId))
+      }
+    }
+  }
+
   // start cleaner thread
   startCleaner()
 }
diff --git 
a/worker/src/test/java/org/apache/celeborn/service/deploy/worker/storage/CreditStreamManagerSuiteJ.java
 
b/worker/src/test/java/org/apache/celeborn/service/deploy/worker/storage/CreditStreamManagerSuiteJ.java
index 136ee00bf..9bd69e76b 100644
--- 
a/worker/src/test/java/org/apache/celeborn/service/deploy/worker/storage/CreditStreamManagerSuiteJ.java
+++ 
b/worker/src/test/java/org/apache/celeborn/service/deploy/worker/storage/CreditStreamManagerSuiteJ.java
@@ -80,18 +80,21 @@ public class CreditStreamManagerSuiteJ {
     fileInfo.setBufferSize(1024);
     Consumer<Long> streamIdConsumer = streamId -> Assert.assertTrue(streamId > 
0);
 
+    String shuffleKey = "application_1694674023293_0003-0";
     long registerStream1 =
-        creditStreamManager.registerStream(streamIdConsumer, channel, 0, 1, 1, 
fileInfo);
+        creditStreamManager.registerStream(
+            streamIdConsumer, channel, shuffleKey, 0, 1, 1, fileInfo);
     Assert.assertTrue(registerStream1 > 0);
     Assert.assertEquals(1, creditStreamManager.getStreamsCount());
 
     long registerStream2 =
-        creditStreamManager.registerStream(streamIdConsumer, channel, 0, 1, 1, 
fileInfo);
+        creditStreamManager.registerStream(
+            streamIdConsumer, channel, shuffleKey, 0, 1, 1, fileInfo);
     Assert.assertNotEquals(registerStream1, registerStream2);
     Assert.assertEquals(2, creditStreamManager.getStreamsCount());
 
-    creditStreamManager.registerStream(streamIdConsumer, channel, 0, 1, 1, 
fileInfo);
-    creditStreamManager.registerStream(streamIdConsumer, channel, 0, 1, 1, 
fileInfo);
+    creditStreamManager.registerStream(streamIdConsumer, channel, shuffleKey, 
0, 1, 1, fileInfo);
+    creditStreamManager.registerStream(streamIdConsumer, channel, shuffleKey, 
0, 1, 1, fileInfo);
 
     MapDataPartition mapDataPartition1 =
         
creditStreamManager.getStreams().get(registerStream1).getMapDataPartition();

Reply via email to