Add healthcheck to provider (#264)

diff --git a/.github/workflows/dubbo-2.yml b/.github/workflows/dubbo-2.yml
index 4f2732d..88677be 100644
--- a/.github/workflows/dubbo-2.yml
+++ b/.github/workflows/dubbo-2.yml
@@ -4,23 +4,30 @@
   pull_request:
     paths:
       - "**"
+      - "!**/*.md"
+      - "!docs/**"
   push:
     paths:
       - '**'
+      - "!**/*.md"
+      - "!docs/**"
+  workflow_dispatch:
 
 env:
   FORK_COUNT: 2
   FAIL_FAST: 0
   SHOW_ERROR_DETAIL: 1
-  BUILD_OPTS: -U --batch-mode --no-transfer-progress --settings ${{github.workspace}}/.mvn/settings.xml clean package dependency:copy-dependencies -DskipTests
+  BUILD_OPTS: -U --batch-mode --no-transfer-progress --settings ${{github.workspace}}/.mvn/settings.xml
+    -Dmaven.wagon.http.retryHandler.count=3 clean package dependency:copy-dependencies -DskipTests
   #multi-version size limit
   VERSIONS_LIMIT: 4
+  #candidate versions (the dubbo snapshot version will be extracted from pom.xml and appended before CANDIDATE_VERSIONS )
   CANDIDATE_VERSIONS: '
-    dubbo.version:2.7.9-SNAPSHOT;
     spring.version:4.3.30.RELEASE;
     spring-boot.version:1.5.22.RELEASE;
     spring-boot.version:2.4.1;
     '
+  DUBBO_REF: master
 
 jobs:
   build-samples:
@@ -35,9 +42,9 @@
         uses: actions/cache@v2
         with:
           path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+          key: ${{ runner.os }}-samples-maven-${{ hashFiles('**/pom.xml') }}
           restore-keys: |
-            ${{ runner.os }}-maven-
+            ${{ runner.os }}-samples-maven-
       - name: Set up JDK ${{matrix.java}}
         uses: actions/setup-java@v1
         with:
@@ -50,56 +57,60 @@
     runs-on: ubuntu-latest
     strategy:
       fail-fast: false
+    # Map a step output to a job output
+    outputs:
+      commit_id: ${{ steps.git-checker.outputs.commit_id }}
+      cache-hit: ${{ steps.dubbocache.outputs.cache-hit }}
     steps:
       - uses: actions/checkout@v2
         with:
           repository: 'apache/dubbo'
-          ref: master
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-      - name: Get last git commit hash
-        id: git-hash
+          ref: ${{env.DUBBO_REF}}
+      - name: Get commit id and dubbo version
+        id: git-checker
         run: |
           #compare dubbo commit id
           last_commit_id=`git log --format="%H" -n 1`
           echo "::set-output name=commit_id::$last_commit_id"
-          if [ -f ~/.m2/repository/org/apache/dubbo/dubbo-commit-id ];then
-            cache_commit_id=`cat ~/.m2/repository/org/apache/dubbo/dubbo-commit-id`
-          fi
-          if [ "$last_commit_id" == "$cache_commit_id" ];then
-            echo "::set-output name=cache-hit::true"
-          else
-            echo "::set-output name=cache-hit::false"
-          fi
+          echo "commit_id: $last_commit_id"
+          # Calculate Dubbo Version
+          REVISION=`awk '/<revision>[^<]+<\/revision>/{gsub(/<revision>|<\/revision>/,"",$1);print $1;exit;}' pom.xml`
+          mkdir dubbo-version
+          echo $REVISION > dubbo-version/dubbo-version
+          echo "dubbo version: $REVISION"
+      - name: Upload Dubbo version
+        uses: actions/upload-artifact@v2
+        with:
+          name: dubbo-version
+          path: dubbo-version
+      - name: Dubbo cache
+        id: dubbocache
+        uses: actions/cache@v2
+        with:
+          path: ~/.m2/repository/org/apache/dubbo
+          key: ${{ runner.os }}-dubbo-snapshot-${{steps.git-checker.outputs.commit_id}}
       - name: Cache local Maven repository
-        if: steps.git-hash.outputs.cache-hit != 'true'
+        if: steps.dubbocache.outputs.cache-hit != 'true'
         uses: actions/cache@v2
         with:
           path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+          key: ${{ runner.os }}-dubbo-${{env.DUBBO_REF}}-maven-${{ hashFiles('**/pom.xml') }}
           restore-keys: |
-            ${{ runner.os }}-maven-
+            ${{ runner.os }}-dubbo-${{env.DUBBO_REF}}-maven-
       - name: Set up JDK 8
-        if: steps.git-hash.outputs.cache-hit != 'true'
+        if: steps.dubbocache.outputs.cache-hit != 'true'
         uses: actions/setup-java@v1
         with:
           java-version: 8
       - name: Build dubbo
-        if: steps.git-hash.outputs.cache-hit != 'true'
+        if: steps.dubbocache.outputs.cache-hit != 'true'
         run: |
           ./mvnw -U --batch-mode --no-transfer-progress  clean install -Dmaven.test.skip=true -Dmaven.test.skip.exec=true
-      - name: Update commit id
-        run: |
-          echo commit_id: ${{steps.git-hash.outputs.commit_id}}
-          echo ${{steps.git-hash.outputs.commit_id}} > ~/.m2/repository/org/apache/dubbo/dubbo-commit-id
 
   prepare_test:
     runs-on: ubuntu-latest
     env:
-      #'JOB_COUNT' MUST match needs job list of 'test_result' job
+      #'JOB_COUNT' MUST match 'job_id' list of 'testjob'
       JOB_COUNT: 5
     steps:
       - uses: actions/checkout@v1
@@ -112,9 +123,65 @@
           name: test-list
           path: test/jobs
 
+  testjob:
+    needs: [prepare_test, build-dubbo]
+    runs-on: ubuntu-latest
+    env:
+      JAVA_VER: ${{matrix.java}}
+      TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
+    strategy:
+      fail-fast: false
+      matrix:
+        java: [8, 11]
+        #testjob id list MUST match 'JOB_COUNT' of 'prepare_test'
+        job_id: [1,2,3,4,5]
+    steps:
+      - uses: actions/checkout@v1
+      - name: Set up JDK ${{matrix.java}}
+        uses: actions/setup-java@v1
+        with:
+          java-version: ${{matrix.java}}
+      - name: Cache local Maven repository
+        uses: actions/cache@v2
+        with:
+          path: ~/.m2/repository
+          key: ${{ runner.os }}-samples-maven-${{ hashFiles('**/pom.xml') }}
+          restore-keys: |
+            ${{ runner.os }}-samples-maven-
+      - name: Dubbo cache
+        uses: actions/cache@v2
+        with:
+          path: ~/.m2/repository/org/apache/dubbo
+          key: ${{ runner.os }}-dubbo-snapshot-${{needs.build-dubbo.outputs.commit_id}}
+      - name: Download test list
+        uses: actions/download-artifact@v2
+        with:
+          name: test-list
+          path: test/jobs/
+      - name: Download Dubbo version
+        uses: actions/download-artifact@v2
+        with:
+          name: dubbo-version
+          path: dubbo-version
+      - name: Init Candidate Versions
+        run: |
+          DUBBO_VERSION=`cat dubbo-version/dubbo-version`
+          CANDIDATE_VERSIONS="dubbo.version:$DUBBO_VERSION;$CANDIDATE_VERSIONS"
+          echo "CANDIDATE_VERSIONS=$CANDIDATE_VERSIONS" >> $GITHUB_ENV
+      - name: Build test image
+        run: |
+          cd test && bash ./build-test-image.sh
+      - name: Run tests
+        run: cd test && bash ./run-tests.sh
+      - name: Upload test result
+        if: always()
+        uses: actions/upload-artifact@v2
+        with:
+          name: test-result
+          path: test/jobs/*-result*
+
   test_result:
-    #testjob list MUST match 'JOB_COUNT' of 'prepare_test' job
-    needs: [testjob_1,testjob_2,testjob_3,testjob_4,testjob_5]
+    needs: [testjob]
     if: always()
     runs-on: ubuntu-latest
     strategy:
@@ -132,238 +199,3 @@
           path: test/jobs/
       - name: Merge test result - java ${{matrix.java}}
         run: ./test/scripts/merge-test-results.sh
-
-  testjob_1:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_2:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_3:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_4:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_5:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
diff --git a/.github/workflows/dubbo-3.yml b/.github/workflows/dubbo-3.yml
index a3299d1..22f44fc 100644
--- a/.github/workflows/dubbo-3.yml
+++ b/.github/workflows/dubbo-3.yml
@@ -4,23 +4,30 @@
   pull_request:
     paths:
       - "**"
+      - "!**/*.md"
+      - "!docs/**"
   push:
     paths:
       - '**'
+      - "!**/*.md"
+      - "!docs/**"
+  workflow_dispatch:
 
 env:
   FORK_COUNT: 2
   FAIL_FAST: 0
   SHOW_ERROR_DETAIL: 1
-  BUILD_OPTS: -U --batch-mode --no-transfer-progress --settings ${{github.workspace}}/.mvn/settings.xml clean package dependency:copy-dependencies -DskipTests
+  BUILD_OPTS: -U --batch-mode --no-transfer-progress --settings ${{github.workspace}}/.mvn/settings.xml
+    -Dmaven.wagon.http.retryHandler.count=3 clean package dependency:copy-dependencies -DskipTests
   #multi-version size limit
   VERSIONS_LIMIT: 4
+  #candidate versions (the dubbo snapshot version will be extracted from pom.xml and appended before CANDIDATE_VERSIONS )
   CANDIDATE_VERSIONS: '
-    dubbo.version:3.0.0-SNAPSHOT;
     spring.version:4.3.30.RELEASE;
     spring-boot.version:1.5.22.RELEASE;
     spring-boot.version:2.4.1;
     '
+  DUBBO_REF: '3.0'
 
 jobs:
   build-samples:
@@ -35,9 +42,9 @@
         uses: actions/cache@v2
         with:
           path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+          key: ${{ runner.os }}-samples-maven-${{ hashFiles('**/pom.xml') }}
           restore-keys: |
-            ${{ runner.os }}-maven-
+            ${{ runner.os }}-samples-maven-
       - name: Set up JDK ${{matrix.java}}
         uses: actions/setup-java@v1
         with:
@@ -50,56 +57,60 @@
     runs-on: ubuntu-latest
     strategy:
       fail-fast: false
+    # Map a step output to a job output
+    outputs:
+      commit_id: ${{ steps.git-checker.outputs.commit_id }}
+      cache-hit: ${{ steps.dubbocache.outputs.cache-hit }}
     steps:
       - uses: actions/checkout@v2
         with:
           repository: 'apache/dubbo'
-          ref: master
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-      - name: Get last git commit hash
-        id: git-hash
+          ref: ${{env.DUBBO_REF}}
+      - name: Get commit id and dubbo version
+        id: git-checker
         run: |
           #compare dubbo commit id
           last_commit_id=`git log --format="%H" -n 1`
           echo "::set-output name=commit_id::$last_commit_id"
-          if [ -f ~/.m2/repository/org/apache/dubbo/dubbo-commit-id ];then
-            cache_commit_id=`cat ~/.m2/repository/org/apache/dubbo/dubbo-commit-id`
-          fi
-          if [ "$last_commit_id" == "$cache_commit_id" ];then
-            echo "::set-output name=cache-hit::true"
-          else
-            echo "::set-output name=cache-hit::false"
-          fi
+          echo "commit_id: $last_commit_id"
+          # Calculate Dubbo Version
+          REVISION=`awk '/<revision>[^<]+<\/revision>/{gsub(/<revision>|<\/revision>/,"",$1);print $1;exit;}' pom.xml`
+          mkdir dubbo-version
+          echo $REVISION > dubbo-version/dubbo-version
+          echo "dubbo version: $REVISION"
+      - name: Upload Dubbo version
+        uses: actions/upload-artifact@v2
+        with:
+          name: dubbo-version
+          path: dubbo-version
+      - name: Dubbo cache
+        id: dubbocache
+        uses: actions/cache@v2
+        with:
+          path: ~/.m2/repository/org/apache/dubbo
+          key: ${{ runner.os }}-dubbo-snapshot-${{steps.git-checker.outputs.commit_id}}
       - name: Cache local Maven repository
-        if: steps.git-hash.outputs.cache-hit != 'true'
+        if: steps.dubbocache.outputs.cache-hit != 'true'
         uses: actions/cache@v2
         with:
           path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+          key: ${{ runner.os }}-dubbo-${{env.DUBBO_REF}}-maven-${{ hashFiles('**/pom.xml') }}
           restore-keys: |
-            ${{ runner.os }}-maven-
+            ${{ runner.os }}-dubbo-${{env.DUBBO_REF}}-maven-
       - name: Set up JDK 8
-        if: steps.git-hash.outputs.cache-hit != 'true'
+        if: steps.dubbocache.outputs.cache-hit != 'true'
         uses: actions/setup-java@v1
         with:
           java-version: 8
       - name: Build dubbo
-        if: steps.git-hash.outputs.cache-hit != 'true'
+        if: steps.dubbocache.outputs.cache-hit != 'true'
         run: |
           ./mvnw -U --batch-mode --no-transfer-progress  clean install -Dmaven.test.skip=true -Dmaven.test.skip.exec=true
-      - name: Update commit id
-        run: |
-          echo commit_id: ${{steps.git-hash.outputs.commit_id}}
-          echo ${{steps.git-hash.outputs.commit_id}} > ~/.m2/repository/org/apache/dubbo/dubbo-commit-id
 
   prepare_test:
     runs-on: ubuntu-latest
     env:
-      #'JOB_COUNT' MUST match needs job list of 'test_result' job
+      #'JOB_COUNT' MUST match 'job_id' list of 'testjob'
       JOB_COUNT: 5
     steps:
       - uses: actions/checkout@v1
@@ -112,9 +123,65 @@
           name: test-list
           path: test/jobs
 
+  testjob:
+    needs: [prepare_test, build-dubbo]
+    runs-on: ubuntu-latest
+    env:
+      JAVA_VER: ${{matrix.java}}
+      TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
+    strategy:
+      fail-fast: false
+      matrix:
+        java: [8, 11]
+        #testjob id list MUST match 'JOB_COUNT' of 'prepare_test'
+        job_id: [1,2,3,4,5]
+    steps:
+      - uses: actions/checkout@v1
+      - name: Set up JDK ${{matrix.java}}
+        uses: actions/setup-java@v1
+        with:
+          java-version: ${{matrix.java}}
+      - name: Cache local Maven repository
+        uses: actions/cache@v2
+        with:
+          path: ~/.m2/repository
+          key: ${{ runner.os }}-samples-maven-${{ hashFiles('**/pom.xml') }}
+          restore-keys: |
+            ${{ runner.os }}-samples-maven-
+      - name: Dubbo cache
+        uses: actions/cache@v2
+        with:
+          path: ~/.m2/repository/org/apache/dubbo
+          key: ${{ runner.os }}-dubbo-snapshot-${{needs.build-dubbo.outputs.commit_id}}
+      - name: Download test list
+        uses: actions/download-artifact@v2
+        with:
+          name: test-list
+          path: test/jobs/
+      - name: Download Dubbo version
+        uses: actions/download-artifact@v2
+        with:
+          name: dubbo-version
+          path: dubbo-version
+      - name: Init Candidate Versions
+        run: |
+          DUBBO_VERSION=`cat dubbo-version/dubbo-version`
+          CANDIDATE_VERSIONS="dubbo.version:$DUBBO_VERSION;$CANDIDATE_VERSIONS"
+          echo "CANDIDATE_VERSIONS=$CANDIDATE_VERSIONS" >> $GITHUB_ENV
+      - name: Build test image
+        run: |
+          cd test && bash ./build-test-image.sh
+      - name: Run tests
+        run: cd test && bash ./run-tests.sh
+      - name: Upload test result
+        if: always()
+        uses: actions/upload-artifact@v2
+        with:
+          name: test-result
+          path: test/jobs/*-result*
+
   test_result:
-    #testjob list MUST match 'JOB_COUNT' of 'prepare_test' job
-    needs: [testjob_1,testjob_2,testjob_3,testjob_4,testjob_5]
+    needs: [testjob]
     if: always()
     runs-on: ubuntu-latest
     strategy:
@@ -132,238 +199,3 @@
           path: test/jobs/
       - name: Merge test result - java ${{matrix.java}}
         run: ./test/scripts/merge-test-results.sh
-
-  testjob_1:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_2:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_3:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_4:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_5:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
diff --git a/.github/workflows/nightly-dubbo-2.yml b/.github/workflows/nightly-dubbo-2.yml
index 4bb85b3..d467678 100644
--- a/.github/workflows/nightly-dubbo-2.yml
+++ b/.github/workflows/nightly-dubbo-2.yml
@@ -2,8 +2,9 @@
 
 on:
   schedule:
-    # nightly build at 2:00
-    - cron:  '0 2 * * *'
+    # nightly build at 2:00+8, should convert into UTC
+    - cron:  '0 18 * * *'
+    - cron:  '0 21 * * *'
   workflow_dispatch:
     inputs:
       remark:
@@ -13,18 +14,21 @@
 
 
 env:
-  FORK_COUNT: 2
+  FORK_COUNT: 1
   FAIL_FAST: 0
   SHOW_ERROR_DETAIL: 1
-  BUILD_OPTS: -U --batch-mode --no-transfer-progress --settings ${{github.workspace}}/.mvn/settings.xml clean package dependency:copy-dependencies -DskipTests
+  BUILD_OPTS: -U --batch-mode --no-transfer-progress --settings ${{github.workspace}}/.mvn/settings.xml
+    -Dmaven.wagon.http.retryHandler.count=3 clean package dependency:copy-dependencies -DskipTests
   #multi-version size limit
   VERSIONS_LIMIT: 12
+  #candidate versions (the dubbo snapshot version will be extracted from pom.xml and appended before CANDIDATE_VERSIONS )
   CANDIDATE_VERSIONS: '
-    dubbo.version: 2.7.8, 2.7.9-SNAPSHOT;
+    dubbo.version: 2.7.8;
     spring.version: 4.2.9.RELEASE, 4.3.30.RELEASE, 5.1.20.RELEASE, 5.3.3;
     spring-boot.version: 1.1.12.RELEASE, 1.2.8.RELEASE, 1.3.8.RELEASE, 1.4.7.RELEASE, 1.5.22.RELEASE;
     spring-boot.version: 2.0.9.RELEASE, 2.1.18.RELEASE, 2.2.12.RELEASE, 2.3.7.RELEASE, 2.4.1
     '
+  DUBBO_REF: master
 
 jobs:
   build-samples:
@@ -39,9 +43,9 @@
         uses: actions/cache@v2
         with:
           path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+          key: ${{ runner.os }}-samples-maven-${{ hashFiles('**/pom.xml') }}
           restore-keys: |
-            ${{ runner.os }}-maven-
+            ${{ runner.os }}-samples-maven-
       - name: Set up JDK ${{matrix.java}}
         uses: actions/setup-java@v1
         with:
@@ -54,56 +58,60 @@
     runs-on: ubuntu-latest
     strategy:
       fail-fast: false
+    # Map a step output to a job output
+    outputs:
+      commit_id: ${{ steps.git-checker.outputs.commit_id }}
+      cache-hit: ${{ steps.dubbocache.outputs.cache-hit }}
     steps:
       - uses: actions/checkout@v2
         with:
           repository: 'apache/dubbo'
-          ref: master
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-      - name: Get last git commit hash
-        id: git-hash
+          ref: ${{env.DUBBO_REF}}
+      - name: Get commit id and dubbo version
+        id: git-checker
         run: |
           #compare dubbo commit id
           last_commit_id=`git log --format="%H" -n 1`
           echo "::set-output name=commit_id::$last_commit_id"
-          if [ -f ~/.m2/repository/org/apache/dubbo/dubbo-commit-id ];then
-            cache_commit_id=`cat ~/.m2/repository/org/apache/dubbo/dubbo-commit-id`
-          fi
-          if [ "$last_commit_id" == "$cache_commit_id" ];then
-            echo "::set-output name=cache-hit::true"
-          else
-            echo "::set-output name=cache-hit::false"
-          fi
+          echo "commit_id: $last_commit_id"
+          # Calculate Dubbo Version
+          REVISION=`awk '/<revision>[^<]+<\/revision>/{gsub(/<revision>|<\/revision>/,"",$1);print $1;exit;}' pom.xml`
+          mkdir dubbo-version
+          echo $REVISION > dubbo-version/dubbo-version
+          echo "dubbo version: $REVISION"
+      - name: Upload Dubbo version
+        uses: actions/upload-artifact@v2
+        with:
+          name: dubbo-version
+          path: dubbo-version
+      - name: Dubbo cache
+        id: dubbocache
+        uses: actions/cache@v2
+        with:
+          path: ~/.m2/repository/org/apache/dubbo
+          key: ${{ runner.os }}-dubbo-snapshot-${{steps.git-checker.outputs.commit_id}}
       - name: Cache local Maven repository
-        if: steps.git-hash.outputs.cache-hit != 'true'
+        if: steps.dubbocache.outputs.cache-hit != 'true'
         uses: actions/cache@v2
         with:
           path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+          key: ${{ runner.os }}-dubbo-${{env.DUBBO_REF}}-maven-${{ hashFiles('**/pom.xml') }}
           restore-keys: |
-            ${{ runner.os }}-maven-
+            ${{ runner.os }}-dubbo-${{env.DUBBO_REF}}-maven-
       - name: Set up JDK 8
-        if: steps.git-hash.outputs.cache-hit != 'true'
+        if: steps.dubbocache.outputs.cache-hit != 'true'
         uses: actions/setup-java@v1
         with:
           java-version: 8
       - name: Build dubbo
-        if: steps.git-hash.outputs.cache-hit != 'true'
+        if: steps.dubbocache.outputs.cache-hit != 'true'
         run: |
           ./mvnw -U --batch-mode --no-transfer-progress  clean install -Dmaven.test.skip=true -Dmaven.test.skip.exec=true
-      - name: Update commit id
-        run: |
-          echo commit_id: ${{steps.git-hash.outputs.commit_id}}
-          echo ${{steps.git-hash.outputs.commit_id}} > ~/.m2/repository/org/apache/dubbo/dubbo-commit-id
 
   prepare_test:
     runs-on: ubuntu-latest
     env:
-      #'JOB_COUNT' MUST match needs job list of 'test_result' job
+      #'JOB_COUNT' MUST match 'job_id' list of 'testjob'
       JOB_COUNT: 5
     steps:
       - uses: actions/checkout@v1
@@ -116,9 +124,65 @@
           name: test-list
           path: test/jobs
 
+  testjob:
+    needs: [prepare_test, build-dubbo]
+    runs-on: ubuntu-latest
+    env:
+      JAVA_VER: ${{matrix.java}}
+      TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
+    strategy:
+      fail-fast: false
+      matrix:
+        java: [8, 11]
+        #testjob id list MUST match 'JOB_COUNT' of 'prepare_test'
+        job_id: [1,2,3,4,5]
+    steps:
+      - uses: actions/checkout@v1
+      - name: Set up JDK ${{matrix.java}}
+        uses: actions/setup-java@v1
+        with:
+          java-version: ${{matrix.java}}
+      - name: Cache local Maven repository
+        uses: actions/cache@v2
+        with:
+          path: ~/.m2/repository
+          key: ${{ runner.os }}-samples-maven-${{ hashFiles('**/pom.xml') }}
+          restore-keys: |
+            ${{ runner.os }}-samples-maven-
+      - name: Dubbo cache
+        uses: actions/cache@v2
+        with:
+          path: ~/.m2/repository/org/apache/dubbo
+          key: ${{ runner.os }}-dubbo-snapshot-${{needs.build-dubbo.outputs.commit_id}}
+      - name: Download test list
+        uses: actions/download-artifact@v2
+        with:
+          name: test-list
+          path: test/jobs/
+      - name: Download Dubbo version
+        uses: actions/download-artifact@v2
+        with:
+          name: dubbo-version
+          path: dubbo-version
+      - name: Init Candidate Versions
+        run: |
+          DUBBO_VERSION=`cat dubbo-version/dubbo-version`
+          CANDIDATE_VERSIONS="dubbo.version:$DUBBO_VERSION;$CANDIDATE_VERSIONS"
+          echo "CANDIDATE_VERSIONS=$CANDIDATE_VERSIONS" >> $GITHUB_ENV
+      - name: Build test image
+        run: |
+          cd test && bash ./build-test-image.sh
+      - name: Run tests
+        run: cd test && bash ./run-tests.sh
+      - name: Upload test result
+        if: always()
+        uses: actions/upload-artifact@v2
+        with:
+          name: test-result
+          path: test/jobs/*-result*
+
   test_result:
-    #testjob list MUST match 'JOB_COUNT' of 'prepare_test' job
-    needs: [testjob_1,testjob_2,testjob_3,testjob_4,testjob_5]
+    needs: [testjob]
     if: always()
     runs-on: ubuntu-latest
     strategy:
@@ -136,238 +200,3 @@
           path: test/jobs/
       - name: Merge test result - java ${{matrix.java}}
         run: ./test/scripts/merge-test-results.sh
-
-  testjob_1:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_2:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_3:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_4:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_5:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
diff --git a/.github/workflows/nightly-dubbo-3.yml b/.github/workflows/nightly-dubbo-3.yml
index 3020628..301dff1 100644
--- a/.github/workflows/nightly-dubbo-3.yml
+++ b/.github/workflows/nightly-dubbo-3.yml
@@ -2,8 +2,9 @@
 
 on:
   schedule:
-    # nightly build at 2:00
-    - cron:  '0 2 * * *'
+    # nightly build at 2:00+8, should convert into UTC
+    - cron:  '0 18 * * *'
+    - cron:  '0 21 * * *'
   workflow_dispatch:
     inputs:
       remark:
@@ -13,18 +14,20 @@
 
 
 env:
-  FORK_COUNT: 2
+  FORK_COUNT: 1
   FAIL_FAST: 0
   SHOW_ERROR_DETAIL: 1
-  BUILD_OPTS: -U --batch-mode --no-transfer-progress --settings ${{github.workspace}}/.mvn/settings.xml clean package dependency:copy-dependencies -DskipTests
+  BUILD_OPTS: -U --batch-mode --no-transfer-progress --settings ${{github.workspace}}/.mvn/settings.xml
+    -Dmaven.wagon.http.retryHandler.count=3 clean package dependency:copy-dependencies -DskipTests
   #multi-version size limit
   VERSIONS_LIMIT: 12
+  #candidate versions (the dubbo snapshot version will be extracted from pom.xml and appended before CANDIDATE_VERSIONS )
   CANDIDATE_VERSIONS: '
-    dubbo.version: 3.0.0-SNAPSHOT;
     spring.version: 4.2.9.RELEASE, 4.3.30.RELEASE, 5.1.20.RELEASE, 5.3.3;
     spring-boot.version: 1.1.12.RELEASE, 1.2.8.RELEASE, 1.3.8.RELEASE, 1.4.7.RELEASE, 1.5.22.RELEASE;
     spring-boot.version: 2.0.9.RELEASE, 2.1.18.RELEASE, 2.2.12.RELEASE, 2.3.7.RELEASE, 2.4.1
     '
+  DUBBO_REF: '3.0'
 
 jobs:
   build-samples:
@@ -39,9 +42,9 @@
         uses: actions/cache@v2
         with:
           path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+          key: ${{ runner.os }}-samples-maven-${{ hashFiles('**/pom.xml') }}
           restore-keys: |
-            ${{ runner.os }}-maven-
+            ${{ runner.os }}-samples-maven-
       - name: Set up JDK ${{matrix.java}}
         uses: actions/setup-java@v1
         with:
@@ -54,56 +57,60 @@
     runs-on: ubuntu-latest
     strategy:
       fail-fast: false
+    # Map a step output to a job output
+    outputs:
+      commit_id: ${{ steps.git-checker.outputs.commit_id }}
+      cache-hit: ${{ steps.dubbocache.outputs.cache-hit }}
     steps:
       - uses: actions/checkout@v2
         with:
           repository: 'apache/dubbo'
-          ref: master
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-      - name: Get last git commit hash
-        id: git-hash
+          ref: ${{env.DUBBO_REF}}
+      - name: Get commit id and dubbo version
+        id: git-checker
         run: |
           #compare dubbo commit id
           last_commit_id=`git log --format="%H" -n 1`
           echo "::set-output name=commit_id::$last_commit_id"
-          if [ -f ~/.m2/repository/org/apache/dubbo/dubbo-commit-id ];then
-            cache_commit_id=`cat ~/.m2/repository/org/apache/dubbo/dubbo-commit-id`
-          fi
-          if [ "$last_commit_id" == "$cache_commit_id" ];then
-            echo "::set-output name=cache-hit::true"
-          else
-            echo "::set-output name=cache-hit::false"
-          fi
+          echo "commit_id: $last_commit_id"
+          # Calculate Dubbo Version
+          REVISION=`awk '/<revision>[^<]+<\/revision>/{gsub(/<revision>|<\/revision>/,"",$1);print $1;exit;}' pom.xml`
+          mkdir dubbo-version
+          echo $REVISION > dubbo-version/dubbo-version
+          echo "dubbo version: $REVISION"
+      - name: Upload Dubbo version
+        uses: actions/upload-artifact@v2
+        with:
+          name: dubbo-version
+          path: dubbo-version
+      - name: Dubbo cache
+        id: dubbocache
+        uses: actions/cache@v2
+        with:
+          path: ~/.m2/repository/org/apache/dubbo
+          key: ${{ runner.os }}-dubbo-snapshot-${{steps.git-checker.outputs.commit_id}}
       - name: Cache local Maven repository
-        if: steps.git-hash.outputs.cache-hit != 'true'
+        if: steps.dubbocache.outputs.cache-hit != 'true'
         uses: actions/cache@v2
         with:
           path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+          key: ${{ runner.os }}-dubbo-${{env.DUBBO_REF}}-maven-${{ hashFiles('**/pom.xml') }}
           restore-keys: |
-            ${{ runner.os }}-maven-
+            ${{ runner.os }}-dubbo-${{env.DUBBO_REF}}-maven-
       - name: Set up JDK 8
-        if: steps.git-hash.outputs.cache-hit != 'true'
+        if: steps.dubbocache.outputs.cache-hit != 'true'
         uses: actions/setup-java@v1
         with:
           java-version: 8
       - name: Build dubbo
-        if: steps.git-hash.outputs.cache-hit != 'true'
+        if: steps.dubbocache.outputs.cache-hit != 'true'
         run: |
           ./mvnw -U --batch-mode --no-transfer-progress  clean install -Dmaven.test.skip=true -Dmaven.test.skip.exec=true
-      - name: Update commit id
-        run: |
-          echo commit_id: ${{steps.git-hash.outputs.commit_id}}
-          echo ${{steps.git-hash.outputs.commit_id}} > ~/.m2/repository/org/apache/dubbo/dubbo-commit-id
 
   prepare_test:
     runs-on: ubuntu-latest
     env:
-      #'JOB_COUNT' MUST match needs job list of 'test_result' job
+      #'JOB_COUNT' MUST match 'job_id' list of 'testjob'
       JOB_COUNT: 5
     steps:
       - uses: actions/checkout@v1
@@ -116,9 +123,65 @@
           name: test-list
           path: test/jobs
 
+  testjob:
+    needs: [prepare_test, build-dubbo]
+    runs-on: ubuntu-latest
+    env:
+      JAVA_VER: ${{matrix.java}}
+      TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
+    strategy:
+      fail-fast: false
+      matrix:
+        java: [8, 11]
+        #testjob id list MUST match 'JOB_COUNT' of 'prepare_test'
+        job_id: [1,2,3,4,5]
+    steps:
+      - uses: actions/checkout@v1
+      - name: Set up JDK ${{matrix.java}}
+        uses: actions/setup-java@v1
+        with:
+          java-version: ${{matrix.java}}
+      - name: Cache local Maven repository
+        uses: actions/cache@v2
+        with:
+          path: ~/.m2/repository
+          key: ${{ runner.os }}-samples-maven-${{ hashFiles('**/pom.xml') }}
+          restore-keys: |
+            ${{ runner.os }}-samples-maven-
+      - name: Dubbo cache
+        uses: actions/cache@v2
+        with:
+          path: ~/.m2/repository/org/apache/dubbo
+          key: ${{ runner.os }}-dubbo-snapshot-${{needs.build-dubbo.outputs.commit_id}}
+      - name: Download test list
+        uses: actions/download-artifact@v2
+        with:
+          name: test-list
+          path: test/jobs/
+      - name: Download Dubbo version
+        uses: actions/download-artifact@v2
+        with:
+          name: dubbo-version
+          path: dubbo-version
+      - name: Init Candidate Versions
+        run: |
+          DUBBO_VERSION=`cat dubbo-version/dubbo-version`
+          CANDIDATE_VERSIONS="dubbo.version:$DUBBO_VERSION;$CANDIDATE_VERSIONS"
+          echo "CANDIDATE_VERSIONS=$CANDIDATE_VERSIONS" >> $GITHUB_ENV
+      - name: Build test image
+        run: |
+          cd test && bash ./build-test-image.sh
+      - name: Run tests
+        run: cd test && bash ./run-tests.sh
+      - name: Upload test result
+        if: always()
+        uses: actions/upload-artifact@v2
+        with:
+          name: test-result
+          path: test/jobs/*-result*
+
   test_result:
-    #testjob list MUST match 'JOB_COUNT' of 'prepare_test' job
-    needs: [testjob_1,testjob_2,testjob_3,testjob_4,testjob_5]
+    needs: [testjob]
     if: always()
     runs-on: ubuntu-latest
     strategy:
@@ -136,238 +199,3 @@
           path: test/jobs/
       - name: Merge test result - java ${{matrix.java}}
         run: ./test/scripts/merge-test-results.sh
-
-  testjob_1:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_2:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_3:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_4:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
-
-  testjob_5:
-    needs: [prepare_test, build-dubbo]
-    runs-on: ubuntu-latest
-    env:
-      JAVA_VER: ${{matrix.java}}
-      TEST_CASE_FILE: jobs/${{github.job}}.txt
-    strategy:
-      fail-fast: false
-      matrix:
-        java: [8, 11]
-    steps:
-      - uses: actions/checkout@v1
-      - name: Cache local Maven repository
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: Dubbo cache
-        uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository/org/apache/dubbo
-          key: ${{ runner.os }}-dubbo-snapshot
-          restore-keys: |
-            ${{ runner.os }}-dubbo-
-      - name: Download test list
-        uses: actions/download-artifact@v2
-        with:
-          name: test-list
-          path: test/jobs/
-      - name: Set up JDK ${{matrix.java}}
-        uses: actions/setup-java@v1
-        with:
-          java-version: ${{matrix.java}}
-      - name: Build test image
-        run: |
-          cd test && bash ./build-test-image.sh
-      - name: Run tests
-        run: cd test && bash ./run-tests.sh
-      - name: Upload test result
-        if: always()
-        uses: actions/upload-artifact@v2
-        with:
-          name: test-result
-          path: test/jobs/*-result*
diff --git a/dubbo-samples-chain/case-configuration.yml b/dubbo-samples-chain/case-configuration.yml
index fd33829..59d21f8 100644
--- a/dubbo-samples-chain/case-configuration.yml
+++ b/dubbo-samples-chain/case-configuration.yml
@@ -27,6 +27,9 @@
       - zookeeper.address=zookeeper
     waitPortsBeforeRun:
       - zookeeper:2181
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - zookeeper
 
@@ -38,8 +41,12 @@
       - zookeeper.address=zookeeper
     waitPortsBeforeRun:
       - zookeeper:2181
+    checkPorts:
+      - 20881
+    checkLog: "dubbo service started"
     depends_on:
       - zookeeper
+      - dubbo-samples-chain-backend
 
   dubbo-samples-chain-front:
     type: test
diff --git a/dubbo-samples-configcenter/dubbo-samples-configcenter-api/case-configuration.yml b/dubbo-samples-configcenter/dubbo-samples-configcenter-api/case-configuration.yml
index b2f3028..e149c1d 100644
--- a/dubbo-samples-configcenter/dubbo-samples-configcenter-api/case-configuration.yml
+++ b/dubbo-samples-configcenter/dubbo-samples-configcenter-api/case-configuration.yml
@@ -33,6 +33,9 @@
     waitPortsBeforeRun:
       - zookeeper1:2181
       - zookeeper2:2181
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - zookeeper1
       - zookeeper2
diff --git a/dubbo-samples-configcenter/dubbo-samples-configcenter-apollo/case-configuration.yml b/dubbo-samples-configcenter/dubbo-samples-configcenter-apollo/case-configuration.yml
index 020e61f..568e112 100644
--- a/dubbo-samples-configcenter/dubbo-samples-configcenter-apollo/case-configuration.yml
+++ b/dubbo-samples-configcenter/dubbo-samples-configcenter-apollo/case-configuration.yml
@@ -32,6 +32,7 @@
     waitTimeout: 100
     checkPorts:
       - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - apollo-db
       - apollo-quick-start
diff --git a/dubbo-samples-configcenter/dubbo-samples-configcenter-multi-registries/case-configuration.yml b/dubbo-samples-configcenter/dubbo-samples-configcenter-multi-registries/case-configuration.yml
index 8cfcd3d..fafcbf6 100644
--- a/dubbo-samples-configcenter/dubbo-samples-configcenter-multi-registries/case-configuration.yml
+++ b/dubbo-samples-configcenter/dubbo-samples-configcenter-multi-registries/case-configuration.yml
@@ -39,6 +39,9 @@
       - config-center:2181
       - zookeeper1:2181
       - zookeeper2:2181
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - config-center
       - zookeeper1
diff --git a/dubbo-samples-consul/case-configuration.yml b/dubbo-samples-consul/case-configuration.yml
index 03d7ce1..f0226a2 100644
--- a/dubbo-samples-consul/case-configuration.yml
+++ b/dubbo-samples-consul/case-configuration.yml
@@ -27,6 +27,9 @@
       - consul.port=8500
     waitPortsBeforeRun:
       - consul:8500
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - consul
 
diff --git a/dubbo-samples-governance/dubbo-samples-applevel-override/case-configuration.yml b/dubbo-samples-governance/dubbo-samples-applevel-override/case-configuration.yml
index e11dc1f..7a24d00 100644
--- a/dubbo-samples-governance/dubbo-samples-applevel-override/case-configuration.yml
+++ b/dubbo-samples-governance/dubbo-samples-applevel-override/case-configuration.yml
@@ -28,6 +28,9 @@
       - dubbo.port=20880
     waitPortsBeforeRun:
       - zookeeper:2181
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - zookeeper
 
@@ -41,6 +44,9 @@
       - dubbo.port=20881
     waitPortsBeforeRun:
       - zookeeper:2181
+    checkPorts:
+      - 20881
+    checkLog: "dubbo service started"
     depends_on:
       - zookeeper
 
diff --git a/dubbo-samples-governance/dubbo-samples-applevel-override/src/main/resources/dubbo-override.yml b/dubbo-samples-governance/dubbo-samples-applevel-override/src/main/resources/dubbo-override.yml
index 3abab95..ac901b9 100644
--- a/dubbo-samples-governance/dubbo-samples-applevel-override/src/main/resources/dubbo-override.yml
+++ b/dubbo-samples-governance/dubbo-samples-applevel-override/src/main/resources/dubbo-override.yml
@@ -28,7 +28,7 @@
 - addresses: ["0.0.0.0:20880"]
   side: provider
   parameters:
-    weight: 1000
+    weight: 100
 - addresses: ["0.0.0.0:20881"]
   side: provider
   parameters:
diff --git a/dubbo-samples-governance/dubbo-samples-applevel-override/src/test/java/org/apache/dubbo/samples/governance/DemoServiceIT.java b/dubbo-samples-governance/dubbo-samples-applevel-override/src/test/java/org/apache/dubbo/samples/governance/DemoServiceIT.java
index 915f987..5af6618 100644
--- a/dubbo-samples-governance/dubbo-samples-applevel-override/src/test/java/org/apache/dubbo/samples/governance/DemoServiceIT.java
+++ b/dubbo-samples-governance/dubbo-samples-applevel-override/src/test/java/org/apache/dubbo/samples/governance/DemoServiceIT.java
@@ -43,7 +43,9 @@
         ZKTools.generateAppLevelOverride(100, 0);
         Thread.sleep(5000);
         for (int i = 0; i < 10; i++) {
-            Assert.assertTrue(demoService.sayHello("world").contains("20880"));
+            String result = demoService.sayHello("world");
+            System.out.println(result);
+            Assert.assertTrue(result.contains("20880"));
         }
     }
 
@@ -52,7 +54,9 @@
         ZKTools.generateAppLevelOverride(0, 100);
         Thread.sleep(5000);
         for (int i = 0; i < 10; i++) {
-            Assert.assertTrue(demoService.sayHello("world").contains("20881"));
+            String result = demoService.sayHello("world");
+            System.out.println(result);
+            Assert.assertTrue(result.contains("20881"));
         }
     }
 }
diff --git a/dubbo-samples-governance/dubbo-samples-configconditionrouter/case-configuration.yml b/dubbo-samples-governance/dubbo-samples-configconditionrouter/case-configuration.yml
index 43ac656..f0c14c8 100644
--- a/dubbo-samples-governance/dubbo-samples-configconditionrouter/case-configuration.yml
+++ b/dubbo-samples-governance/dubbo-samples-configconditionrouter/case-configuration.yml
@@ -28,6 +28,9 @@
       - dubbo.port=20880
     waitPortsBeforeRun:
       - zookeeper:2181
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - zookeeper
 
@@ -41,6 +44,9 @@
       - dubbo.port=20881
     waitPortsBeforeRun:
       - zookeeper:2181
+    checkPorts:
+      - 20881
+    checkLog: "dubbo service started"
     depends_on:
       - zookeeper
 
diff --git a/dubbo-samples-governance/dubbo-samples-tagrouter/case-configuration.yml b/dubbo-samples-governance/dubbo-samples-tagrouter/case-configuration.yml
index c251a4c..00f10ec 100644
--- a/dubbo-samples-governance/dubbo-samples-tagrouter/case-configuration.yml
+++ b/dubbo-samples-governance/dubbo-samples-tagrouter/case-configuration.yml
@@ -28,6 +28,9 @@
       - dubbo.port=20880
     waitPortsBeforeRun:
       - zookeeper:2181
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - zookeeper
 
@@ -41,6 +44,9 @@
       - dubbo.port=20881
     waitPortsBeforeRun:
       - zookeeper:2181
+    checkPorts:
+      - 20881
+    checkLog: "dubbo service started"
     depends_on:
       - zookeeper
 
diff --git a/dubbo-samples-merge/case-configuration.yml b/dubbo-samples-merge/case-configuration.yml
index 1cbfc76..55589be 100644
--- a/dubbo-samples-merge/case-configuration.yml
+++ b/dubbo-samples-merge/case-configuration.yml
@@ -27,6 +27,9 @@
       - zookeeper.address=zookeeper
     waitPortsBeforeRun:
       - zookeeper:2181
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - zookeeper
 
@@ -38,6 +41,9 @@
       - zookeeper.address=zookeeper
     waitPortsBeforeRun:
       - zookeeper:2181
+    checkPorts:
+      - 20881
+    checkLog: "dubbo service started"
     depends_on:
       - zookeeper
 
diff --git a/dubbo-samples-monitor/case-configuration.yml b/dubbo-samples-monitor/case-configuration.yml
index 4e2ea13..77b0773 100644
--- a/dubbo-samples-monitor/case-configuration.yml
+++ b/dubbo-samples-monitor/case-configuration.yml
@@ -14,10 +14,46 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from: app-external-zookeeper.yml
+services:
+  zookeeper:
+    image: zookeeper:latest
 
-props:
-  project_name: dubbo-samples-monitor
-  main_class: org.apache.dubbo.samples.monitor.BasicProvider
-  dubbo_port: 20880
+  dubbo-provider:
+    type: app
+    basedir: .
+    mainClass: org.apache.dubbo.samples.monitor.BasicProvider
+    systemProps:
+      - zookeeper.address=zookeeper
+      - zookeeper.port=2181
+    waitPortsBeforeRun:
+      - zookeeper:2181
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
 
+  dubbo-monitor:
+    type: app
+    basedir: .
+    mainClass: org.apache.dubbo.samples.monitor.BasicMonitor
+    systemProps:
+      - zookeeper.address=zookeeper
+      - zookeeper.port=2181
+    waitPortsBeforeRun:
+      - zookeeper:2181
+    checkPorts:
+      - 20881
+    checkLog: "dubbo service started"
+
+  monitor-test:
+    type: test
+    basedir: .
+    tests:
+      - "**/*IT.class"
+    systemProps:
+      - zookeeper.address=zookeeper
+      - zookeeper.port=2181
+    waitPortsBeforeRun:
+      - zookeeper:2181
+    depends_on:
+      - dubbo-provider
+      - dubbo-monitor
diff --git a/dubbo-samples-monitor/pom.xml b/dubbo-samples-monitor/pom.xml
index e3a3362..afb07ae 100644
--- a/dubbo-samples-monitor/pom.xml
+++ b/dubbo-samples-monitor/pom.xml
@@ -29,7 +29,7 @@
     <properties>
         <source.level>1.8</source.level>
         <target.level>1.8</target.level>
-        <dubbo.version>2.7.7</dubbo.version>
+        <dubbo.version>2.7.8</dubbo.version>
         <spring.version>4.3.16.RELEASE</spring.version>
         <junit.version>4.12</junit.version>
         <maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
diff --git a/dubbo-samples-monitor/src/main/java/org/apache/dubbo/samples/monitor/BasicMonitor.java b/dubbo-samples-monitor/src/main/java/org/apache/dubbo/samples/monitor/BasicMonitor.java
new file mode 100644
index 0000000..1ffc6a6
--- /dev/null
+++ b/dubbo-samples-monitor/src/main/java/org/apache/dubbo/samples/monitor/BasicMonitor.java
@@ -0,0 +1,34 @@
+/*
+ *   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.dubbo.samples.monitor;
+
+import org.apache.dubbo.samples.monitor.api.DemoService;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import java.util.concurrent.CountDownLatch;
+
+public class BasicMonitor {
+
+    public static void main(String[] args) throws Exception {
+        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-demo-monitor.xml");
+        context.start();
+
+        System.out.println("dubbo service started");
+        new CountDownLatch(1).await();
+    }
+}
diff --git a/dubbo-samples-monitor/src/test/java/org/apache/dubbo/samples/monitor/MonitorServiceImpl.java b/dubbo-samples-monitor/src/main/java/org/apache/dubbo/samples/monitor/impl/MonitorServiceImpl.java
similarity index 96%
rename from dubbo-samples-monitor/src/test/java/org/apache/dubbo/samples/monitor/MonitorServiceImpl.java
rename to dubbo-samples-monitor/src/main/java/org/apache/dubbo/samples/monitor/impl/MonitorServiceImpl.java
index aa05da3..e674261 100644
--- a/dubbo-samples-monitor/src/test/java/org/apache/dubbo/samples/monitor/MonitorServiceImpl.java
+++ b/dubbo-samples-monitor/src/main/java/org/apache/dubbo/samples/monitor/impl/MonitorServiceImpl.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.samples.monitor;
+package org.apache.dubbo.samples.monitor.impl;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.monitor.MonitorService;
diff --git a/dubbo-samples-monitor/src/main/resources/spring/dubbo-demo-monitor.xml b/dubbo-samples-monitor/src/main/resources/spring/dubbo-demo-monitor.xml
new file mode 100644
index 0000000..65d1d0b
--- /dev/null
+++ b/dubbo-samples-monitor/src/main/resources/spring/dubbo-demo-monitor.xml
@@ -0,0 +1,35 @@
+<?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.
+  -->
+
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
+       xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
+    <context:property-placeholder/>
+
+    <dubbo:application name="demo-monitor"/>
+
+    <dubbo:registry address="zookeeper://${zookeeper.address:127.0.0.1}:2181"/>
+
+    <dubbo:protocol name="dubbo" port="20881"/>
+
+    <dubbo:service interface="org.apache.dubbo.monitor.MonitorService" ref="monitorService" filter="-monitor"/>
+
+    <bean id="monitorService" class="org.apache.dubbo.samples.monitor.impl.MonitorServiceImpl" />
+</beans>
diff --git a/dubbo-samples-monitor/src/test/java/org/apache/dubbo/samples/monitor/MonitorServiceIT.java b/dubbo-samples-monitor/src/test/java/org/apache/dubbo/samples/monitor/MonitorServiceIT.java
index 6b871ba..de1c3a4 100644
--- a/dubbo-samples-monitor/src/test/java/org/apache/dubbo/samples/monitor/MonitorServiceIT.java
+++ b/dubbo-samples-monitor/src/test/java/org/apache/dubbo/samples/monitor/MonitorServiceIT.java
@@ -46,31 +46,18 @@
     @Autowired
     private DemoService demoService;
 
-    @Before
-    public void setUp() throws Exception {
-        ServiceConfig<MonitorService> service = new ServiceConfig<>();
-        // FIXME: has to set application name to "demo-consumer"
-        service.setApplication(new ApplicationConfig("demo-consumer"));
-        service.setRegistry(new RegistryConfig("zookeeper://" + zookeeperHost + ":2181"));
-//        MonitorConfig monitorConfig = new MonitorConfig();
-//        monitorConfig.setProtocol("registry");
-//        monitorConfig.setInterval("100");
-//        service.setMonitor(monitorConfig);
-        service.setInterface(MonitorService.class);
-        service.setFilter("-monitor");
-        service.setRef(new MonitorServiceImpl());
-        service.export();
-    }
-
     @Test
     public void test() throws Exception {
-        for (int i = 0; i < 10; i++) {
+        for (int i = 0; i < 5; i++) {
             demoService.sayHello("world");
-            Thread.sleep(50);
+            Thread.sleep(500);
         }
 
+        //wait for monitor data post
+        Thread.sleep(1000);
+
         ReferenceConfig<MonitorService> reference = new ReferenceConfig<>();
-        reference.setApplication(new ApplicationConfig("demo-consumer"));
+        reference.setApplication(new ApplicationConfig("demo-monitor"));
         reference.setRegistry(new RegistryConfig("zookeeper://" + zookeeperHost + ":2181"));
         reference.setInterface(MonitorService.class);
         reference.setFilter("-monitor");
@@ -79,6 +66,7 @@
 
         boolean countProvider = false;
         boolean countConsumer = false;
+        System.out.println("monitor stats: "+stats.size());
         for (URL stat : stats) {
             Assert.assertEquals("count", stat.getProtocol());
             Assert.assertEquals("org.apache.dubbo.samples.monitor.api.DemoService/sayHello", stat.getPath());
diff --git a/dubbo-samples-monitor/src/test/resources/spring/monitor-service.xml b/dubbo-samples-monitor/src/test/resources/spring/monitor-service.xml
index bb10dfe..bdbfffd 100644
--- a/dubbo-samples-monitor/src/test/resources/spring/monitor-service.xml
+++ b/dubbo-samples-monitor/src/test/resources/spring/monitor-service.xml
@@ -29,7 +29,7 @@
 
     <dubbo:protocol name="dubbo" port="20880"/>
 
-    <bean id="monitorService" class="org.apache.dubbo.samples.monitor.MonitorServiceImpl"/>
+    <bean id="monitorService" class="org.apache.dubbo.samples.monitor.impl.MonitorServiceImpl"/>
 
     <dubbo:service interface="org.apache.dubbo.monitor.MonitorService" ref="monitorService"/>
 </beans>
diff --git a/dubbo-samples-multi-registry/case-configuration.yml b/dubbo-samples-multi-registry/case-configuration.yml
index 5d3bbd1..574400a 100644
--- a/dubbo-samples-multi-registry/case-configuration.yml
+++ b/dubbo-samples-multi-registry/case-configuration.yml
@@ -19,6 +19,9 @@
     type: app
     basedir: .
     mainClass: org.apache.dubbo.samples.multi.registry.MultiRegistryProvider
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
 
   dubbo-samples-multi-registry-test:
     type: test
diff --git a/dubbo-samples-nacos/dubbo-samples-nacos-conditionrouter/case-configuration.yml b/dubbo-samples-nacos/dubbo-samples-nacos-conditionrouter/case-configuration.yml
index 73fe123..f9f69d7 100644
--- a/dubbo-samples-nacos/dubbo-samples-nacos-conditionrouter/case-configuration.yml
+++ b/dubbo-samples-nacos/dubbo-samples-nacos-conditionrouter/case-configuration.yml
@@ -20,6 +20,9 @@
     environment:
       - PREFER_HOST_MODE=hostname
       - MODE=standalone
+      - JVM_XMS=350m
+      - JVM_XMX=350m
+      - JVM_XMN=150m
 
   dubbo-samples-nacos-conditionrouter1:
     type: app
@@ -31,6 +34,9 @@
       - dubbo.port=20880
     waitPortsBeforeRun:
       - nacos:8848
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - nacos
 
@@ -44,6 +50,9 @@
       - dubbo.port=20881
     waitPortsBeforeRun:
       - nacos:8848
+    checkPorts:
+      - 20881
+    checkLog: "dubbo service started"
     depends_on:
       - nacos
 
diff --git a/dubbo-samples-nacos/dubbo-samples-nacos-configcenter/case-configuration.yml b/dubbo-samples-nacos/dubbo-samples-nacos-configcenter/case-configuration.yml
index c2c9991..ea897f4 100644
--- a/dubbo-samples-nacos/dubbo-samples-nacos-configcenter/case-configuration.yml
+++ b/dubbo-samples-nacos/dubbo-samples-nacos-configcenter/case-configuration.yml
@@ -20,6 +20,9 @@
     environment:
       - PREFER_HOST_MODE=hostname
       - MODE=standalone
+      - JVM_XMS=350m
+      - JVM_XMX=350m
+      - JVM_XMN=150m
 
   dubbo-samples-nacos-configcenter:
     type: app
@@ -30,6 +33,9 @@
       - nacos.port=8848
     waitPortsBeforeRun:
       - nacos:8848
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - nacos
 
diff --git a/dubbo-samples-nacos/dubbo-samples-nacos-override/case-configuration.yml b/dubbo-samples-nacos/dubbo-samples-nacos-override/case-configuration.yml
index 7ee1dc7..8cffd7d 100644
--- a/dubbo-samples-nacos/dubbo-samples-nacos-override/case-configuration.yml
+++ b/dubbo-samples-nacos/dubbo-samples-nacos-override/case-configuration.yml
@@ -22,6 +22,9 @@
     environment:
       - PREFER_HOST_MODE=hostname
       - MODE=standalone
+      - JVM_XMS=350m
+      - JVM_XMX=350m
+      - JVM_XMN=150m
 
   dubbo-samples-nacos-override:
     type: app
@@ -32,6 +35,9 @@
       - nacos.port=8848
     waitPortsBeforeRun:
       - nacos:8848
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - nacos
 
diff --git a/dubbo-samples-nacos/dubbo-samples-nacos-registry/case-configuration.yml b/dubbo-samples-nacos/dubbo-samples-nacos-registry/case-configuration.yml
index daee816..6a1b00a 100644
--- a/dubbo-samples-nacos/dubbo-samples-nacos-registry/case-configuration.yml
+++ b/dubbo-samples-nacos/dubbo-samples-nacos-registry/case-configuration.yml
@@ -20,6 +20,9 @@
     environment:
       - PREFER_HOST_MODE=hostname
       - MODE=standalone
+      - JVM_XMS=350m
+      - JVM_XMX=350m
+      - JVM_XMN=150m
 
   dubbo-samples-nacos-registry:
     type: app
@@ -30,6 +33,9 @@
       - nacos.port=8848
     waitPortsBeforeRun:
       - nacos:8848
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - nacos
 
diff --git a/dubbo-samples-nacos/dubbo-samples-nacos-tagrouter/case-configuration.yml b/dubbo-samples-nacos/dubbo-samples-nacos-tagrouter/case-configuration.yml
index 460453c..0f6c428 100644
--- a/dubbo-samples-nacos/dubbo-samples-nacos-tagrouter/case-configuration.yml
+++ b/dubbo-samples-nacos/dubbo-samples-nacos-tagrouter/case-configuration.yml
@@ -20,6 +20,9 @@
     environment:
       - PREFER_HOST_MODE=hostname
       - MODE=standalone
+      - JVM_XMS=350m
+      - JVM_XMX=350m
+      - JVM_XMN=150m
 
   dubbo-samples-nacos-tagrouter1:
     type: app
@@ -31,6 +34,9 @@
       - dubbo.port=20880
     waitPortsBeforeRun:
       - nacos:8848
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - nacos
 
@@ -44,6 +50,9 @@
       - dubbo.port=20881
     waitPortsBeforeRun:
       - nacos:8848
+    checkPorts:
+      - 20881
+    checkLog: "dubbo service started"
     depends_on:
       - nacos
 
diff --git a/dubbo-samples-ssl/case-configuration.yml b/dubbo-samples-ssl/case-configuration.yml
index 6c106c5..26a2125 100644
--- a/dubbo-samples-ssl/case-configuration.yml
+++ b/dubbo-samples-ssl/case-configuration.yml
@@ -28,6 +28,9 @@
       - dubbo.ssl.server-key-cert-chain-path=/dubbo-samples-ssl-provider/certs/server0.pem
       - dubbo.ssl.server-private-key-path=/dubbo-samples-ssl-provider/certs/server0.key
       - dubbo.ssl.server-trust-cert-collection-path=/dubbo-samples-ssl-provider/certs/ca.pem
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
 
   dubbo-samples-ssl-test:
     type: test
diff --git a/dubbo-samples-tengine/case-configuration.yml b/dubbo-samples-tengine/case-configuration.yml
index 9065441..13fb926 100644
--- a/dubbo-samples-tengine/case-configuration.yml
+++ b/dubbo-samples-tengine/case-configuration.yml
@@ -30,6 +30,7 @@
     mainClass: org.apache.dubbo.samples.tengine.provider.Provider
     checkPorts:
       - 20880
+    checkLog: "dubbo service started"
 
   dubbo-samples-tengine-test:
     type: test
diff --git a/dubbo-samples-transaction/case-configuration.yml b/dubbo-samples-transaction/case-configuration.yml
index 0446efe..4ba3e64 100644
--- a/dubbo-samples-transaction/case-configuration.yml
+++ b/dubbo-samples-transaction/case-configuration.yml
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-timeout: 150
+timeout: 300
 
 # global system props for all service
 systemProps:
@@ -107,6 +107,7 @@
     depends_on:
       - seata-mysql
       - seata-server
+      - account-service
 
   transaction-test:
     type: test
diff --git a/dubbo-samples-version/case-configuration.yml b/dubbo-samples-version/case-configuration.yml
index 8747bac..4c817b3 100644
--- a/dubbo-samples-version/case-configuration.yml
+++ b/dubbo-samples-version/case-configuration.yml
@@ -26,6 +26,9 @@
       - zookeeper.address=zookeeper
     waitPortsBeforeRun:
       - zookeeper:2181
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - zookeeper
 
@@ -37,6 +40,9 @@
       - zookeeper.address=zookeeper
     waitPortsBeforeRun:
       - zookeeper:2181
+    checkPorts:
+      - 20882
+    checkLog: "dubbo service started"
     depends_on:
       - zookeeper
 
diff --git a/dubbo-samples-zipkin/case-configuration.yml b/dubbo-samples-zipkin/case-configuration.yml
index 2576256..6568123 100644
--- a/dubbo-samples-zipkin/case-configuration.yml
+++ b/dubbo-samples-zipkin/case-configuration.yml
@@ -32,6 +32,9 @@
     waitPortsBeforeRun:
       - zookeeper:2181
       - zipkin:9411
+    checkPorts:
+      - 20880
+    checkLog: "dubbo service started"
     depends_on:
       - zookeeper
       - zipkin
@@ -47,27 +50,14 @@
       - zookeeper:2181
       - zipkin:9411
       - dubbo-samples-zipkin-hello:20880
+    checkPorts:
+      - 20881
+    checkLog: "dubbo service started"
     depends_on:
       - zookeeper
       - zipkin
       - dubbo-samples-zipkin-hello
 
-  dubbo-samples-zipkin-client:
-    type: app
-    basedir: .
-    mainClass: org.apache.dubbo.samples.client.Application
-    systemProps:
-      - zookeeper.address=zookeeper
-      - zipkin.address=zipkin
-      - dubbo-samples-zipkin-greeting:20881
-    waitPortsBeforeRun:
-      - zookeeper:2181
-      - zipkin:9411
-    depends_on:
-      - zookeeper
-      - zipkin
-      - dubbo-samples-zipkin-greeting
-
   dubbo-samples-zipkin-test:
     type: test
     basedir: .
@@ -83,4 +73,5 @@
     depends_on:
       - zookeeper
       - zipkin
-      - dubbo-samples-zipkin-client
+      - dubbo-samples-zipkin-greeting
+      - dubbo-samples-zipkin-hello
diff --git a/test/dubbo-scenario-builder/src/main/resources/scenario.sh b/test/dubbo-scenario-builder/src/main/resources/scenario.sh
index b09f98e..f264d19 100644
--- a/test/dubbo-scenario-builder/src/main/resources/scenario.sh
+++ b/test/dubbo-scenario-builder/src/main/resources/scenario.sh
@@ -184,9 +184,12 @@
     ${removeImagesScript}
 else
     for service_name in ${service_names[@]};do
-        echo "docker inspect ${project_name}_${service_name}_1 :"
-        docker inspect ${project_name}_${service_name}_1 >> $scenario_log
-        echo ""
+        service_container_name=${project_name}_${service_name}_1
+        echo "docker inspect $service_container_name  :" >> $scenario_log
+        docker inspect $service_container_name >> $scenario_log
+        echo "" >> $scenario_log
+
+        docker logs -f $service_container_name &> $SCENARIO_HOME/logs/${service_name}.log
     done
 fi
 
diff --git a/test/dubbo-test-runner/pom.xml b/test/dubbo-test-runner/pom.xml
index b91e715..e6bdbe8 100644
--- a/test/dubbo-test-runner/pom.xml
+++ b/test/dubbo-test-runner/pom.xml
@@ -57,6 +57,15 @@
     <build>
         <plugins>
             <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.7.0</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+            <plugin>
                 <artifactId>maven-assembly-plugin</artifactId>
                 <version>3.3.0</version>
                 <configuration>
diff --git a/test/dubbo-test-runner/src/docker/run-dubbo-test.sh b/test/dubbo-test-runner/src/docker/run-dubbo-test.sh
index 1f1640e..2ae882e 100755
--- a/test/dubbo-test-runner/src/docker/run-dubbo-test.sh
+++ b/test/dubbo-test-runner/src/docker/run-dubbo-test.sh
@@ -23,6 +23,11 @@
   fi
 fi
 
+# At least delay 1 second
+if [ $RUN_DELAY -le 0 ]; then
+  RUN_DELAY=1
+fi
+
 #delay start
 if [ $RUN_DELAY -gt 0 ]; then
   echo "Delay $RUN_DELAY s."
@@ -32,7 +37,11 @@
 # run testcase
 echo "Running tests ..."
 report_dir=$DIR/app/test-reports
-java $JAVA_OPTS $DEBUG_OPTS -jar dubbo-test-runner.jar "$TEST_CLASSES_DIR" "$APP_CLASSES_DIR" "$APP_DEPENDENCY_DIR" "$report_dir" "$TEST_PATTERNS" 2>&1
+
+# Fix Class loading problem in java9+: CompletableFuture.supplyAsync() is executed in the ForkJoinWorkerThread
+# and it only uses system classloader to load classes instead of the IsolatedClassLoader
+classpath=dubbo-test-runner.jar:$TEST_CLASSES_DIR:$APP_CLASSES_DIR:$APP_DEPENDENCY_DIR/*
+java $JAVA_OPTS $DEBUG_OPTS -cp $classpath org.apache.dubbo.test.runner.TestRunnerMain "$TEST_CLASSES_DIR" "$APP_CLASSES_DIR" "$APP_DEPENDENCY_DIR" "$report_dir" "$TEST_PATTERNS" 2>&1
 result=$?
 if [ $result -ne 0 ]; then
   echo "Run tests failure"
diff --git a/test/dubbo-test-runner/src/main/java/org/apache/dubbo/test/runner/ClassloaderSurefireStarter.java b/test/dubbo-test-runner/src/main/java/org/apache/dubbo/test/runner/ClassloaderSurefireStarter.java
new file mode 100644
index 0000000..47bd341
--- /dev/null
+++ b/test/dubbo-test-runner/src/main/java/org/apache/dubbo/test/runner/ClassloaderSurefireStarter.java
@@ -0,0 +1,86 @@
+package org.apache.dubbo.test.runner;
+/*
+ * 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.
+ */
+
+import org.apache.maven.plugin.surefire.CommonReflector;
+import org.apache.maven.plugin.surefire.StartupReportConfiguration;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.surefire.booter.ClasspathConfiguration;
+import org.apache.maven.surefire.booter.ProviderConfiguration;
+import org.apache.maven.surefire.booter.StartupConfiguration;
+import org.apache.maven.surefire.booter.SurefireExecutionException;
+import org.apache.maven.surefire.suite.RunResult;
+import org.apache.maven.surefire.testset.TestSetFailedException;
+import org.apache.maven.surefire.util.DefaultScanResult;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Map;
+
+import static org.apache.maven.surefire.booter.ProviderFactory.invokeProvider;
+
+/**
+ * Starts the provider in specify classloader.
+ */
+public class ClassloaderSurefireStarter
+{
+    private final StartupConfiguration startupConfig;
+    private final StartupReportConfiguration startupReportConfig;
+    private final ProviderConfiguration providerConfig;
+    private final ConsoleLogger consoleLogger;
+    private ClassLoader testClassLoader;
+
+    public ClassloaderSurefireStarter(StartupConfiguration startupConfig,
+                                      ProviderConfiguration providerConfig,
+                                      StartupReportConfiguration startupReportConfig,
+                                      ConsoleLogger consoleLogger,
+                                      ClassLoader testClassLoader)
+    {
+        this.startupConfig = startupConfig;
+        this.startupReportConfig = startupReportConfig;
+        this.providerConfig = providerConfig;
+        this.consoleLogger = consoleLogger;
+        this.testClassLoader = testClassLoader;
+    }
+
+    public RunResult runSuitesInProcess( DefaultScanResult scanResult )
+        throws SurefireExecutionException, TestSetFailedException
+    {
+        // The test classloader must be constructed first to avoid issues with commons-logging until we properly
+        // separate the TestNG classloader
+
+        Map<String, String> providerProperties = providerConfig.getProviderProperties();
+        scanResult.writeTo( providerProperties );
+
+        startupConfig.writeSurefireTestClasspathProperty();
+
+        CommonReflector surefireReflector = new CommonReflector(testClassLoader);
+
+        Object factory = surefireReflector.createReportingReporterFactory( startupReportConfig, consoleLogger );
+
+        try
+        {
+            return invokeProvider( null, testClassLoader, factory, providerConfig, false, startupConfig, true );
+        }
+        catch ( InvocationTargetException e )
+        {
+            throw new SurefireExecutionException( "Exception in provider", e.getTargetException() );
+        }
+    }
+
+}
diff --git a/test/dubbo-test-runner/src/main/java/org/apache/dubbo/test/runner/TestRunnerMain.java b/test/dubbo-test-runner/src/main/java/org/apache/dubbo/test/runner/TestRunnerMain.java
index 9363ae0..11d7784 100644
--- a/test/dubbo-test-runner/src/main/java/org/apache/dubbo/test/runner/TestRunnerMain.java
+++ b/test/dubbo-test-runner/src/main/java/org/apache/dubbo/test/runner/TestRunnerMain.java
@@ -172,10 +172,16 @@
 
 
         DefaultScanResult scanResult = getScanResult(testClassesDir, tests);
-
         ConsoleLogger consoleLogger = new PrintStreamLogger(System.out);
-        InPluginVMSurefireStarter testStarter = new InPluginVMSurefireStarter(startupConfiguration, providerConfiguration,
-                startupReportConfiguration, consoleLogger);
+
+        // Fix Class loading problem in java9+:
+        // CompletableFuture.supplyAsync() is executed in the ForkJoinWorkerThread
+        // and it only uses system classloader to load classes instead of the IsolatedClassLoader
+        ClassloaderSurefireStarter testStarter = new ClassloaderSurefireStarter(startupConfiguration, providerConfiguration,
+                startupReportConfiguration, consoleLogger, ClassLoader.getSystemClassLoader());
+//        InPluginVMSurefireStarter testStarter = new InPluginVMSurefireStarter(startupConfiguration, providerConfiguration,
+//                startupReportConfiguration, consoleLogger);
+
         RunResult runResult = testStarter.runSuitesInProcess(scanResult);
         boolean runSuccess = runResult.getCompletedCount() > 0 && runResult.isErrorFree() && !runResult.isTimeout();
 
diff --git a/test/run-tests.sh b/test/run-tests.sh
index 98aed23..5075108 100755
--- a/test/run-tests.sh
+++ b/test/run-tests.sh
@@ -62,7 +62,7 @@
 CONFIG_FILE="case-configuration.yml"
 VERSONS_FILE="case-versions.conf"
 
-mkdir $DIR/jobs
+mkdir -p $DIR/jobs
 testListFile=$DIR/jobs/testjob.txt
 targetTestcases=$1
 if [ "$targetTestcases" != "" ];then
@@ -102,6 +102,7 @@
 #clear test results
 testResultFile=${testListFile%.*}-result-java${JAVA_VER}.txt
 rm -f $testResultFile
+touch $testResultFile
 echo "Test results: $testResultFile"
 
 if [ "$CANDIDATE_VERSIONS" == "" ];then
@@ -320,6 +321,10 @@
     sleep 1
     if [ -f $testResultFile ]; then
       finishedTest=`grep "" -c $testResultFile`
+      if [ "$finishedTest" == "" ];then
+        finishedTest=0
+        continue
+      fi
       # check fail fast
       if [ "$FAIL_FAST" == "1" ]; then
         failedTest=`grep "$TEST_FAILURE" -c $testResultFile`