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

wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git


The following commit(s) were added to refs/heads/master by this push:
     new 97f5411  Add the implementation of ConfigurationDiscovery on the OAP 
side. (#6220)
97f5411 is described below

commit 97f54114a5e9abff84dae55a44f711f9d8567610
Author: zifeihan <[email protected]>
AuthorDate: Tue Jan 19 14:53:49 2021 +0800

    Add the implementation of ConfigurationDiscovery on the OAP side. (#6220)
---
 CHANGES.md                                         |   1 +
 .../component/command/CommandDeserializer.java     |   2 +
 .../command/ConfigurationDiscoveryCommand.java     |  92 +++++++++++++++++
 apm-protocol/apm-network/src/main/proto            |   2 +-
 docs/en/setup/backend/backend-receivers.md         |   7 +-
 docs/en/setup/backend/configuration-vocabulary.md  |   1 +
 docs/en/setup/backend/dynamic-config.md            |   1 +
 docs/en/setup/service-agent/java-agent/README.md   |   3 +
 .../java-agent/configuration-discovery.md          |  29 ++++++
 oap-server/server-bootstrap/pom.xml                |   5 +
 .../src/main/resources/application.yml             |   5 +
 .../pom.xml                                        |  38 +++++++
 .../discovery/AgentConfigurations.java             |  45 +++++++++
 .../discovery/AgentConfigurationsReader.java       |  75 ++++++++++++++
 .../discovery/AgentConfigurationsTable.java        |  39 ++++++++
 .../discovery/AgentConfigurationsWatcher.java      |  60 +++++++++++
 .../discovery/ConfigurationDiscoveryModule.java    |  28 +++---
 .../ConfigurationDiscoveryModuleConfig.java        |  33 ++++++
 .../discovery/ConfigurationDiscoveryProvider.java  |  92 +++++++++++++++++
 .../grpc/ConfigurationDiscoveryServiceHandler.java |  88 ++++++++++++++++
 ...ywalking.oap.server.library.module.ModuleDefine |  19 ++++
 ...alking.oap.server.library.module.ModuleProvider |  19 ++++
 .../discovery/AgentConfigurationsReaderTest.java   |  56 +++++++++++
 .../discovery/AgentConfigurationsWatcherTest.java  | 111 +++++++++++++++++++++
 .../test/resources/agent-dynamic-configuration.yml |  22 ++++
 oap-server/server-receiver-plugin/pom.xml          |   1 +
 test/e2e/e2e-protocol/src/main/proto               |   2 +-
 27 files changed, 860 insertions(+), 16 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index dbc8b15..387c7ea 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -69,6 +69,7 @@ Release Notes.
 * Fix receiver analysis error count metrics
 * Log collecting and query implementation
 * Support Alarm to feishu
+* Add the implementation of ConfigurationDiscovery on the OAP side.
 
 #### UI
 * Fix un-removed tags in trace query.
diff --git 
a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/CommandDeserializer.java
 
b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/CommandDeserializer.java
index 6465e5f..ff8680b 100644
--- 
a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/CommandDeserializer.java
+++ 
b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/CommandDeserializer.java
@@ -25,6 +25,8 @@ public class CommandDeserializer {
         final String commandName = command.getCommand();
         if (ProfileTaskCommand.NAME.equals(commandName)) {
             return ProfileTaskCommand.DESERIALIZER.deserialize(command);
+        } else if (ConfigurationDiscoveryCommand.NAME.equals(commandName)) {
+            return 
ConfigurationDiscoveryCommand.DESERIALIZER.deserialize(command);
         }
         throw new UnsupportedCommandException(command);
     }
diff --git 
a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/ConfigurationDiscoveryCommand.java
 
b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/ConfigurationDiscoveryCommand.java
new file mode 100644
index 0000000..a1bb63f
--- /dev/null
+++ 
b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/ConfigurationDiscoveryCommand.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.network.trace.component.command;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.skywalking.apm.network.common.v3.Command;
+import org.apache.skywalking.apm.network.common.v3.KeyStringValuePair;
+
+public class ConfigurationDiscoveryCommand extends BaseCommand implements 
Serializable, Deserializable<ConfigurationDiscoveryCommand> {
+    public static final Deserializable<ConfigurationDiscoveryCommand> 
DESERIALIZER = new ConfigurationDiscoveryCommand(
+        "", "", new ArrayList<>());
+    public static final String NAME = 
ConfigurationDiscoveryCommand.class.getSimpleName();
+
+    public static final String UUID_CONST_NAME = "UUID";
+    public static final String SERIAL_NUMBER_CONST_NAME = "SerialNumber";
+
+    /*
+     * If config is unchanged, then could response the same uuid, and config 
is not required.
+     */
+    private String uuid;
+    /*
+     * The configuration of service.
+     */
+    private List<KeyStringValuePair> config;
+
+    public ConfigurationDiscoveryCommand(String serialNumber,
+                                         String uuid,
+                                         List<KeyStringValuePair> config) {
+        super(NAME, serialNumber);
+        this.uuid = uuid;
+        this.config = config;
+    }
+
+    @Override
+    public ConfigurationDiscoveryCommand deserialize(Command command) {
+        String serialNumber = null;
+        String uuid = null;
+        List<KeyStringValuePair> config = new ArrayList<>();
+
+        for (final KeyStringValuePair pair : command.getArgsList()) {
+            if (SERIAL_NUMBER_CONST_NAME.equals(pair.getKey())) {
+                serialNumber = pair.getValue();
+            } else if (UUID_CONST_NAME.equals(pair.getKey())) {
+                uuid = pair.getValue();
+            } else {
+                config.add(pair);
+            }
+        }
+        return new ConfigurationDiscoveryCommand(serialNumber, uuid, config);
+    }
+
+    @Override
+    public Command.Builder serialize() {
+        final Command.Builder builder = commandBuilder();
+        
builder.addArgs(KeyStringValuePair.newBuilder().setKey(UUID_CONST_NAME).setValue(uuid));
+        builder.addAllArgs(config);
+        return builder;
+    }
+
+    public String getUuid() {
+        return uuid;
+    }
+
+    public List<KeyStringValuePair> getConfig() {
+        return config;
+    }
+
+    @Override
+    public String toString() {
+        return "ConfigurationDiscoveryCommand{" +
+            "uuid='" + uuid + '\'' +
+            ", config=" + config +
+            '}';
+    }
+}
diff --git a/apm-protocol/apm-network/src/main/proto 
b/apm-protocol/apm-network/src/main/proto
index ea906c1..101dc50 160000
--- a/apm-protocol/apm-network/src/main/proto
+++ b/apm-protocol/apm-network/src/main/proto
@@ -1 +1 @@
-Subproject commit ea906c1ace2b5eaf19b1c36ead0fd6e1489feaeb
+Subproject commit 101dc50429c98147b1109cb15c8a6c623e751759
diff --git a/docs/en/setup/backend/backend-receivers.md 
b/docs/en/setup/backend/backend-receivers.md
index e248fcf..2840cde 100644
--- a/docs/en/setup/backend/backend-receivers.md
+++ b/docs/en/setup/backend/backend-receivers.md
@@ -17,6 +17,7 @@ We have following receivers, and `default` implementors are 
provided in our Apac
 1. **receiver-meter**. See [details](backend-meter.md).
 1. **receiver-browser**. gRPC services to accept browser performance data and 
error log.
 1. **receiver-log**. gRPC services accept log data.
+1. **configuration-discovery**. gRPC services handle configurationDiscovery.
 
 The sample settings of these receivers should be already in default 
`application.yml`, and also list here
 ```yaml
@@ -66,6 +67,10 @@ receiver-browser:
 receiver-log:
   selector: ${SW_RECEIVER_LOG:default}
   default:
+  
+configuration-discovery:
+  selector: ${SW_CONFIGURATION_DISCOVERY:default}
+  default:
 ```
 
 ## gRPC/HTTP server for receiver
@@ -153,7 +158,7 @@ receiver_jaeger:
   default:
     gRPCHost: ${SW_RECEIVER_JAEGER_HOST:0.0.0.0}
     gRPCPort: ${SW_RECEIVER_JAEGER_PORT:14250}
-``` 
+```
 
 NOTICE, Jaeger receiver is only provided in 
`apache-skywalking-apm-x.y.z.tar.gz` tar.
 
diff --git a/docs/en/setup/backend/configuration-vocabulary.md 
b/docs/en/setup/backend/configuration-vocabulary.md
index b57b5a6..669697b 100644
--- a/docs/en/setup/backend/configuration-vocabulary.md
+++ b/docs/en/setup/backend/configuration-vocabulary.md
@@ -260,6 +260,7 @@ core|default|role|Option values, 
`Mixed/Receiver/Aggregator`. **Receiver** mode
 | exporter | grpc | targetHost | The host of target grpc server for receiving 
export data. | SW_EXPORTER_GRPC_HOST | 127.0.0.1 |
 | - | - | targetPort | The port of target grpc server for receiving export 
data. | SW_EXPORTER_GRPC_PORT | 9870 |
 | health-checker | default | checkIntervalSeconds | The period of check OAP 
internal health status. Unit is second. | SW_HEALTH_CHECKER_INTERVAL_SECONDS | 
5 |
+| configuration-discovery | default | disableMessageDigest | If true, agent 
receives the latest configuration every time even without change. In default, 
OAP uses SHA512 message digest mechanism to detect changes of configuration. | 
SW_DISABLE_MESSAGE_DIGEST | false
 
 ## Notice
 ยน System Environment Variable name could be declared and changed in the 
application.yml. The names listed here,
diff --git a/docs/en/setup/backend/dynamic-config.md 
b/docs/en/setup/backend/dynamic-config.md
index 3837370..5f94200 100755
--- a/docs/en/setup/backend/dynamic-config.md
+++ b/docs/en/setup/backend/dynamic-config.md
@@ -13,6 +13,7 @@ Right now, SkyWalking supports following dynamic 
configurations.
 |core.default.endpoint-name-grouping| The endpoint name grouping setting, will 
override `endpoint-name-grouping.yml`. | same as 
[`endpoint-name-grouping.yml`](endpoint-grouping-rules.md) |
 |agent-analyzer.default.sampleRate| Trace sampling , override 
`receiver-trace/default/sampleRate` of `application.yml`. | 10000 |
 |agent-analyzer.default.slowTraceSegmentThreshold| Setting this threshold 
about the latency would make the slow trace segments sampled if they cost more 
time, even the sampling mechanism activated. The default value is `-1`, which 
means would not sample slow traces. Unit, millisecond. override 
`receiver-trace/default/slowTraceSegmentThreshold` of `application.yml`. | -1 |
+|configuration-discovery.default.agentConfigurations| The 
ConfigurationDiscovery settings | look at 
[`configuration-discovery.md`](../service-agent/java-agent/configuration-discovery.md)
 |
 
 This feature depends on upstream service, so it is **DISABLED** by default.
 
diff --git a/docs/en/setup/service-agent/java-agent/README.md 
b/docs/en/setup/service-agent/java-agent/README.md
index f2811d6..5faa98b 100755
--- a/docs/en/setup/service-agent/java-agent/README.md
+++ b/docs/en/setup/service-agent/java-agent/README.md
@@ -164,6 +164,9 @@ property key | Description | Default |
 `plugin.toolkit.log.grpc.reporter.max_message_size` | Specify the maximum size 
of log data for grpc client to report to. | `10485760` |
 `plugin.toolkit.log.grpc.reporter.upstream_timeout` | How long grpc client 
will timeout in sending data to upstream. Unit is second.|`30` seconds|
 
+## Dynamic Configurations
+All configurations above are static, if you need to change some agent settings 
at runtime, please read [CDS - Configuration Discovery Service 
document](configuration-discovery.md) for more details.
+
 ## Optional Plugins
 Java agent plugins are all pluggable. Optional plugins could be provided in 
`optional-plugins` folder under agent or 3rd party repositories.
 For using these plugins, you need to put the target plugin jar file into 
`/plugins`.
diff --git a/docs/en/setup/service-agent/java-agent/configuration-discovery.md 
b/docs/en/setup/service-agent/java-agent/configuration-discovery.md
new file mode 100644
index 0000000..ffd6bc1
--- /dev/null
+++ b/docs/en/setup/service-agent/java-agent/configuration-discovery.md
@@ -0,0 +1,29 @@
+# CDS - Configuration Discovery Service
+
+CDS - Configuration Discovery Service provides the dynamic configuration for 
the agent, defined in 
[gRPC](https://github.com/apache/skywalking-data-collect-protocol/blob/master/language-agent/ConfigurationDiscoveryService.proto).
+
+## Configuration Format
+
+The configuration content includes the service name and their configs. The 
+```yml
+configurations:
+  //service name
+  serviceA:
+    // Configurations of service A
+    // Key and Value are determined by the agent side.
+    // Check the agent setup doc for all available configurations.
+    key1: value1
+    key2: value2
+    ...
+  serviceB:
+    ...
+```
+
+## Available key(s) and value(s) in Java Agent.
+Java agent supports the following dynamic configurations.
+
+|        Config Key         |                      Value Description           
            | Value Format Example  | Required Plugin(s) |
+| :-----------------------: | 
:----------------------------------------------------------: | 
:-------------------: | :----------------: |
+| agent.sample_n_per_3_secs |          The number of sampled traces per 3 
seconds          |          -1           | - |
+
+* `Required plugin(s)`, the configuration affects only when the required 
plugins activated.
diff --git a/oap-server/server-bootstrap/pom.xml 
b/oap-server/server-bootstrap/pom.xml
index efec58b..b4e0453 100644
--- a/oap-server/server-bootstrap/pom.xml
+++ b/oap-server/server-bootstrap/pom.xml
@@ -131,6 +131,11 @@
             <artifactId>skywalking-log-recevier-plugin</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>configuration-discovery-receiver-plugin</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <!-- receiver module -->
 
         <!-- fetcher module -->
diff --git a/oap-server/server-bootstrap/src/main/resources/application.yml 
b/oap-server/server-bootstrap/src/main/resources/application.yml
index 7af29a4..18ab546 100755
--- a/oap-server/server-bootstrap/src/main/resources/application.yml
+++ b/oap-server/server-bootstrap/src/main/resources/application.yml
@@ -413,3 +413,8 @@ health-checker:
   selector: ${SW_HEALTH_CHECKER:-}
   default:
     checkIntervalSeconds: ${SW_HEALTH_CHECKER_INTERVAL_SECONDS:5}
+
+configuration-discovery:
+  selector: ${SW_CONFIGURATION_DISCOVERY:-}
+  default:
+    disableMessageDigest: ${SW_DISABLE_MESSAGE_DIGEST:false}
diff --git 
a/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/pom.xml
 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/pom.xml
new file mode 100644
index 0000000..4aec867
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/pom.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <parent>
+        <artifactId>server-receiver-plugin</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>8.4.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>configuration-discovery-receiver-plugin</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>skywalking-sharing-server-plugin</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git 
a/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurations.java
 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurations.java
new file mode 100644
index 0000000..24349e8
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurations.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.recevier.configuration.discovery;
+
+import java.util.Map;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+/**
+ * Dynamic configuration items, save the dynamic configuration of the agent 
corresponding to the service.
+ */
+@Setter
+@Getter
+@ToString
+public class AgentConfigurations {
+    private String service;
+    private Map<String, String> configuration;
+    /**
+     * The uuid is calculated by the dynamic configuration of the service.
+     */
+    private volatile String uuid;
+
+    public AgentConfigurations(final String service, final Map<String, String> 
configuration, final String uuid) {
+        this.service = service;
+        this.configuration = configuration;
+        this.uuid = uuid;
+    }
+}
diff --git 
a/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurationsReader.java
 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurationsReader.java
new file mode 100644
index 0000000..b9ebd2b
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurationsReader.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.recevier.configuration.discovery;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.SafeConstructor;
+
+/**
+ * Used to parse the String configuration to AgentConfigurations.
+ */
+@Slf4j
+public class AgentConfigurationsReader {
+    private Map yamlData;
+
+    public AgentConfigurationsReader(InputStream inputStream) {
+        Yaml yaml = new Yaml(new SafeConstructor());
+        yamlData = (Map) yaml.load(inputStream);
+    }
+
+    public AgentConfigurationsReader(Reader io) {
+        Yaml yaml = new Yaml(new SafeConstructor());
+        yamlData = (Map) yaml.load(io);
+    }
+
+    public AgentConfigurationsTable readAgentConfigurationsTable() {
+        AgentConfigurationsTable agentConfigurationsTable = new 
AgentConfigurationsTable();
+        try {
+            if (Objects.nonNull(yamlData)) {
+                Map configurationsData = (Map) yamlData.get("configurations");
+                if (configurationsData != null) {
+                    configurationsData.forEach((k, v) -> {
+                        Map map = (Map) v;
+                        StringBuilder serviceConfigStr = new StringBuilder();
+                        Map<String, String> config = new HashMap<>(map.size());
+                        map.forEach((key, value) -> {
+                            config.put(key.toString(), value.toString());
+
+                            
serviceConfigStr.append(key.toString()).append(":").append(value.toString());
+                        });
+                        AgentConfigurations agentConfigurations = new 
AgentConfigurations(
+                            k.toString(), config, 
DigestUtils.sha512Hex(serviceConfigStr.toString()));
+                        agentConfigurationsTable.getAgentConfigurationsCache()
+                                                
.put(agentConfigurations.getService(), agentConfigurations);
+                    });
+                }
+            }
+        } catch (Exception e) {
+            log.error("Read ConfigurationDiscovery configurations error.", e);
+        }
+        return agentConfigurationsTable;
+    }
+}
diff --git 
a/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurationsTable.java
 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurationsTable.java
new file mode 100644
index 0000000..7d7666c
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurationsTable.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.recevier.configuration.discovery;
+
+import java.util.HashMap;
+import java.util.Map;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+/**
+ * Dynamic configuration items, save the dynamic configuration of the agent 
corresponding to the service.
+ */
+@Setter
+@Getter
+@ToString
+public class AgentConfigurationsTable {
+    private Map<String, AgentConfigurations> agentConfigurationsCache;
+
+    public AgentConfigurationsTable() {
+        this.agentConfigurationsCache = new HashMap<>();
+    }
+}
diff --git 
a/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurationsWatcher.java
 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurationsWatcher.java
new file mode 100644
index 0000000..a7d95e9
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurationsWatcher.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.recevier.configuration.discovery;
+
+import java.io.StringReader;
+import org.apache.skywalking.oap.server.configuration.api.ConfigChangeWatcher;
+import org.apache.skywalking.oap.server.core.Const;
+import org.apache.skywalking.oap.server.library.module.ModuleProvider;
+
+/**
+ * AgentConfigurationsWatcher used to handle dynamic configuration changes.
+ */
+public class AgentConfigurationsWatcher extends ConfigChangeWatcher {
+    private volatile String settingsString;
+    private volatile AgentConfigurationsTable agentConfigurationsTable;
+
+    public AgentConfigurationsWatcher(ModuleProvider provider) {
+        super(ConfigurationDiscoveryModule.NAME, provider, 
"agentConfigurations");
+        this.settingsString = Const.EMPTY_STRING;
+        this.agentConfigurationsTable = new AgentConfigurationsTable();
+    }
+
+    @Override
+    public void notify(ConfigChangeEvent value) {
+        if (value.getEventType().equals(EventType.DELETE)) {
+            settingsString = Const.EMPTY_STRING;
+            this.agentConfigurationsTable = new AgentConfigurationsTable();
+        } else {
+            settingsString = value.getNewValue();
+            AgentConfigurationsReader agentConfigurationsReader =
+                new AgentConfigurationsReader(new 
StringReader(value.getNewValue()));
+            this.agentConfigurationsTable = 
agentConfigurationsReader.readAgentConfigurationsTable();
+        }
+    }
+
+    @Override
+    public String value() {
+        return settingsString;
+    }
+
+    public AgentConfigurations getAgentConfigurations(String service) {
+        return 
agentConfigurationsTable.getAgentConfigurationsCache().get(service);
+    }
+}
diff --git 
a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/CommandDeserializer.java
 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/ConfigurationDiscoveryModule.java
similarity index 50%
copy from 
apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/CommandDeserializer.java
copy to 
oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/ConfigurationDiscoveryModule.java
index 6465e5f..bdd644b 100644
--- 
a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/CommandDeserializer.java
+++ 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/ConfigurationDiscoveryModule.java
@@ -6,27 +6,29 @@
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
  */
 
-package org.apache.skywalking.apm.network.trace.component.command;
+package org.apache.skywalking.oap.server.recevier.configuration.discovery;
 
-import org.apache.skywalking.apm.network.common.v3.Command;
+import org.apache.skywalking.oap.server.library.module.ModuleDefine;
 
-public class CommandDeserializer {
+public class ConfigurationDiscoveryModule extends ModuleDefine {
+    public static final String NAME = "configuration-discovery";
 
-    public static BaseCommand deserialize(final Command command) {
-        final String commandName = command.getCommand();
-        if (ProfileTaskCommand.NAME.equals(commandName)) {
-            return ProfileTaskCommand.DESERIALIZER.deserialize(command);
-        }
-        throw new UnsupportedCommandException(command);
+    public ConfigurationDiscoveryModule() {
+        super(NAME);
     }
 
-}
+    @Override
+    public Class[] services() {
+        return new Class[0];
+    }
+}
\ No newline at end of file
diff --git 
a/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/ConfigurationDiscoveryModuleConfig.java
 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/ConfigurationDiscoveryModuleConfig.java
new file mode 100644
index 0000000..0a9c164
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/ConfigurationDiscoveryModuleConfig.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.recevier.configuration.discovery;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.skywalking.oap.server.library.module.ModuleConfig;
+
+public class ConfigurationDiscoveryModuleConfig extends ModuleConfig {
+    /**
+     *  If true, agent receives the latest configuration every time even 
without change. 
+     *  In default, OAP uses SHA512 message digest mechanism to detect changes 
of configuration. 
+     */
+    @Setter
+    @Getter
+    private boolean disableMessageDigest = false;
+}
diff --git 
a/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/ConfigurationDiscoveryProvider.java
 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/ConfigurationDiscoveryProvider.java
new file mode 100644
index 0000000..603065a
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/ConfigurationDiscoveryProvider.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.recevier.configuration.discovery;
+
+import org.apache.skywalking.oap.server.configuration.api.ConfigurationModule;
+import 
org.apache.skywalking.oap.server.configuration.api.DynamicConfigurationService;
+import org.apache.skywalking.oap.server.core.server.GRPCHandlerRegister;
+import org.apache.skywalking.oap.server.library.module.ModuleConfig;
+import org.apache.skywalking.oap.server.library.module.ModuleDefine;
+import org.apache.skywalking.oap.server.library.module.ModuleProvider;
+import org.apache.skywalking.oap.server.library.module.ModuleStartException;
+import 
org.apache.skywalking.oap.server.library.module.ServiceNotProvidedException;
+import 
org.apache.skywalking.oap.server.receiver.sharing.server.SharingServerModule;
+import 
org.apache.skywalking.oap.server.recevier.configuration.discovery.handler.grpc.ConfigurationDiscoveryServiceHandler;
+
+public class ConfigurationDiscoveryProvider extends ModuleProvider {
+
+    private AgentConfigurationsWatcher agentConfigurationsWatcher;
+    private ConfigurationDiscoveryModuleConfig 
configurationDiscoveryModuleConfig;
+
+    @Override
+    public String name() {
+        return "default";
+    }
+
+    @Override
+    public Class<? extends ModuleDefine> module() {
+        return ConfigurationDiscoveryModule.class;
+    }
+
+    public ConfigurationDiscoveryProvider() {
+        configurationDiscoveryModuleConfig = new 
ConfigurationDiscoveryModuleConfig();
+    }
+
+    @Override
+    public ModuleConfig createConfigBeanIfAbsent() {
+        return configurationDiscoveryModuleConfig;
+    }
+
+    @Override
+    public void prepare() throws ServiceNotProvidedException, 
ModuleStartException {
+        agentConfigurationsWatcher = new AgentConfigurationsWatcher(this);
+    }
+
+    @Override
+    public void start() throws ServiceNotProvidedException, 
ModuleStartException {
+        DynamicConfigurationService dynamicConfigurationService = 
getManager().find(ConfigurationModule.NAME)
+                                                                              
.provider()
+                                                                              
.getService(
+                                                                               
   DynamicConfigurationService.class);
+        
dynamicConfigurationService.registerConfigChangeWatcher(agentConfigurationsWatcher);
+
+        /*
+         * Register ConfigurationDiscoveryServiceHandler to process gRPC 
requests for ConfigurationDiscovery.
+         */
+        GRPCHandlerRegister grpcHandlerRegister = 
getManager().find(SharingServerModule.NAME)
+                                                              .provider()
+                                                              
.getService(GRPCHandlerRegister.class);
+        grpcHandlerRegister.addHandler(new 
ConfigurationDiscoveryServiceHandler(
+            agentConfigurationsWatcher,
+            configurationDiscoveryModuleConfig.isDisableMessageDigest()
+        ));
+    }
+
+    @Override
+    public void notifyAfterCompleted() throws ServiceNotProvidedException, 
ModuleStartException {
+    }
+
+    @Override
+    public String[] requiredModules() {
+        return new String[] {
+            ConfigurationModule.NAME,
+            SharingServerModule.NAME
+        };
+    }
+}
diff --git 
a/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/handler/grpc/ConfigurationDiscoveryServiceHandler.java
 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/handler/grpc/ConfigurationDiscoveryServiceHandler.java
new file mode 100644
index 0000000..85d8ab8
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/handler/grpc/ConfigurationDiscoveryServiceHandler.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package 
org.apache.skywalking.oap.server.recevier.configuration.discovery.handler.grpc;
+
+import com.google.common.collect.Lists;
+import io.grpc.stub.StreamObserver;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+import lombok.extern.slf4j.Slf4j;
+import 
org.apache.skywalking.apm.network.agent.dynamic.configuration.v3.ConfigurationDiscoveryServiceGrpc;
+import 
org.apache.skywalking.apm.network.agent.dynamic.configuration.v3.ConfigurationSyncRequest;
+import org.apache.skywalking.apm.network.common.v3.Commands;
+import org.apache.skywalking.apm.network.common.v3.KeyStringValuePair;
+import 
org.apache.skywalking.apm.network.trace.component.command.ConfigurationDiscoveryCommand;
+import org.apache.skywalking.oap.server.library.server.grpc.GRPCHandler;
+import 
org.apache.skywalking.oap.server.recevier.configuration.discovery.AgentConfigurations;
+import 
org.apache.skywalking.oap.server.recevier.configuration.discovery.AgentConfigurationsWatcher;
+
+/**
+ * Provide query agent dynamic configuration, through the gRPC protocol,
+ */
+@Slf4j
+public class ConfigurationDiscoveryServiceHandler extends 
ConfigurationDiscoveryServiceGrpc.ConfigurationDiscoveryServiceImplBase 
implements GRPCHandler {
+
+    private final AgentConfigurationsWatcher agentConfigurationsWatcher;
+
+    /**
+     * If the current configuration is true, the requestId and uuid will not 
be judged, and the dynamic configuration of
+     * the service corresponding to the agent will be returned directly
+     */
+    private boolean disableMessageDigest = false;
+
+    public ConfigurationDiscoveryServiceHandler(AgentConfigurationsWatcher 
agentConfigurationsWatcher,
+                                                boolean disableMessageDigest) {
+        this.agentConfigurationsWatcher = agentConfigurationsWatcher;
+        this.disableMessageDigest = disableMessageDigest;
+    }
+
+    /*
+     * Process the request for querying the dynamic configuration of the agent.
+     * If there is agent dynamic configuration information corresponding to 
the service,
+     * the ConfigurationDiscoveryCommand is returned to represent the dynamic 
configuration information.
+     */
+    @Override
+    public void fetchConfigurations(final ConfigurationSyncRequest request,
+                                    final StreamObserver<Commands> 
responseObserver) {
+        Commands.Builder commandsBuilder = Commands.newBuilder();
+
+        AgentConfigurations agentConfigurations = 
agentConfigurationsWatcher.getAgentConfigurations(
+            request.getService());
+        if (null != agentConfigurations) {
+            if (disableMessageDigest || 
!Objects.equals(agentConfigurations.getUuid(), request.getUuid())) {
+                ConfigurationDiscoveryCommand configurationDiscoveryCommand =
+                    newAgentDynamicConfigCommand(agentConfigurations);
+                
commandsBuilder.addCommands(configurationDiscoveryCommand.serialize().build());
+            }
+        }
+        responseObserver.onNext(commandsBuilder.build());
+        responseObserver.onCompleted();
+    }
+
+    public ConfigurationDiscoveryCommand 
newAgentDynamicConfigCommand(AgentConfigurations agentConfigurations) {
+        List<KeyStringValuePair> configurationList = Lists.newArrayList();
+        agentConfigurations.getConfiguration().forEach((k, v) -> {
+            KeyStringValuePair.Builder builder = 
KeyStringValuePair.newBuilder().setKey(k).setValue(v);
+            configurationList.add(builder.build());
+        });
+        return new ConfigurationDiscoveryCommand(
+            UUID.randomUUID().toString(), agentConfigurations.getUuid(), 
configurationList);
+    }
+}
diff --git 
a/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine
 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine
new file mode 100644
index 0000000..ca0bbb5
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+
+org.apache.skywalking.oap.server.recevier.configuration.discovery.ConfigurationDiscoveryModule
\ No newline at end of file
diff --git 
a/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
new file mode 100644
index 0000000..3a34f7e
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+
+org.apache.skywalking.oap.server.recevier.configuration.discovery.ConfigurationDiscoveryProvider
\ No newline at end of file
diff --git 
a/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurationsReaderTest.java
 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurationsReaderTest.java
new file mode 100644
index 0000000..49485c3
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurationsReaderTest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.recevier.configuration.discovery;
+
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class AgentConfigurationsReaderTest {
+    @Test
+    public void testReadAgentConfigurations() {
+        AgentConfigurationsReader reader = new AgentConfigurationsReader(
+            
this.getClass().getClassLoader().getResourceAsStream("agent-dynamic-configuration.yml"));
+
+        Map<String, AgentConfigurations> configurationCache = 
reader.readAgentConfigurationsTable()
+                                                                    
.getAgentConfigurationsCache();
+        Assert.assertEquals(2, configurationCache.size());
+        AgentConfigurations agentConfigurations0 = 
configurationCache.get("serviceA");
+        Assert.assertEquals("serviceA", agentConfigurations0.getService());
+        Assert.assertEquals(2, agentConfigurations0.getConfiguration().size());
+        Assert.assertEquals("1000", 
agentConfigurations0.getConfiguration().get("trace.sample_rate"));
+        Assert.assertEquals(
+            "/api/seller/seller/*", 
agentConfigurations0.getConfiguration().get("trace.ignore_path"));
+        Assert.assertEquals(
+            
"92670f1ccbdee60e14ffc054d70a5cf3f93f6b5fb1adb83b10bea4fec79b96e7bc5e7b188e231428853721ded42ec756663947316065617f3cfdf51d6dfc8da6",
+            agentConfigurations0.getUuid()
+        );
+
+        AgentConfigurations agentConfigurations1 = 
configurationCache.get("serviceB");
+        Assert.assertEquals("serviceB", agentConfigurations1.getService());
+        Assert.assertEquals(2, agentConfigurations1.getConfiguration().size());
+        Assert.assertEquals("1000", 
agentConfigurations1.getConfiguration().get("trace.sample_rate"));
+        Assert.assertEquals(
+            "/api/seller/seller/*", 
agentConfigurations1.getConfiguration().get("trace.ignore_path"));
+        Assert.assertEquals(
+            
"92670f1ccbdee60e14ffc054d70a5cf3f93f6b5fb1adb83b10bea4fec79b96e7bc5e7b188e231428853721ded42ec756663947316065617f3cfdf51d6dfc8da6",
+            agentConfigurations0.getUuid()
+        );
+    }
+}
diff --git 
a/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurationsWatcherTest.java
 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurationsWatcherTest.java
new file mode 100644
index 0000000..2c9c2f0
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/recevier/configuration/discovery/AgentConfigurationsWatcherTest.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.recevier.configuration.discovery;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Map;
+import org.apache.skywalking.oap.server.configuration.api.ConfigChangeWatcher;
+import org.apache.skywalking.oap.server.library.util.ResourceUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.powermock.reflect.Whitebox;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.spy;
+
+public class AgentConfigurationsWatcherTest {
+    @Spy
+    private AgentConfigurationsWatcher agentConfigurationsWatcher = new 
AgentConfigurationsWatcher(null);
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void testConfigModifyEvent() throws IOException {
+        AgentConfigurationsTable agentConfigurationsTable = 
Whitebox.getInternalState(
+            agentConfigurationsWatcher, "agentConfigurationsTable");
+        
assertTrue(agentConfigurationsTable.getAgentConfigurationsCache().isEmpty());
+
+        Reader reader = ResourceUtils.read("agent-dynamic-configuration.yml");
+        char[] chars = new char[1024 * 1024];
+        int length = reader.read(chars);
+
+        agentConfigurationsWatcher.notify(new 
ConfigChangeWatcher.ConfigChangeEvent(
+            new String(chars, 0, length),
+            ConfigChangeWatcher.EventType.MODIFY
+        ));
+
+        AgentConfigurationsTable modifyAgentConfigurationsTable = 
Whitebox.getInternalState(
+            agentConfigurationsWatcher, "agentConfigurationsTable");
+        Map<String, AgentConfigurations> configurationCache = 
modifyAgentConfigurationsTable.getAgentConfigurationsCache();
+        Assert.assertEquals(2, configurationCache.size());
+        AgentConfigurations agentConfigurations0 = 
configurationCache.get("serviceA");
+        Assert.assertEquals("serviceA", agentConfigurations0.getService());
+        Assert.assertEquals(2, agentConfigurations0.getConfiguration().size());
+        Assert.assertEquals("1000", 
agentConfigurations0.getConfiguration().get("trace.sample_rate"));
+        Assert.assertEquals(
+            "/api/seller/seller/*", 
agentConfigurations0.getConfiguration().get("trace.ignore_path"));
+        Assert.assertEquals(
+            
"92670f1ccbdee60e14ffc054d70a5cf3f93f6b5fb1adb83b10bea4fec79b96e7bc5e7b188e231428853721ded42ec756663947316065617f3cfdf51d6dfc8da6",
+            agentConfigurations0.getUuid()
+        );
+
+        AgentConfigurations agentConfigurations1 = 
configurationCache.get("serviceB");
+        Assert.assertEquals("serviceB", agentConfigurations1.getService());
+        Assert.assertEquals(2, agentConfigurations1.getConfiguration().size());
+        Assert.assertEquals("1000", 
agentConfigurations1.getConfiguration().get("trace.sample_rate"));
+        Assert.assertEquals(
+            "/api/seller/seller/*", 
agentConfigurations1.getConfiguration().get("trace.ignore_path"));
+        Assert.assertEquals(
+            
"92670f1ccbdee60e14ffc054d70a5cf3f93f6b5fb1adb83b10bea4fec79b96e7bc5e7b188e231428853721ded42ec756663947316065617f3cfdf51d6dfc8da6",
+            agentConfigurations0.getUuid()
+        );
+    }
+
+    @Test
+    public void testConfigDeleteEvent() throws IOException {
+        Reader reader = ResourceUtils.read("agent-dynamic-configuration.yml");
+        agentConfigurationsWatcher = spy(new AgentConfigurationsWatcher(null));
+
+        Whitebox.setInternalState(
+            agentConfigurationsWatcher, "agentConfigurationsTable",
+            new 
AgentConfigurationsReader(reader).readAgentConfigurationsTable()
+        );
+
+        agentConfigurationsWatcher.notify(
+            new ConfigChangeWatcher.ConfigChangeEvent("whatever", 
ConfigChangeWatcher.EventType.DELETE));
+
+        AgentConfigurationsTable agentConfigurationsTable = 
Whitebox.getInternalState(
+            agentConfigurationsWatcher, "agentConfigurationsTable");
+        Map<String, AgentConfigurations> configurationCache = 
agentConfigurationsTable.getAgentConfigurationsCache();
+
+        Assert.assertEquals(0, configurationCache.size());
+        AgentConfigurations agentConfigurations0 = 
configurationCache.get("serviceA");
+        AgentConfigurations agentConfigurations1 = 
configurationCache.get("serviceB");
+
+        Assert.assertNull(null, agentConfigurations0);
+        Assert.assertNull(null, agentConfigurations1);
+    }
+}
\ No newline at end of file
diff --git 
a/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/test/resources/agent-dynamic-configuration.yml
 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/test/resources/agent-dynamic-configuration.yml
new file mode 100644
index 0000000..49bb7a1
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/configuration-discovery-receiver-plugin/src/test/resources/agent-dynamic-configuration.yml
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+configurations:
+  serviceA:
+    trace.sample_rate: 1000
+    trace.ignore_path: /api/seller/seller/*
+  serviceB:
+    trace.sample_rate: 1000
+    trace.ignore_path: /api/seller/seller/*
\ No newline at end of file
diff --git a/oap-server/server-receiver-plugin/pom.xml 
b/oap-server/server-receiver-plugin/pom.xml
index 7a4ecdc..b4e61f5 100644
--- a/oap-server/server-receiver-plugin/pom.xml
+++ b/oap-server/server-receiver-plugin/pom.xml
@@ -43,6 +43,7 @@
         <module>skywalking-meter-receiver-plugin</module>
         <module>skywalking-browser-receiver-plugin</module>
         <module>skywalking-log-recevier-plugin</module>
+        <module>configuration-discovery-receiver-plugin</module>
     </modules>
 
     <dependencies>
diff --git a/test/e2e/e2e-protocol/src/main/proto 
b/test/e2e/e2e-protocol/src/main/proto
index ea906c1..101dc50 160000
--- a/test/e2e/e2e-protocol/src/main/proto
+++ b/test/e2e/e2e-protocol/src/main/proto
@@ -1 +1 @@
-Subproject commit ea906c1ace2b5eaf19b1c36ead0fd6e1489feaeb
+Subproject commit 101dc50429c98147b1109cb15c8a6c623e751759

Reply via email to