You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by ra...@apache.org on 2021/07/29 06:19:21 UTC

[dubbo-admin] branch develop-for-dubbo-3.x updated: [3.0]Add mesh rule route (#789)

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

ranke pushed a commit to branch develop-for-dubbo-3.x
in repository https://gitbox.apache.org/repos/asf/dubbo-admin.git


The following commit(s) were added to refs/heads/develop-for-dubbo-3.x by this push:
     new a9925f5  [3.0]Add mesh rule route (#789)
a9925f5 is described below

commit a9925f55903caf6193f8207b99d0e601076ae319
Author: haoyann <10...@qq.com>
AuthorDate: Thu Jul 29 14:19:12 2021 +0800

    [3.0]Add mesh rule route (#789)
    
    * add mesh rule route
    
    * add mesh rule check
---
 .../apache/dubbo/admin/common/util/Constants.java  |   2 +-
 .../apache/dubbo/admin/common/util/YamlParser.java |  10 +-
 .../admin/controller/MeshRouteController.java      | 105 +++++
 .../apache/dubbo/admin/model/dto/MeshRouteDTO.java |  32 ++
 .../dubbo/admin/model/store/mesh/BaseRule.java     |  60 +++
 .../admin/model/store/mesh/VsDestinationGroup.java |  56 +++
 .../mesh/destination/ConnectionPoolSettings.java   |  22 ++
 .../store/mesh/destination/DestinationRule.java    |  41 ++
 .../mesh/destination/DestinationRuleSpec.java      |  60 +++
 .../admin/model/store/mesh/destination/Subset.java |  50 +++
 .../model/store/mesh/destination/TCPSettings.java  |  25 ++
 .../model/store/mesh/destination/TcpKeepalive.java |  26 ++
 .../store/mesh/destination/TrafficPolicy.java      |  40 ++
 .../destination/loadbalance/ConsistentHashLB.java  |  22 ++
 .../loadbalance/LoadBalancerSettings.java          |  48 +++
 .../mesh/destination/loadbalance/SimpleLB.java     |  26 ++
 .../mesh/virtualservice/DubboMatchRequest.java     | 131 +++++++
 .../store/mesh/virtualservice/DubboRoute.java      |  63 +++
 .../mesh/virtualservice/DubboRouteDetail.java      |  63 +++
 .../mesh/virtualservice/VirtualServiceRule.java    |  41 ++
 .../mesh/virtualservice/VirtualServiceSpec.java    |  50 +++
 .../destination/DubboDestination.java              |  59 +++
 .../destination/DubboRouteDestination.java         |  40 ++
 .../store/mesh/virtualservice/match/BoolMatch.java |  38 ++
 .../mesh/virtualservice/match/DoubleMatch.java     |  63 +++
 .../virtualservice/match/DoubleRangeMatch.java     |  53 +++
 .../virtualservice/match/DubboAttachmentMatch.java |  76 ++++
 .../mesh/virtualservice/match/DubboMethodArg.java  |  90 +++++
 .../virtualservice/match/DubboMethodMatch.java     | 128 +++++++
 .../mesh/virtualservice/match/ListBoolMatch.java   |  22 ++
 .../mesh/virtualservice/match/ListDoubleMatch.java |  43 +++
 .../mesh/virtualservice/match/ListStringMatch.java |  44 +++
 .../mesh/virtualservice/match/StringMatch.java     | 105 +++++
 .../dubbo/admin/service/MeshRouteService.java      |  56 +++
 .../admin/service/impl/MeshRouteServiceImpl.java   |  90 +++++
 .../admin/controller/MeshRouteControllerTest.java  | 141 +++++++
 .../src/test/resources/MeshRoute.yml               |  58 +++
 .../src/test/resources/MeshRouteTest2.yml          |  41 ++
 dubbo-admin-ui/src/api/menu.js                     |   3 +-
 .../src/components/governance/MeshRule.vue         | 422 +++++++++++++++++++++
 dubbo-admin-ui/src/lang/en.js                      |   4 +
 dubbo-admin-ui/src/lang/zh.js                      |   4 +
 dubbo-admin-ui/src/router/index.js                 |   9 +
 43 files changed, 2558 insertions(+), 4 deletions(-)

diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
index f98a0d9..96e3f24 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
@@ -79,7 +79,7 @@ public class Constants {
     public static final String METRICS_PROTOCOL = "metrics.protocol";
     public static final Set<String> CONFIGS = new HashSet<>();
     public static final String COLON = ":";
-
+    public static final String MESH_RULE_SUFFIX = ".MESHAPPRULE";
     static {
         CONFIGS.add(WEIGHT);
         CONFIGS.add(BALANCING);
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java
index 024097d..81ec3b3 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java
@@ -17,7 +17,7 @@
 
 package org.apache.dubbo.admin.common.util;
 
-import org.apache.dubbo.common.utils.PojoUtils;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.yaml.snakeyaml.Yaml;
 import org.yaml.snakeyaml.constructor.SafeConstructor;
 import org.yaml.snakeyaml.error.YAMLException;
@@ -30,6 +30,8 @@ import java.util.Map;
 
 public class YamlParser {
 
+    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
     public static String dumpObject(Object object) {
         return new Yaml(new SafeConstructor(), new CustomRepresenter()).dumpAsMap(object);
     }
@@ -37,12 +39,16 @@ public class YamlParser {
     public static <T> T loadObject(String content, Class<T> type) {
         Map<String, Object> map = new Yaml(new SafeConstructor(), new CustomRepresenter()).load(content);
         try {
-            return (T) PojoUtils.mapToPojo(map, type);
+            return OBJECT_MAPPER.convertValue(map, type);
         } catch (Exception e) {
             throw new YAMLException(e);
         }
     }
 
+    public static Iterable<Object> loadAll(String content) {
+        return new Yaml(new SafeConstructor(), new CustomRepresenter()).loadAll(content);
+    }
+
     public static class CustomRepresenter extends Representer {
 
         protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MeshRouteController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MeshRouteController.java
new file mode 100644
index 0000000..537ca0c
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MeshRouteController.java
@@ -0,0 +1,105 @@
+/*
+ * 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.admin.controller;
+
+import org.apache.dubbo.admin.annotation.Authority;
+import org.apache.dubbo.admin.common.exception.ParamValidationException;
+import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.model.dto.MeshRouteDTO;
+import org.apache.dubbo.admin.service.MeshRouteService;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Authority(needLogin = true)
+@RestController
+@RequestMapping("/api/{env}/rules/route/mesh")
+public class MeshRouteController {
+
+    private final MeshRouteService meshRouteService;
+
+    @Autowired
+    public MeshRouteController(MeshRouteService meshRouteService) {
+        this.meshRouteService = meshRouteService;
+    }
+
+    @RequestMapping(method = RequestMethod.POST)
+    @ResponseStatus(HttpStatus.CREATED)
+    public boolean createMeshRoute(@RequestBody MeshRouteDTO meshRoute, @PathVariable String env) {
+        String app = meshRoute.getApplication();
+        if (StringUtils.isEmpty(app)) {
+            throw new ParamValidationException("app is Empty!");
+        }
+        // todo check appName
+
+        return meshRouteService.createMeshRule(meshRoute);
+    }
+
+    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
+    public boolean updateRule(@PathVariable String id, @RequestBody MeshRouteDTO meshRoute, @PathVariable String env) {
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
+        if (meshRouteService.findMeshRoute(id) == null) {
+            throw new ResourceNotFoundException("can not find mesh route, Id: " + id);
+        }
+        meshRoute.setId(id);
+        return meshRouteService.updateMeshRule(meshRoute);
+    }
+
+    @RequestMapping(method = RequestMethod.GET)
+    public List<MeshRouteDTO> searchRoutes(@RequestParam String application, @PathVariable String env) {
+        if (StringUtils.isBlank(application)) {
+            throw new ParamValidationException("application is required.");
+        }
+        List<MeshRouteDTO> result = new ArrayList<>();
+
+        MeshRouteDTO meshRoute = meshRouteService.findMeshRoute(application);
+        if (meshRoute != null) {
+            result.add(meshRoute);
+        }
+        return result;
+    }
+
+    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
+    public MeshRouteDTO detailRoute(@PathVariable String id, @PathVariable String env) {
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
+        MeshRouteDTO meshRoute = meshRouteService.findMeshRoute(id);
+        if (meshRoute == null) {
+            throw new ResourceNotFoundException("Unknown ID!");
+        }
+        return meshRoute;
+    }
+
+    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
+    public boolean deleteRoute(@PathVariable String id, @PathVariable String env) {
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
+        return meshRouteService.deleteMeshRule(id);
+    }
+
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MeshRouteDTO.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MeshRouteDTO.java
new file mode 100644
index 0000000..349c3c0
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MeshRouteDTO.java
@@ -0,0 +1,32 @@
+/*
+ * 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.admin.model.dto;
+
+public class MeshRouteDTO extends BaseDTO{
+
+    private String meshRule;
+
+    public String getMeshRule() {
+        return meshRule;
+    }
+
+    public void setMeshRule(String meshRule) {
+        this.meshRule = meshRule;
+    }
+
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/BaseRule.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/BaseRule.java
new file mode 100644
index 0000000..94e7afd
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/BaseRule.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.admin.model.store.mesh;
+
+import java.util.Map;
+
+
+public class BaseRule {
+    private String apiVersion;
+    private String kind;
+    private Map<String,String> metadata;
+
+    public String getApiVersion() {
+        return apiVersion;
+    }
+
+    public void setApiVersion(String apiVersion) {
+        this.apiVersion = apiVersion;
+    }
+
+    public String getKind() {
+        return kind;
+    }
+
+    public void setKind(String kind) {
+        this.kind = kind;
+    }
+
+    public Map<String, String> getMetadata() {
+        return metadata;
+    }
+
+    public void setMetadata(Map<String, String> metadata) {
+        this.metadata = metadata;
+    }
+
+    @Override
+    public String toString() {
+        return "BaseRule{" +
+                "apiVersion='" + apiVersion + '\'' +
+                ", kind='" + kind + '\'' +
+                ", metadata=" + metadata +
+                '}';
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/VsDestinationGroup.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/VsDestinationGroup.java
new file mode 100644
index 0000000..8c99863
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/VsDestinationGroup.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.admin.model.store.mesh;
+
+
+import org.apache.dubbo.admin.model.store.mesh.destination.DestinationRule;
+import org.apache.dubbo.admin.model.store.mesh.virtualservice.VirtualServiceRule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class VsDestinationGroup {
+    private String appName;
+    private List<VirtualServiceRule> virtualServiceRuleList = new ArrayList<>();
+    private List<DestinationRule> destinationRuleList = new ArrayList<>();
+
+    public String getAppName() {
+        return appName;
+    }
+
+    public void setAppName(String appName) {
+        this.appName = appName;
+    }
+
+    public List<VirtualServiceRule> getVirtualServiceRuleList() {
+        return virtualServiceRuleList;
+    }
+
+    public void setVirtualServiceRuleList(List<VirtualServiceRule> virtualServiceRuleList) {
+        this.virtualServiceRuleList = virtualServiceRuleList;
+    }
+
+    public List<DestinationRule> getDestinationRuleList() {
+        return destinationRuleList;
+    }
+
+    public void setDestinationRuleList(List<DestinationRule> destinationRuleList) {
+        this.destinationRuleList = destinationRuleList;
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/ConnectionPoolSettings.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/ConnectionPoolSettings.java
new file mode 100644
index 0000000..71a5c43
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/ConnectionPoolSettings.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.admin.model.store.mesh.destination;
+
+
+public class ConnectionPoolSettings {
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRule.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRule.java
new file mode 100644
index 0000000..9b0d8c6
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRule.java
@@ -0,0 +1,41 @@
+/*
+ * 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.admin.model.store.mesh.destination;
+
+
+import org.apache.dubbo.admin.model.store.mesh.BaseRule;
+
+public class DestinationRule extends BaseRule {
+    private DestinationRuleSpec spec;
+
+    public DestinationRuleSpec getSpec() {
+        return spec;
+    }
+
+    public void setSpec(DestinationRuleSpec spec) {
+        this.spec = spec;
+    }
+
+    @Override
+    public String toString() {
+        return "DestinationRule{" +
+                "base=" + super.toString() +
+                ", spec=" + spec +
+                '}';
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRuleSpec.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRuleSpec.java
new file mode 100644
index 0000000..470b7c4
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRuleSpec.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.admin.model.store.mesh.destination;
+
+import java.util.List;
+
+
+public class DestinationRuleSpec {
+    private String host;
+    private List<Subset> subsets;
+    private TrafficPolicy trafficPolicy;
+
+    public String getHost() {
+        return host;
+    }
+
+    public void setHost(String host) {
+        this.host = host;
+    }
+
+    public List<Subset> getSubsets() {
+        return subsets;
+    }
+
+    public void setSubsets(List<Subset> subsets) {
+        this.subsets = subsets;
+    }
+
+    public TrafficPolicy getTrafficPolicy() {
+        return trafficPolicy;
+    }
+
+    public void setTrafficPolicy(TrafficPolicy trafficPolicy) {
+        this.trafficPolicy = trafficPolicy;
+    }
+
+    @Override
+    public String toString() {
+        return "DestinationRuleSpec{" +
+                "host='" + host + '\'' +
+                ", subsets=" + subsets +
+                ", trafficPolicy=" + trafficPolicy +
+                '}';
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/Subset.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/Subset.java
new file mode 100644
index 0000000..66b6fa4
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/Subset.java
@@ -0,0 +1,50 @@
+/*
+ * 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.admin.model.store.mesh.destination;
+
+import java.util.Map;
+
+
+public class Subset {
+    private String name;
+    private Map<String, String> labels;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Map<String, String> getLabels() {
+        return labels;
+    }
+
+    public void setLabels(Map<String, String> labels) {
+        this.labels = labels;
+    }
+
+    @Override
+    public String toString() {
+        return "Subset{" +
+                "name='" + name + '\'' +
+                ", labels=" + labels +
+                '}';
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TCPSettings.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TCPSettings.java
new file mode 100644
index 0000000..1cc05ce
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TCPSettings.java
@@ -0,0 +1,25 @@
+/*
+ * 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.admin.model.store.mesh.destination;
+
+
+public class TCPSettings {
+    private int maxConnections;
+    private int connectTimeout;
+    private TcpKeepalive tcpKeepalive;
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TcpKeepalive.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TcpKeepalive.java
new file mode 100644
index 0000000..aa48bf6
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TcpKeepalive.java
@@ -0,0 +1,26 @@
+/*
+ * 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.admin.model.store.mesh.destination;
+
+
+public class TcpKeepalive {
+    private int probes;
+    private int time;
+    private int interval;
+
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TrafficPolicy.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TrafficPolicy.java
new file mode 100644
index 0000000..bda74d6
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TrafficPolicy.java
@@ -0,0 +1,40 @@
+/*
+ * 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.admin.model.store.mesh.destination;
+
+
+import org.apache.dubbo.admin.model.store.mesh.destination.loadbalance.LoadBalancerSettings;
+
+public class TrafficPolicy {
+    private LoadBalancerSettings loadBalancer;
+
+    public LoadBalancerSettings getLoadBalancer() {
+        return loadBalancer;
+    }
+
+    public void setLoadBalancer(LoadBalancerSettings loadBalancer) {
+        this.loadBalancer = loadBalancer;
+    }
+
+    @Override
+    public String toString() {
+        return "TrafficPolicy{" +
+                "loadBalancer=" + loadBalancer +
+                '}';
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/ConsistentHashLB.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/ConsistentHashLB.java
new file mode 100644
index 0000000..e0c11e4
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/ConsistentHashLB.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.admin.model.store.mesh.destination.loadbalance;
+
+
+public class ConsistentHashLB {
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/LoadBalancerSettings.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/LoadBalancerSettings.java
new file mode 100644
index 0000000..5a5a1ec
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/LoadBalancerSettings.java
@@ -0,0 +1,48 @@
+/*
+ * 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.admin.model.store.mesh.destination.loadbalance;
+
+
+public class LoadBalancerSettings {
+    private SimpleLB simple;
+    private ConsistentHashLB consistentHash;
+
+    public SimpleLB getSimple() {
+        return simple;
+    }
+
+    public void setSimple(SimpleLB simple) {
+        this.simple = simple;
+    }
+
+    public ConsistentHashLB getConsistentHash() {
+        return consistentHash;
+    }
+
+    public void setConsistentHash(ConsistentHashLB consistentHash) {
+        this.consistentHash = consistentHash;
+    }
+
+    @Override
+    public String toString() {
+        return "LoadBalancerSettings{" +
+                "simple=" + simple +
+                ", consistentHash=" + consistentHash +
+                '}';
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/SimpleLB.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/SimpleLB.java
new file mode 100644
index 0000000..b8b13ec
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/SimpleLB.java
@@ -0,0 +1,26 @@
+/*
+ * 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.admin.model.store.mesh.destination.loadbalance;
+
+
+public enum SimpleLB {
+    ROUND_ROBIN,
+    LEAST_CONN,
+    RANDOM,
+    PASSTHROUGH
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboMatchRequest.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboMatchRequest.java
new file mode 100644
index 0000000..59dcd3c
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboMatchRequest.java
@@ -0,0 +1,131 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice;
+
+
+import org.apache.dubbo.admin.model.store.mesh.virtualservice.match.DoubleMatch;
+import org.apache.dubbo.admin.model.store.mesh.virtualservice.match.DubboAttachmentMatch;
+import org.apache.dubbo.admin.model.store.mesh.virtualservice.match.DubboMethodMatch;
+import org.apache.dubbo.admin.model.store.mesh.virtualservice.match.StringMatch;
+
+import java.util.Map;
+
+
+public class DubboMatchRequest {
+    private String name;
+    private DubboMethodMatch method;
+    private Map<String, String> sourceLabels;
+    private DubboAttachmentMatch attachments;
+    private Map<String, StringMatch> headers;
+    private DoubleMatch threshold;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public DubboMethodMatch getMethod() {
+        return method;
+    }
+
+    public void setMethod(DubboMethodMatch method) {
+        this.method = method;
+    }
+
+    public Map<String, String> getSourceLabels() {
+        return sourceLabels;
+    }
+
+    public void setSourceLabels(Map<String, String> sourceLabels) {
+        this.sourceLabels = sourceLabels;
+    }
+
+    public DubboAttachmentMatch getAttachments() {
+        return attachments;
+    }
+
+    public void setAttachments(DubboAttachmentMatch attachments) {
+        this.attachments = attachments;
+    }
+
+    public Map<String, StringMatch> getHeaders() {
+        return headers;
+    }
+
+    public void setHeaders(Map<String, StringMatch> headers) {
+        this.headers = headers;
+    }
+
+    public DoubleMatch getThreshold() {
+        return threshold;
+    }
+
+    public void setThreshold(DoubleMatch threshold) {
+        this.threshold = threshold;
+    }
+
+
+    public static boolean isMatch(DubboMatchRequest dubboMatchRequest,
+                                  String methodName, String[] parameterTypeList, Object[] parameters,
+                                  Map<String, String> sourceLabels,
+                                  Map<String, String> eagleeyeContext, Map<String, String> dubboContext,
+                                  Map<String, String> headers
+    ) {
+        if (dubboMatchRequest.getMethod() != null) {
+            if (!DubboMethodMatch.isMatch(dubboMatchRequest.getMethod(), methodName, parameterTypeList, parameters)) {
+                return false;
+            }
+        }
+
+        if (dubboMatchRequest.getSourceLabels() != null) {
+            for (Map.Entry<String, String> entry : dubboMatchRequest.getSourceLabels().entrySet()) {
+                String value = sourceLabels.get(entry.getKey());
+                if (value == null || !entry.getValue().equals(value)) {
+                    return false;
+                }
+            }
+        }
+
+        if (dubboMatchRequest.getAttachments() != null) {
+            if (!DubboAttachmentMatch.isMatch(dubboMatchRequest.getAttachments(),eagleeyeContext,dubboContext)){
+                return false;
+            }
+        }
+
+        //TODO headers
+
+
+        return true;
+
+    }
+
+    @Override
+    public String toString() {
+        return "DubboMatchRequest{" +
+                "name='" + name + '\'' +
+                ", method=" + method +
+                ", sourceLabels=" + sourceLabels +
+                ", attachments=" + attachments +
+                ", headers=" + headers +
+                ", threshold=" + threshold +
+                '}';
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRoute.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRoute.java
new file mode 100644
index 0000000..9747b6b
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRoute.java
@@ -0,0 +1,63 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice;
+
+
+import org.apache.dubbo.admin.model.store.mesh.virtualservice.match.StringMatch;
+
+import java.util.List;
+
+
+public class DubboRoute {
+    private String name;
+    private List<StringMatch> services;
+    private List<DubboRouteDetail> routedetail;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public List<StringMatch> getServices() {
+        return services;
+    }
+
+    public void setServices(List<StringMatch> services) {
+        this.services = services;
+    }
+
+    public List<DubboRouteDetail> getRoutedetail() {
+        return routedetail;
+    }
+
+    public void setRoutedetail(List<DubboRouteDetail> routedetail) {
+        this.routedetail = routedetail;
+    }
+
+    @Override
+    public String toString() {
+        return "DubboRoute{" +
+                "name='" + name + '\'' +
+                ", services=" + services +
+                ", routedetail=" + routedetail +
+                '}';
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRouteDetail.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRouteDetail.java
new file mode 100644
index 0000000..1b576d5
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRouteDetail.java
@@ -0,0 +1,63 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice;
+
+
+import org.apache.dubbo.admin.model.store.mesh.virtualservice.destination.DubboRouteDestination;
+
+import java.util.List;
+
+
+public class DubboRouteDetail {
+    private String name;
+    private List<DubboMatchRequest> match;
+    private List<DubboRouteDestination> route;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public List<DubboMatchRequest> getMatch() {
+        return match;
+    }
+
+    public void setMatch(List<DubboMatchRequest> match) {
+        this.match = match;
+    }
+
+    public List<DubboRouteDestination> getRoute() {
+        return route;
+    }
+
+    public void setRoute(List<DubboRouteDestination> route) {
+        this.route = route;
+    }
+
+    @Override
+    public String toString() {
+        return "DubboRouteDetail{" +
+                "name='" + name + '\'' +
+                ", match=" + match +
+                ", route=" + route +
+                '}';
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceRule.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceRule.java
new file mode 100644
index 0000000..c5798d8
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceRule.java
@@ -0,0 +1,41 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice;
+
+
+import org.apache.dubbo.admin.model.store.mesh.BaseRule;
+
+public class VirtualServiceRule extends BaseRule {
+    private VirtualServiceSpec spec;
+
+    public VirtualServiceSpec getSpec() {
+        return spec;
+    }
+
+    public void setSpec(VirtualServiceSpec spec) {
+        this.spec = spec;
+    }
+
+    @Override
+    public String toString() {
+        return "VirtualServiceRule{" +
+                "base=" + super.toString() +
+                ", spec=" + spec +
+                '}';
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceSpec.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceSpec.java
new file mode 100644
index 0000000..c4eab8d
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceSpec.java
@@ -0,0 +1,50 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice;
+
+import java.util.List;
+
+
+public class VirtualServiceSpec {
+    private List<String> hosts;
+    private List<DubboRoute> dubbo;
+
+    public List<String> getHosts() {
+        return hosts;
+    }
+
+    public void setHosts(List<String> hosts) {
+        this.hosts = hosts;
+    }
+
+    public List<DubboRoute> getDubbo() {
+        return dubbo;
+    }
+
+    public void setDubbo(List<DubboRoute> dubbo) {
+        this.dubbo = dubbo;
+    }
+
+    @Override
+    public String toString() {
+        return "VirtualServiceSpec{" +
+                "hosts=" + hosts +
+                ", dubbo=" + dubbo +
+                '}';
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboDestination.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboDestination.java
new file mode 100644
index 0000000..781308e
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboDestination.java
@@ -0,0 +1,59 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice.destination;
+
+
+public class DubboDestination {
+    private String host;
+    private String subset;
+    private int port;
+    private DubboRouteDestination fallback;
+
+
+    public String getHost() {
+        return host;
+    }
+
+    public void setHost(String host) {
+        this.host = host;
+    }
+
+    public String getSubset() {
+        return subset;
+    }
+
+    public void setSubset(String subset) {
+        this.subset = subset;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public DubboRouteDestination getFallback() {
+        return fallback;
+    }
+
+    public void setFallback(DubboRouteDestination fallback) {
+        this.fallback = fallback;
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboRouteDestination.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboRouteDestination.java
new file mode 100644
index 0000000..95ede77
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboRouteDestination.java
@@ -0,0 +1,40 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice.destination;
+
+
+public class DubboRouteDestination {
+    private DubboDestination destination;
+    private int weight;
+
+    public DubboDestination getDestination() {
+        return destination;
+    }
+
+    public void setDestination(DubboDestination destination) {
+        this.destination = destination;
+    }
+
+    public int getWeight() {
+        return weight;
+    }
+
+    public void setWeight(int weight) {
+        this.weight = weight;
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/BoolMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/BoolMatch.java
new file mode 100644
index 0000000..d354157
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/BoolMatch.java
@@ -0,0 +1,38 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice.match;
+
+
+public class BoolMatch {
+    private Boolean exact;
+
+    public Boolean getExact() {
+        return exact;
+    }
+
+    public void setExact(Boolean exact) {
+        this.exact = exact;
+    }
+
+    public static boolean isMatch(BoolMatch boolMatch,boolean input){
+        if (boolMatch.getExact() != null){
+            return input == boolMatch.getExact();
+        }
+        return false;
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleMatch.java
new file mode 100644
index 0000000..89ab4d6
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleMatch.java
@@ -0,0 +1,63 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice.match;
+
+
+public class DoubleMatch {
+    private Double exact;
+    private DoubleRangeMatch range;
+    private Double mod;
+
+    public Double getExact() {
+        return exact;
+    }
+
+    public void setExact(Double exact) {
+        this.exact = exact;
+    }
+
+    public DoubleRangeMatch getRange() {
+        return range;
+    }
+
+    public void setRange(DoubleRangeMatch range) {
+        this.range = range;
+    }
+
+    public Double getMod() {
+        return mod;
+    }
+
+    public void setMod(Double mod) {
+        this.mod = mod;
+    }
+
+
+    public static boolean isMatch(DoubleMatch doubleMatch, Double input) {
+        if (doubleMatch.getExact() != null && doubleMatch.getMod() == null) {
+            return input.equals(doubleMatch.getExact());
+        } else if (doubleMatch.getRange() != null) {
+            return DoubleRangeMatch.isMatch(doubleMatch.getRange(), input);
+        } else if (doubleMatch.getExact() != null && doubleMatch.getMod() != null) {
+            Double result = input % doubleMatch.getMod();
+            return result.equals(doubleMatch.getExact());
+        }
+
+        return false;
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleRangeMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleRangeMatch.java
new file mode 100644
index 0000000..00d09db
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleRangeMatch.java
@@ -0,0 +1,53 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice.match;
+
+
+public class DoubleRangeMatch {
+    private Double start;
+    private Double end;
+
+    public Double getStart() {
+        return start;
+    }
+
+    public void setStart(Double start) {
+        this.start = start;
+    }
+
+    public Double getEnd() {
+        return end;
+    }
+
+    public void setEnd(Double end) {
+        this.end = end;
+    }
+
+
+    public static boolean isMatch(DoubleRangeMatch doubleRangeMatch, Double input) {
+        if (doubleRangeMatch.getStart() != null && doubleRangeMatch.getEnd() != null) {
+            return input.compareTo(doubleRangeMatch.getStart()) >= 0 && input.compareTo(doubleRangeMatch.getEnd()) < 0;
+        } else if (doubleRangeMatch.getStart() != null) {
+            return input.compareTo(doubleRangeMatch.getStart()) >= 0;
+        } else if (doubleRangeMatch.getEnd() != null) {
+            return input.compareTo(doubleRangeMatch.getEnd()) < 0;
+        } else {
+            return false;
+        }
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboAttachmentMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboAttachmentMatch.java
new file mode 100644
index 0000000..37f1da4
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboAttachmentMatch.java
@@ -0,0 +1,76 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice.match;
+
+import java.util.Map;
+
+
+public class DubboAttachmentMatch {
+    private Map<String, StringMatch> eagleeyecontext;
+    private Map<String, StringMatch> dubbocontext;
+
+    public Map<String, StringMatch> getEagleeyecontext() {
+        return eagleeyecontext;
+    }
+
+    public void setEagleeyecontext(Map<String, StringMatch> eagleeyecontext) {
+        this.eagleeyecontext = eagleeyecontext;
+    }
+
+    public Map<String, StringMatch> getDubbocontext() {
+        return dubbocontext;
+    }
+
+    public void setDubbocontext(Map<String, StringMatch> dubbocontext) {
+        this.dubbocontext = dubbocontext;
+    }
+
+    public static boolean isMatch(DubboAttachmentMatch dubboAttachmentMatch, Map<String, String> eagleeyeContext, Map<String, String> dubboContext) {
+        if (dubboAttachmentMatch.getDubbocontext() != null) {
+            for (Map.Entry<String, StringMatch> stringStringMatchEntry : dubboAttachmentMatch.getDubbocontext().entrySet()) {
+                String key = stringStringMatchEntry.getKey();
+                StringMatch stringMatch = stringStringMatchEntry.getValue();
+
+                String dubboContextValue = dubboContext.get(key);
+                if (dubboContextValue == null) {
+                    return false;
+                }
+                if (!StringMatch.isMatch(stringMatch, dubboContextValue)) {
+                    return false;
+                }
+            }
+        }
+
+        if (dubboAttachmentMatch.getEagleeyecontext() != null) {
+            for (Map.Entry<String, StringMatch> stringStringMatchEntry : dubboAttachmentMatch.getEagleeyecontext().entrySet()) {
+                String key = stringStringMatchEntry.getKey();
+                StringMatch stringMatch = stringStringMatchEntry.getValue();
+
+                String eagleeyeContextValue = eagleeyeContext.get(key);
+                if (eagleeyeContextValue == null) {
+                    return false;
+                }
+                if (!StringMatch.isMatch(stringMatch, eagleeyeContextValue)) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodArg.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodArg.java
new file mode 100644
index 0000000..8e0f991
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodArg.java
@@ -0,0 +1,90 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice.match;
+
+
+public class DubboMethodArg {
+    private int index;
+    private String type;
+    private ListStringMatch str_value;
+    private ListDoubleMatch num_value;
+    private BoolMatch bool_value;
+
+    public int getIndex() {
+        return index;
+    }
+
+    public void setIndex(int index) {
+        this.index = index;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public ListStringMatch getStr_value() {
+        return str_value;
+    }
+
+    public void setStr_value(ListStringMatch str_value) {
+        this.str_value = str_value;
+    }
+
+    public ListDoubleMatch getNum_value() {
+        return num_value;
+    }
+
+    public void setNum_value(ListDoubleMatch num_value) {
+        this.num_value = num_value;
+    }
+
+    public BoolMatch getBool_value() {
+        return bool_value;
+    }
+
+    public void setBool_value(BoolMatch bool_value) {
+        this.bool_value = bool_value;
+    }
+
+    public static boolean isMatch(DubboMethodArg dubboMethodArg, Object input) {
+
+        if (dubboMethodArg.getStr_value() != null) {
+            return ListStringMatch.isMatch(dubboMethodArg.getStr_value(), (String) input);
+        } else if (dubboMethodArg.getNum_value() != null) {
+            return ListDoubleMatch.isMatch(dubboMethodArg.getNum_value(), Double.valueOf(input.toString()));
+        } else if (dubboMethodArg.getBool_value() != null) {
+            return BoolMatch.isMatch(dubboMethodArg.getBool_value(), (Boolean) input);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return "DubboMethodArg{" +
+                "index=" + index +
+                ", type='" + type + '\'' +
+                ", str_value=" + str_value +
+                ", num_value=" + num_value +
+                ", bool_value=" + bool_value +
+                '}';
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodMatch.java
new file mode 100644
index 0000000..c448895
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodMatch.java
@@ -0,0 +1,128 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice.match;
+
+import java.util.List;
+import java.util.Map;
+
+
+public class DubboMethodMatch {
+    private StringMatch name_match;
+    private Integer argc;
+    private List<DubboMethodArg> args;
+    private List<StringMatch> argp;
+    private Map<String, StringMatch> headers;
+
+    public StringMatch getName_match() {
+        return name_match;
+    }
+
+    public void setName_match(StringMatch name_match) {
+        this.name_match = name_match;
+    }
+
+    public Integer getArgc() {
+        return argc;
+    }
+
+    public void setArgc(Integer argc) {
+        this.argc = argc;
+    }
+
+    public List<DubboMethodArg> getArgs() {
+        return args;
+    }
+
+    public void setArgs(List<DubboMethodArg> args) {
+        this.args = args;
+    }
+
+    public List<StringMatch> getArgp() {
+        return argp;
+    }
+
+    public void setArgp(List<StringMatch> argp) {
+        this.argp = argp;
+    }
+
+    public Map<String, StringMatch> getHeaders() {
+        return headers;
+    }
+
+    public void setHeaders(Map<String, StringMatch> headers) {
+        this.headers = headers;
+    }
+
+    public static boolean isMatch(DubboMethodMatch dubboMethodMatch, String methodName, String[] parameterTypeList, Object[] parameters) {
+        StringMatch nameMatch = dubboMethodMatch.getName_match();
+        if (nameMatch != null && !StringMatch.isMatch(nameMatch, methodName)) {
+            return false;
+        }
+
+        Integer argc = dubboMethodMatch.getArgc();
+        if (argc != null &&
+                ((argc != 0 && (parameters == null || parameters.length == 0)) || (argc != parameters.length))) {
+            return false;
+        }
+        List<StringMatch> argp = dubboMethodMatch.getArgp();
+        if (argp != null) {
+            if (((parameterTypeList == null || parameterTypeList.length == 0) && argp.size() > 0)
+                    || (argp.size() != parameterTypeList.length)) {
+                return false;
+            }
+
+            for (int index = 0; index < argp.size(); index++) {
+                if (!StringMatch.isMatch(argp.get(index), parameterTypeList[index])) {
+                    return false;
+                }
+            }
+        }
+
+        List<DubboMethodArg> args = dubboMethodMatch.getArgs();
+
+        if (args != null && args.size() > 0) {
+            if (parameters == null || parameters.length == 0) {
+                return false;
+            }
+
+            for (DubboMethodArg dubboMethodArg : args) {
+                int index = dubboMethodArg.getIndex();
+                if (index >= parameters.length) {
+                    throw new IndexOutOfBoundsException("DubboMethodArg index >= parameters.length");
+                }
+                if (!DubboMethodArg.isMatch(dubboMethodArg, parameters[index])) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "DubboMethodMatch{" +
+                "name_match=" + name_match +
+                ", argc=" + argc +
+                ", args=" + args +
+                ", argp=" + argp +
+                ", headers=" + headers +
+                '}';
+    }
+}
+
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListBoolMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListBoolMatch.java
new file mode 100644
index 0000000..b3289e2
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListBoolMatch.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.admin.model.store.mesh.virtualservice.match;
+
+
+public class ListBoolMatch {
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListDoubleMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListDoubleMatch.java
new file mode 100644
index 0000000..51c4b44
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListDoubleMatch.java
@@ -0,0 +1,43 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice.match;
+
+import java.util.List;
+
+
+public class ListDoubleMatch {
+    private List<DoubleMatch> oneof;
+
+    public List<DoubleMatch> getOneof() {
+        return oneof;
+    }
+
+    public void setOneof(List<DoubleMatch> oneof) {
+        this.oneof = oneof;
+    }
+
+    public static boolean isMatch(ListDoubleMatch listDoubleMatch, Double input) {
+
+        for (DoubleMatch doubleMatch : listDoubleMatch.getOneof()) {
+            if (DoubleMatch.isMatch(doubleMatch, input)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListStringMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListStringMatch.java
new file mode 100644
index 0000000..d8f935f
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListStringMatch.java
@@ -0,0 +1,44 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice.match;
+
+import java.util.List;
+
+
+public class ListStringMatch {
+    private List<StringMatch> oneof;
+
+    public List<StringMatch> getOneof() {
+        return oneof;
+    }
+
+    public void setOneof(List<StringMatch> oneof) {
+        this.oneof = oneof;
+    }
+
+
+    public static boolean isMatch(ListStringMatch listStringMatch, String input) {
+
+        for (StringMatch stringMatch : listStringMatch.getOneof()) {
+            if (StringMatch.isMatch(stringMatch, input)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/StringMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/StringMatch.java
new file mode 100644
index 0000000..5cd7465
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/StringMatch.java
@@ -0,0 +1,105 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice.match;
+
+
+public class StringMatch {
+    private String exact;
+    private String prefix;
+    private String regex;
+    private String noempty;
+    private String empty;
+
+
+    public String getExact() {
+        return exact;
+    }
+
+    public void setExact(String exact) {
+        this.exact = exact;
+    }
+
+    public String getPrefix() {
+        return prefix;
+    }
+
+    public void setPrefix(String prefix) {
+        this.prefix = prefix;
+    }
+
+    public String getRegex() {
+        return regex;
+    }
+
+    public void setRegex(String regex) {
+        this.regex = regex;
+    }
+
+    public String getNoempty() {
+        return noempty;
+    }
+
+    public void setNoempty(String noempty) {
+        this.noempty = noempty;
+    }
+
+    public String getEmpty() {
+        return empty;
+    }
+
+    public void setEmpty(String empty) {
+        this.empty = empty;
+    }
+
+
+    public static boolean isMatch(StringMatch stringMatch, String input) {
+        if (stringMatch.getExact() != null && input != null) {
+            if (input.equals(stringMatch.getExact())) {
+                return true;
+            }
+        } else if (stringMatch.getPrefix() != null && input != null) {
+            if (input.startsWith(stringMatch.getPrefix())) {
+                return true;
+            }
+        } else if (stringMatch.getRegex() != null && input != null) {
+            if (input.matches(stringMatch.getRegex())) {
+                return true;
+            }
+        } else if (stringMatch.getEmpty() != null) {
+            return input == null || "".equals(input);
+        } else if (stringMatch.getNoempty() != null) {
+            return input != null && input.length() > 0;
+        } else {
+            return false;
+        }
+
+        return false;
+    }
+
+
+    @Override
+    public String toString() {
+        return "StringMatch{" +
+                "exact='" + exact + '\'' +
+                ", prefix='" + prefix + '\'' +
+                ", regex='" + regex + '\'' +
+                ", noempty='" + noempty + '\'' +
+                ", empty='" + empty + '\'' +
+                '}';
+    }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MeshRouteService.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MeshRouteService.java
new file mode 100644
index 0000000..708dd7e
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MeshRouteService.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.admin.service;
+
+import org.apache.dubbo.admin.model.dto.MeshRouteDTO;
+
+public interface MeshRouteService {
+
+    /**
+     * create mesh rule route
+     *
+     * @param meshRoute dto
+     * @return success
+     */
+    boolean createMeshRule(MeshRouteDTO meshRoute);
+
+    /**
+     * update mesh rule route
+     *
+     * @param meshRoute dto
+     * @return success
+     */
+    boolean updateMeshRule(MeshRouteDTO meshRoute);
+
+    /**
+     * delete mesh rule
+     *
+     * @param id id
+     * @return success
+     */
+    boolean deleteMeshRule(String id);
+
+    /**
+     * find mesh rule by id
+     *
+     * @param id id
+     * @return dto
+     */
+    MeshRouteDTO findMeshRoute(String id);
+
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MeshRouteServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MeshRouteServiceImpl.java
new file mode 100644
index 0000000..b234eaf
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MeshRouteServiceImpl.java
@@ -0,0 +1,90 @@
+/*
+ * 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.admin.service.impl;
+
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.common.util.ConvertUtil;
+import org.apache.dubbo.admin.common.util.YamlParser;
+import org.apache.dubbo.admin.model.dto.MeshRouteDTO;
+import org.apache.dubbo.admin.model.store.mesh.destination.DestinationRule;
+import org.apache.dubbo.admin.model.store.mesh.virtualservice.VirtualServiceRule;
+import org.apache.dubbo.admin.service.MeshRouteService;
+
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+
+@Service
+public class MeshRouteServiceImpl extends AbstractService implements MeshRouteService {
+
+    @Override
+    public boolean createMeshRule(MeshRouteDTO meshRoute) {
+        String routeRule = meshRoute.getMeshRule();
+        checkMeshRule(routeRule);
+        String id = ConvertUtil.getIdFromDTO(meshRoute);
+        String path = getPath(id);
+        dynamicConfiguration.setConfig(path, routeRule);
+        return true;
+    }
+
+    @Override
+    public boolean updateMeshRule(MeshRouteDTO meshRoute) {
+        String id = ConvertUtil.getIdFromDTO(meshRoute);
+        String path = getPath(id);
+        checkMeshRule(meshRoute.getMeshRule());
+        dynamicConfiguration.setConfig(path, meshRoute.getMeshRule());
+        return true;
+    }
+
+    private void checkMeshRule(String meshRule) {
+        Iterable<Object> objectIterable = YamlParser.loadAll(meshRule);
+        for (Object result : objectIterable) {
+            Map resultMap = (Map) result;
+            if ("DestinationRule".equals(resultMap.get("kind"))) {
+                YamlParser.loadObject(YamlParser.dumpObject(result), DestinationRule.class);
+            } else if ("VirtualService".equals(resultMap.get("kind"))) {
+                YamlParser.loadObject(YamlParser.dumpObject(result), VirtualServiceRule.class);
+            }
+        }
+    }
+
+    @Override
+    public boolean deleteMeshRule(String id) {
+        String path = getPath(id);
+        return dynamicConfiguration.deleteConfig(path);
+    }
+
+    @Override
+    public MeshRouteDTO findMeshRoute(String id) {
+        String path = getPath(id);
+        String rule = dynamicConfiguration.getConfig(path);
+        if (rule == null) {
+            return null;
+        }
+        MeshRouteDTO meshRoute = new MeshRouteDTO();
+        meshRoute.setApplication(id);
+        meshRoute.setMeshRule(rule);
+        return meshRoute;
+    }
+
+    private String getPath(String id) {
+        return Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + id + Constants.MESH_RULE_SUFFIX;
+    }
+
+}
diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/MeshRouteControllerTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/MeshRouteControllerTest.java
new file mode 100644
index 0000000..9cf6146
--- /dev/null
+++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/MeshRouteControllerTest.java
@@ -0,0 +1,141 @@
+/*
+ * 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.admin.controller;
+
+import org.apache.dubbo.admin.AbstractSpringIntegrationTest;
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.model.dto.MeshRouteDTO;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.After;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+
+public class MeshRouteControllerTest extends AbstractSpringIntegrationTest {
+
+    private final String env = "whatever";
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @After
+    public void tearDown() throws Exception {
+        if (zkClient.checkExists().forPath("/dubbo") != null) {
+            zkClient.delete().deletingChildrenIfNeeded().forPath("/dubbo");
+        }
+    }
+
+    private String getFileContent(String file) throws IOException {
+        try (InputStream stream = this.getClass().getResourceAsStream(file)) {
+            byte[] bytes = new byte[stream.available()];
+            stream.read(bytes);
+            return new String(bytes, StandardCharsets.UTF_8);
+        }
+    }
+
+
+    @Test
+    public void createMeshRoute() throws IOException {
+        MeshRouteDTO meshRoute = new MeshRouteDTO();
+        ResponseEntity<String> response;
+        String application = "mesh-create";
+        // application are all blank
+        response = restTemplate.postForEntity(url("/api/{env}/rules/route/mesh"), meshRoute, String.class, env);
+        assertFalse("should return a fail response, when application is blank", (Boolean) objectMapper.readValue(response.getBody(), Map.class).get("success"));
+
+        // valid mesh rule
+        meshRoute.setApplication(application);
+        meshRoute.setMeshRule(getFileContent("/MeshRoute.yml"));
+        response = restTemplate.postForEntity(url("/api/{env}/rules/route/mesh"), meshRoute, String.class, env);
+        assertEquals(HttpStatus.CREATED, response.getStatusCode());
+        assertTrue(Boolean.valueOf(response.getBody()));
+    }
+
+
+    @Test
+    public void detailMeshRoute() throws Exception {
+        String id = "1";
+        ResponseEntity<String> response;
+        // when balancing is not exist
+        response = restTemplate.getForEntity(url("/api/{env}/rules/route/mesh/{id}"), String.class, env, id);
+        assertFalse("should return a fail response, when id is null", (Boolean) objectMapper.readValue(response.getBody(), Map.class).get("success"));
+        // when balancing is not null
+        String application = "mesh-detail";
+        String content = getFileContent("/MeshRoute.yml");
+        String path = "/dubbo/" + Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + application + Constants.MESH_RULE_SUFFIX;
+        zkClient.create().creatingParentContainersIfNeeded().forPath(path);
+        zkClient.setData().forPath(path, content.getBytes());
+        assertNotNull("zk path should not be null before deleting", zkClient.checkExists().forPath(path));
+
+        response = restTemplate.getForEntity(url("/api/{env}/rules/route/mesh/{id}"), String.class, env, application);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+        assertEquals(content, objectMapper.readValue(response.getBody(), Map.class).get("meshRule"));
+    }
+
+    @Test
+    public void updateMeshRoute() throws Exception {
+        String application = "mesh-update";
+        String content = getFileContent("/MeshRoute.yml");
+        String path = "/dubbo/" + Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + application + Constants.MESH_RULE_SUFFIX;
+        zkClient.create().creatingParentContainersIfNeeded().forPath(path);
+        zkClient.setData().forPath(path, content.getBytes());
+        assertNotNull("zk path should not be null before deleting", zkClient.checkExists().forPath(path));
+
+        MeshRouteDTO meshRoute = new MeshRouteDTO();
+        meshRoute.setApplication(application);
+        meshRoute.setMeshRule(getFileContent("/MeshRouteTest2.yml"));
+
+        ResponseEntity<String> response = restTemplate.exchange(url("/api/{env}/rules/route/mesh/{id}"), HttpMethod.PUT, new HttpEntity<>(meshRoute, null), String.class, env, application);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+        assertTrue(Boolean.valueOf(response.getBody()));
+        byte[] bytes = zkClient.getData().forPath(path);
+        String updatedConfig = new String(bytes);
+        assertEquals(updatedConfig, meshRoute.getMeshRule());
+    }
+
+
+    @Test
+    public void deleteMeshRoute() throws Exception {
+        String application = "mesh-delete";
+        String content = getFileContent("/MeshRoute.yml");
+        String path = "/dubbo/" + Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + application + Constants.MESH_RULE_SUFFIX;
+        zkClient.create().creatingParentContainersIfNeeded().forPath(path);
+        zkClient.setData().forPath(path, content.getBytes());
+        assertNotNull("zk path should not be null before deleting", zkClient.checkExists().forPath(path));
+
+        ResponseEntity<String> response = restTemplate.exchange(url("/api/{env}/rules/route/mesh/{id}"), HttpMethod.DELETE, new HttpEntity<>(null), String.class, env, application);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+        assertNull(zkClient.checkExists().forPath(path));
+    }
+}
diff --git a/dubbo-admin-server/src/test/resources/MeshRoute.yml b/dubbo-admin-server/src/test/resources/MeshRoute.yml
new file mode 100644
index 0000000..b6a1071
--- /dev/null
+++ b/dubbo-admin-server/src/test/resources/MeshRoute.yml
@@ -0,0 +1,58 @@
+#
+#
+#   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.
+#
+#
+
+apiVersion: service.dubbo.apache.org/v1alpha1
+kind: DestinationRule
+metadata: { name: demo-route }
+spec:
+  host: demo
+  subsets:
+    - labels: { env-sign: xxx, tag1: hello }
+      name: isolation
+    - labels: { env-sign: yyy }
+      name: testing-trunk
+    - labels: { env-sign: zzz }
+      name: testing
+  trafficPolicy:
+    loadBalancer: { simple: ROUND_ROBIN }
+
+---
+
+apiVersion: service.dubbo.apache.org/v1alpha1
+kind: VirtualService
+metadata: {name: demo-route}
+spec:
+  dubbo:
+    - routedetail:
+        - match:
+            - sourceLabels: {trafficLabel: xxx}
+          name: xxx-project
+          route:
+            - destination: {host: demo, subset: isolation}
+        - match:
+            - sourceLabels: {trafficLabel: testing-trunk}
+          name: testing-trunk
+          route:
+            - destination: {host: demo, subset: testing-trunk}
+        - name: testing
+          route:
+            - destination: {host: demo, subset: testing}
+      services:
+        - {regex: ccc}
+  hosts: [demo]
\ No newline at end of file
diff --git a/dubbo-admin-server/src/test/resources/MeshRouteTest2.yml b/dubbo-admin-server/src/test/resources/MeshRouteTest2.yml
new file mode 100644
index 0000000..4d3454b
--- /dev/null
+++ b/dubbo-admin-server/src/test/resources/MeshRouteTest2.yml
@@ -0,0 +1,41 @@
+#
+#
+#   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.
+#
+#
+
+apiVersion: service.dubbo.apache.org/v1alpha1
+kind: VirtualService
+metadata: {name: demo-route}
+spec:
+  dubbo:
+    - routedetail:
+        - match:
+            - sourceLabels: {trafficLabel: xxx}
+          name: xxx-project
+          route:
+            - destination: {host: demo, subset: isolation}
+        - match:
+            - sourceLabels: {trafficLabel: testing-trunk}
+          name: testing-trunk
+          route:
+            - destination: {host: demo, subset: testing-trunk}
+        - name: testing
+          route:
+            - destination: {host: demo, subset: testing}
+      services:
+        - {regex: ccc}
+  hosts: [demo]
diff --git a/dubbo-admin-ui/src/api/menu.js b/dubbo-admin-ui/src/api/menu.js
index 0a4fced..a68f536 100644
--- a/dubbo-admin-ui/src/api/menu.js
+++ b/dubbo-admin-ui/src/api/menu.js
@@ -23,7 +23,8 @@ const Menu = [
     group: 'governance',
     items: [
       { title: 'routingRule', path: '/governance/routingRule' },
-      { title: 'tagRule', path: '/governance/tagRule', badge: 'new' },
+      { title: 'tagRule', path: '/governance/tagRule' },
+      { title: 'meshRule', path: '/governance/meshRule', badge: 'new' },
       { title: 'accessControl', path: '/governance/access' },
       { title: 'dynamicConfig', path: '/governance/config' },
       { title: 'weightAdjust', path: '/governance/weight' },
diff --git a/dubbo-admin-ui/src/components/governance/MeshRule.vue b/dubbo-admin-ui/src/components/governance/MeshRule.vue
new file mode 100644
index 0000000..f29b5a4
--- /dev/null
+++ b/dubbo-admin-ui/src/components/governance/MeshRule.vue
@@ -0,0 +1,422 @@
+<!--
+  - 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.
+  -->
+
+<template>
+  <v-container grid-list-xl fluid>
+    <v-layout row wrap>
+      <v-flex lg12>
+        <breadcrumb title="meshRule" :items="breads"></breadcrumb>
+      </v-flex>
+    </v-layout>
+    <v-flex lg12>
+      <v-card flat color="transparent">
+        <v-card-text>
+          <v-form>
+            <v-layout row wrap>
+              <v-combobox
+                id="serviceSearch"
+                :loading="searchLoading"
+                :items="typeAhead"
+                :search-input.sync="input"
+                @keyup.enter="submit"
+                v-model="filter"
+                flat
+                append-icon=""
+                hide-no-data
+                :label="$t('searchMeshRule')"
+              ></v-combobox>
+              <v-btn @click="submit" color="primary" large>{{$t('search')}}</v-btn>
+
+            </v-layout>
+          </v-form>
+        </v-card-text>
+      </v-card>
+    </v-flex>
+    <v-flex lg12>
+      <v-card>
+        <v-toolbar flat color="transparent" class="elevation-0">
+          <v-toolbar-title><span class="headline">{{$t('searchResult')}}</span></v-toolbar-title>
+          <v-spacer></v-spacer>
+          <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">{{$t('create')}}</v-btn>
+        </v-toolbar>
+
+        <v-card-text class="pa-0">
+          <v-data-table
+            :headers="headers"
+            :items="meshRoutingRules"
+            hide-actions
+            class="elevation-0"
+          >
+            <template slot="items" slot-scope="props">
+              <td class="text-xs-left">{{ props.item.application }}</td>
+              <td class="text-xs-center px-0">
+                <v-tooltip bottom>
+                  <v-icon small
+                          class="mr-2"
+                          color="blue"
+                          slot="activator"
+                          @click="itemOperation('visibility', props.item)">visibility
+                  </v-icon>
+                  <span>{{$t('view')}}</span>
+                </v-tooltip>
+                <v-tooltip bottom>
+                  <v-icon small
+                          class="mr-2"
+                          color="blue"
+                          slot="activator"
+                          @click="itemOperation('edit', props.item)">edit
+                  </v-icon>
+                  <span>Edit</span>
+                </v-tooltip>
+                <v-tooltip bottom>
+                  <v-icon small
+                          class="mr-2"
+                          slot="activator"
+                          color="red"
+                          @click="itemOperation('delete', props.item)">delete
+                  </v-icon>
+                  <span>Delete</span>
+                </v-tooltip>
+              </td>
+            </template>
+          </v-data-table>
+        </v-card-text>
+      </v-card>
+    </v-flex>
+
+    <v-dialog v-model="dialog" width="800px" persistent>
+      <v-card>
+        <v-card-title class="justify-center">
+          <span class="headline">{{$t('createNewMeshRule')}}</span>
+        </v-card-title>
+        <v-card-text>
+          <v-text-field
+            :label="$t('appName')"
+            :hint="$t('appNameHint')"
+            v-model="application"
+          ></v-text-field>
+
+          <v-subheader class="pa-0 mt-3">{{$t('ruleContent')}}</v-subheader>
+          <ace-editor v-model="ruleText" :readonly="readonly"></ace-editor>
+
+        </v-card-text>
+        <v-card-actions>
+          <v-spacer></v-spacer>
+          <v-btn flat @click.native="closeDialog">{{$t('close')}}</v-btn>
+          <v-btn depressed color="primary" @click.native="saveItem">{{$t('save')}}</v-btn>
+        </v-card-actions>
+      </v-card>
+    </v-dialog>
+
+    <v-dialog v-model="warn.display" persistent max-width="500px">
+      <v-card>
+        <v-card-title class="headline">{{$t(this.warn.title)}}</v-card-title>
+        <v-card-text>{{this.warn.text}}</v-card-text>
+        <v-card-actions>
+          <v-spacer></v-spacer>
+          <v-btn flat @click.native="closeWarn">CANCLE</v-btn>
+          <v-btn depressed color="primary" @click.native="deleteItem(warn.status)">{{$t('confirm')}}</v-btn>
+        </v-card-actions>
+      </v-card>
+    </v-dialog>
+
+  </v-container>
+
+</template>
+<script>
+  import yaml from 'js-yaml'
+  import AceEditor from '@/components/public/AceEditor'
+  import operations from '@/api/operation'
+  import Search from '@/components/public/Search'
+  import Breadcrumb from '@/components/public/Breadcrumb'
+
+  export default {
+    components: {
+      AceEditor,
+      Search,
+      Breadcrumb
+    },
+    data: () => ({
+      dropdown_font: ['Service', 'App', 'IP'],
+      ruleKeys: ['enabled', 'force', 'dynamic', 'runtime', 'group', 'version', 'rule'],
+      pattern: 'Service',
+      filter: '',
+      dialog: false,
+      updateId: '',
+      application: '',
+      searchLoading: false,
+      typeAhead: [],
+      input: null,
+      timerID: null,
+      warn: {
+        display: false,
+        title: '',
+        text: '',
+        status: {}
+      },
+      breads: [
+        {
+          text: 'serviceGovernance',
+          href: ''
+        },
+        {
+          text: 'meshRule',
+          href: ''
+        }
+      ],
+      height: 0,
+      operations: operations,
+      meshRoutingRules: [],
+      template: 'apiVersion: service.dubbo.apache.org/v1alpha1\n' +
+        'kind: DestinationRule\n' +
+        'metadata: { name: demo-route }\n' +
+        'spec:\n' +
+        '  host: demo\n' +
+        '  subsets:\n' +
+        '    - labels: { env-sign: xxx, tag1: hello }\n' +
+        '      name: isolation\n' +
+        '    - labels: { env-sign: yyy }\n' +
+        '      name: testing-trunk\n' +
+        '    - labels: { env-sign: zzz }\n' +
+        '      name: testing\n' +
+        '  trafficPolicy:\n' +
+        '    loadBalancer: { simple: ROUND_ROBIN }\n' +
+        '\n' +
+        '---\n' +
+        '\n' +
+        'apiVersion: service.dubbo.apache.org/v1alpha1\n' +
+        'kind: VirtualService\n' +
+        'metadata: {name: demo-route}\n' +
+        'spec:\n' +
+        '  dubbo:\n' +
+        '    - routedetail:\n' +
+        '        - match:\n' +
+        '            - sourceLabels: {trafficLabel: xxx}\n' +
+        '          name: xxx-project\n' +
+        '          route:\n' +
+        '            - destination: {host: demo, subset: isolation}\n' +
+        '        - match:\n' +
+        '            - sourceLabels: {trafficLabel: testing-trunk}\n' +
+        '          name: testing-trunk\n' +
+        '          route:\n' +
+        '            - destination: {host: demo, subset: testing-trunk}\n' +
+        '        - name: testing\n' +
+        '          route:\n' +
+        '            - destination: {host: demo, subset: testing}\n' +
+        '      services:\n' +
+        '        - {regex: ccc}\n' +
+        '  hosts: [demo]',
+      ruleText: '',
+      readonly: false,
+      headers: []
+    }),
+    methods: {
+      setHeaders: function () {
+        this.headers = [
+          {
+            text: this.$t('appName'),
+            value: 'application',
+            align: 'left'
+          },
+          {
+            text: this.$t('operation'),
+            value: 'operation',
+            sortable: false,
+            width: '115px'
+          }
+        ]
+      },
+      querySelections(v) {
+        if (this.timerID) {
+          clearTimeout(this.timerID)
+        }
+        // Simulated ajax query
+        this.timerID = setTimeout(() => {
+          if (v && v.length >= 4) {
+            this.searchLoading = true
+            this.typeAhead = this.$store.getters.getAppItems(v)
+            this.searchLoading = false
+            this.timerID = null
+          } else {
+            this.typeAhead = []
+          }
+        }, 500)
+      },
+      submit: function () {
+        if (!this.filter) {
+          this.$notify.error('application is needed')
+          return
+        }
+        this.filter = this.filter.trim()
+        this.search(true)
+      },
+      search: function (rewrite) {
+        let url = '/rules/route/mesh/?application' + '=' + this.filter
+        this.$axios.get(url)
+          .then(response => {
+            this.meshRoutingRules = response.data
+            if (rewrite) {
+              this.$router.push({path: 'meshRule', query: {application: this.filter}})
+            }
+          })
+      },
+      closeDialog: function () {
+        this.ruleText = this.template
+        this.updateId = ''
+        this.application = ''
+        this.dialog = false
+        this.readonly = false
+      },
+      openDialog: function () {
+        this.dialog = true
+      },
+      openWarn: function (title, text) {
+        this.warn.title = title
+        this.warn.text = text
+        this.warn.display = true
+      },
+      closeWarn: function () {
+        this.warn.title = ''
+        this.warn.text = ''
+        this.warn.display = false
+      },
+      saveItem: function () {
+        const rule = {}
+        rule.meshRule = this.ruleText
+        if (!this.application) {
+          this.$notify.error('application is required')
+          return
+        }
+        rule.application = this.application
+        let vm = this
+        if (this.updateId) {
+          if (this.updateId === 'close') {
+            this.closeDialog()
+          } else {
+            rule.id = this.updateId
+            this.$axios.put('/rules/route/mesh/' + rule.id, rule)
+              .then(response => {
+                if (response.status === 200) {
+                  vm.search(vm.application, true)
+                  vm.closeDialog()
+                  vm.$notify.success('Update success')
+                }
+              })
+          }
+        } else {
+          this.$axios.post('/rules/route/mesh/', rule)
+            .then(response => {
+              if (response.status === 201) {
+                vm.search(vm.application, true)
+                vm.filter = vm.application
+                vm.closeDialog()
+                vm.$notify.success('Create success')
+              }
+            })
+            .catch(error => {
+              console.log(error)
+            })
+        }
+      },
+      itemOperation: function (icon, item) {
+        let itemId = item.application
+        switch (icon) {
+          case 'visibility':
+            this.$axios.get('/rules/route/mesh/' + itemId)
+              .then(response => {
+                let meshRoute = response.data
+                this.handleBalance(meshRoute, true)
+                this.updateId = 'close'
+              })
+            break
+          case 'edit':
+            let id = {}
+            id.id = itemId
+            this.$axios.get('/rules/route/mesh/' + itemId)
+              .then(response => {
+                let meshRoute = response.data
+                this.handleBalance(meshRoute, false)
+                this.updateId = itemId
+              })
+            break
+          case 'delete':
+            this.openWarn('warnDeleteMeshRule', 'application: ' + item.application)
+            this.warn.status.operation = 'delete'
+            this.warn.status.id = itemId
+        }
+      },
+      handleBalance: function (meshRoute, readonly) {
+        this.application = meshRoute.application
+        delete meshRoute.id
+        delete meshRoute.application
+        this.ruleText = meshRoute.meshRule
+        this.readonly = readonly
+        this.dialog = true
+      },
+      setHeight: function () {
+        this.height = window.innerHeight * 0.5
+      },
+      deleteItem: function (warnStatus) {
+        let id = warnStatus.id
+        let operation = warnStatus.operation
+        if (operation === 'delete') {
+          this.$axios.delete('/rules/route/mesh/' + id)
+            .then(response => {
+              if (response.status === 200) {
+                this.warn.display = false
+                this.search(this.filter, false)
+                this.$notify.success('Delete success')
+              }
+            })
+        }
+      }
+    },
+    created() {
+      this.setHeight()
+    },
+    computed: {
+      area() {
+        return this.$i18n.locale
+      }
+    },
+    watch: {
+      input(val) {
+        this.querySelections(val)
+      },
+      area() {
+        this.setHeaders()
+      }
+    },
+    mounted: function () {
+      this.setHeaders()
+      this.$store.dispatch('loadAppItems')
+      this.ruleText = this.template
+      let query = this.$route.query
+      let filter = null
+      Object.keys(query).forEach(function (key) {
+        if (key === 'application') {
+          filter = query[key]
+        }
+      })
+      if (filter !== null) {
+        this.filter = filter
+        this.search(false)
+      }
+    }
+
+  }
+</script>
diff --git a/dubbo-admin-ui/src/lang/en.js b/dubbo-admin-ui/src/lang/en.js
index c0d485f..c239380 100644
--- a/dubbo-admin-ui/src/lang/en.js
+++ b/dubbo-admin-ui/src/lang/en.js
@@ -20,6 +20,7 @@ export default {
   serviceGovernance: 'Service Governance',
   routingRule: 'Condition Rule',
   tagRule: 'Tag Rule',
+  meshRule: 'Mesh Rule',
   dynamicConfig: 'Dynamic Config',
   accessControl: 'Black White List',
   weightAdjust: 'Weight Adjust',
@@ -61,6 +62,7 @@ export default {
   ruleContent: 'RULE CONTENT',
   createNewRoutingRule: 'Create New Routing Rule',
   createNewTagRule: 'Create New Tag Rule',
+  createNewMeshRule: 'Create New Mesh Rule',
   createNewDynamicConfigRule: 'Create New Dynamic Config Rule',
   createNewWeightRule: 'Create New Weight Rule',
   createNewLoadBalanceRule: 'Create new load balancing rule',
@@ -86,6 +88,7 @@ export default {
   ipSearchHint: 'Find all services provided by the target server on the specified IP address',
   appSearchHint: 'Input an application name to find all services provided by one particular application, * for all',
   searchTagRule: 'Search Tag Rule by application name',
+  searchMeshRule: 'Search Mesh Rule by application name',
   searchSingleMetrics: 'Search Metrics by IP',
   searchBalanceRule: 'Search Balancing Rule',
   noMetadataHint: 'There is no metadata available, please update to Dubbo2.7, or check your config center configuration in application.properties, please check ',
@@ -137,6 +140,7 @@ export default {
   warnDeleteBalancing: 'Are you sure to Delete load balancing',
   warnDeleteAccessControl: 'Are you sure to Delete access control',
   warnDeleteTagRule: 'Are you sure to Delete tag rule',
+  warnDeleteMeshRule: 'Are you sure to Delete mesh rule',
   warnDeleteWeightAdjust: 'Are you sure to Delete weight adjust',
   configNameHint: "Application name the config belongs to, use 'global'(without quotes) for global config",
   configContent: 'Config Content',
diff --git a/dubbo-admin-ui/src/lang/zh.js b/dubbo-admin-ui/src/lang/zh.js
index 786b494..1116702 100644
--- a/dubbo-admin-ui/src/lang/zh.js
+++ b/dubbo-admin-ui/src/lang/zh.js
@@ -22,6 +22,7 @@ export default {
   serviceRelation: '服务关系',
   routingRule: '条件路由',
   tagRule: '标签路由',
+  meshRule: 'Mesh路由',
   dynamicConfig: '动态配置',
   accessControl: '黑白名单',
   weightAdjust: '权重调整',
@@ -61,6 +62,7 @@ export default {
   ruleContent: '规则内容',
   createNewRoutingRule: '创建新路由规则',
   createNewTagRule: '创建新标签规则',
+  createMeshTagRule: '创建新mesh规则',
   createNewDynamicConfigRule: '创建新动态配置规则',
   createNewWeightRule: '新建权重规则',
   createNewLoadBalanceRule: '新建负载均衡规则',
@@ -86,6 +88,7 @@ export default {
   ipSearchHint: '在指定的IP地址上查找目标服务器提供的所有服务',
   appSearchHint: '输入应用名称以查找由一个特定应用提供的所有服务, * 代表所有',
   searchTagRule: '根据应用名搜索标签规则',
+  searchMeshRule: '根据应用名搜索mesh规则',
   searchSingleMetrics: '输入IP搜索Metrics信息',
   searchBalanceRule: '搜索负载均衡规则',
   parameterList: '参数列表',
@@ -137,6 +140,7 @@ export default {
   warnDeleteBalancing: '是否要删除负载均衡规则',
   warnDeleteAccessControl: '是否要删除黑白名单',
   warnDeleteTagRule: '是否要删除标签路由',
+  warnDeleteMeshRule: '是否要删除mesh路由',
   warnDeleteWeightAdjust: '是否要删除权重规则',
   configNameHint: '配置所属的应用名, global 表示全局配置',
   configContent: '配置内容',
diff --git a/dubbo-admin-ui/src/router/index.js b/dubbo-admin-ui/src/router/index.js
index 1a4c2c1..6343d34 100644
--- a/dubbo-admin-ui/src/router/index.js
+++ b/dubbo-admin-ui/src/router/index.js
@@ -22,6 +22,7 @@ import ServiceDetail from '@/components/ServiceDetail'
 import TestMethod from '@/components/test/TestMethod'
 import RoutingRule from '@/components/governance/RoutingRule'
 import TagRule from '@/components/governance/TagRule'
+import MeshRule from '@/components/governance/MeshRule'
 import AccessControl from '@/components/governance/AccessControl'
 import LoadBalance from '@/components/governance/LoadBalance'
 import WeightAdjust from '@/components/governance/WeightAdjust'
@@ -88,6 +89,14 @@ export default new Router({
           }
         },
         {
+          path: '/governance/meshRule',
+          name: 'MeshRule',
+          component: MeshRule,
+          meta: {
+            requireLogin: true
+          }
+        },
+        {
           path: '/governance/access',
           name: 'AccessControl',
           component: AccessControl,