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

tydhot pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new 3625d85  [new: feature] register shenyu instance by zookeeper (#2437)
3625d85 is described below

commit 3625d8571eba163e6a6ffde49a0e3c6f60b0ff0f
Author: xiaoyu <[email protected]>
AuthorDate: Wed Nov 24 10:52:10 2021 +0800

    [new: feature] register shenyu instance by zookeeper (#2437)
    
    * [new: feature] register shenyu instance by zookeeper
    
    * fix checkstyle
    
    * fix checkstyle
---
 shenyu-bootstrap/pom.xml                           |   8 +
 .../src/main/resources/application-local.yml       |   5 +
 .../apache/shenyu/common/config/ShenyuConfig.java  | 127 ++++++++++++
 shenyu-register-center/pom.xml                     |   1 +
 .../register/common/dto/InstanceRegisterDTO.java   | 224 +++++++++++++++++++++
 .../common/path/RegisterPathConstants.java         |  18 +-
 .../{ => shenyu-register-instance}/pom.xml         |  18 +-
 .../shenyu-register-instance-api}/pom.xml          |  36 ++--
 .../api/ShenyuInstanceRegisterRepository.java      |  50 +++++
 .../shenyu-register-instance-core}/pom.xml         |  29 ++-
 .../ShenyuInstanceRegisterRepositoryFactory.java   |  47 +++++
 .../shenyu-register-instance-zookeeper}/pom.xml    |  39 ++--
 .../ZookeeperInstanceRegisterRepository.java       | 105 ++++++++++
 ...r.instance.api.ShenyuInstanceRegisterRepository |  17 ++
 shenyu-spring-boot-starter/pom.xml                 |   1 +
 .../shenyu-spring-boot-starter-instance/pom.xml    |  56 ++++++
 .../starter/instance/InstanceRegisterListener.java |  87 ++++++++
 .../instance/ShenyuInstanceConfiguration.java      |  42 ++++
 .../src/main/resources/META-INF/spring.factories   |   3 +
 .../src/main/resources/META-INF/spring.provides    |   1 +
 20 files changed, 855 insertions(+), 59 deletions(-)

diff --git a/shenyu-bootstrap/pom.xml b/shenyu-bootstrap/pom.xml
index 9dbb81a..16174a0 100644
--- a/shenyu-bootstrap/pom.xml
+++ b/shenyu-bootstrap/pom.xml
@@ -409,6 +409,14 @@
             <version>${project.version}</version>
         </dependency>
         <!--shenyu param mapping end-->
+
+        <!--shenyu instance start-->
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-spring-boot-starter-instance</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!--shenyu instance end-->
     </dependencies>
     
     <profiles>
diff --git a/shenyu-bootstrap/src/main/resources/application-local.yml 
b/shenyu-bootstrap/src/main/resources/application-local.yml
index 0ee69b7..00cef3c 100644
--- a/shenyu-bootstrap/src/main/resources/application-local.yml
+++ b/shenyu-bootstrap/src/main/resources/application-local.yml
@@ -47,6 +47,11 @@ management:
       enabled: false
 
 shenyu:
+  instance:
+    enabled: false
+    registerType: zookeeper #etcd #consul
+    serverLists: localhost:2181 #http://localhost:2379 #localhost:8848
+    props:
   cross:
     enabled: true
     allowedHeaders:
diff --git 
a/shenyu-common/src/main/java/org/apache/shenyu/common/config/ShenyuConfig.java 
b/shenyu-common/src/main/java/org/apache/shenyu/common/config/ShenyuConfig.java
index ddb56ee..981c7d1 100644
--- 
a/shenyu-common/src/main/java/org/apache/shenyu/common/config/ShenyuConfig.java
+++ 
b/shenyu-common/src/main/java/org/apache/shenyu/common/config/ShenyuConfig.java
@@ -22,6 +22,7 @@ import org.springframework.util.StringUtils;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Properties;
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -45,6 +46,26 @@ public class ShenyuConfig {
 
     private CrossFilterConfig cross = new CrossFilterConfig();
     
+    private InstanceConfig instance = new InstanceConfig();
+    
+    /**
+     * Gets instance.
+     *
+     * @return the instance
+     */
+    public InstanceConfig getInstance() {
+        return instance;
+    }
+    
+    /**
+     * Sets instance.
+     *
+     * @param instance the instance
+     */
+    public void setInstance(final InstanceConfig instance) {
+        this.instance = instance;
+    }
+    
     /**
      * Gets switch config.
      *
@@ -793,4 +814,110 @@ public class ShenyuConfig {
             this.allowCredentials = allowCredentials;
         }
     }
+    
+    /**
+     * The type Instance config.
+     */
+    public static class InstanceConfig {
+    
+        private Boolean enabled = false;
+    
+        private String registerType;
+    
+        private String serverLists;
+    
+        private Properties props = new Properties();
+        
+        /**
+         * Instantiates a new Instance config.
+         */
+        public InstanceConfig() {
+        
+        }
+    
+        /**
+         * Instantiates a new Instance config.
+         *
+         * @param registerType the register type
+         * @param serverLists the server lists
+         * @param props the props
+         */
+        public InstanceConfig(final String registerType, final String 
serverLists, final Properties props) {
+            this.registerType = registerType;
+            this.serverLists = serverLists;
+            this.props = props;
+        }
+    
+        /**
+         * Gets enabled.
+         *
+         * @return the enabled
+         */
+        public Boolean getEnabled() {
+            return enabled;
+        }
+    
+        /**
+         * Sets enabled.
+         *
+         * @param enabled the enabled
+         */
+        public void setEnabled(final Boolean enabled) {
+            this.enabled = enabled;
+        }
+    
+        /**
+         * getRegisterType.
+         *
+         * @return String register type
+         */
+        public String getRegisterType() {
+            return registerType;
+        }
+    
+        /**
+         * setRegisterType.
+         *
+         * @param registerType registerType
+         */
+        public void setRegisterType(final String registerType) {
+            this.registerType = registerType;
+        }
+    
+        /**
+         * getServerLists.
+         *
+         * @return String server lists
+         */
+        public String getServerLists() {
+            return serverLists;
+        }
+    
+        /**
+         * setServerLists.
+         *
+         * @param serverLists serverLists
+         */
+        public void setServerLists(final String serverLists) {
+            this.serverLists = serverLists;
+        }
+    
+        /**
+         * getProps.
+         *
+         * @return String props
+         */
+        public Properties getProps() {
+            return props;
+        }
+    
+        /**
+         * setProps.
+         *
+         * @param props props
+         */
+        public void setProps(final Properties props) {
+            this.props = props;
+        }
+    }
 }
diff --git a/shenyu-register-center/pom.xml b/shenyu-register-center/pom.xml
index cbffeac..911c9f5 100644
--- a/shenyu-register-center/pom.xml
+++ b/shenyu-register-center/pom.xml
@@ -30,6 +30,7 @@
         <module>shenyu-register-common</module>
         <module>shenyu-register-client</module>
         <module>shenyu-register-server</module>
+        <module>shenyu-register-instance</module>
     </modules>
 
 </project>
\ No newline at end of file
diff --git 
a/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/dto/InstanceRegisterDTO.java
 
b/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/dto/InstanceRegisterDTO.java
new file mode 100644
index 0000000..3920483
--- /dev/null
+++ 
b/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/dto/InstanceRegisterDTO.java
@@ -0,0 +1,224 @@
+/*
+ *   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.shenyu.register.common.dto;
+
+import java.util.Objects;
+
+/**
+ * The type Instance register dto.
+ */
+public class InstanceRegisterDTO {
+
+    private String appName;
+
+    private String host;
+
+    private Integer port;
+    
+    /**
+     * Instantiates a new Instance register dto.
+     *
+     * @param appName the app name
+     * @param host the host
+     * @param port the port
+     */
+    public InstanceRegisterDTO(final String appName, final String host, final 
Integer port) {
+        this.appName = appName;
+        this.host = host;
+        this.port = port;
+    }
+    
+    /**
+     * Instantiates a new Instance register dto.
+     */
+    public InstanceRegisterDTO() {
+    }
+
+    private InstanceRegisterDTO(final Builder builder) {
+        appName = builder.appName;
+        host = builder.host;
+        port = builder.port;
+    }
+    
+    /**
+     * Trans form uri register dto.
+     *
+     * @param metaDataRegisterDTO the meta data register dto
+     * @return the uri register dto
+     */
+    public static InstanceRegisterDTO transForm(final MetaDataRegisterDTO 
metaDataRegisterDTO) {
+        return InstanceRegisterDTO.builder()
+                .appName(metaDataRegisterDTO.getAppName())
+                .host(metaDataRegisterDTO.getHost())
+                .port(metaDataRegisterDTO.getPort()).build();
+    }
+    
+    /**
+     * return builder.
+     *
+     * @return Builder builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+    
+    /**
+     * getAppName.
+     *
+     * @return String app name
+     */
+    public String getAppName() {
+        return appName;
+    }
+    
+    /**
+     * setAppName.
+     *
+     * @param appName appName
+     */
+    public void setAppName(final String appName) {
+        this.appName = appName;
+    }
+    
+    /**
+     * getHost.
+     *
+     * @return String host
+     */
+    public String getHost() {
+        return host;
+    }
+    
+    /**
+     * setHost.
+     *
+     * @param host host
+     */
+    public void setHost(final String host) {
+        this.host = host;
+    }
+    
+    /**
+     * getPort.
+     *
+     * @return String port
+     */
+    public Integer getPort() {
+        return port;
+    }
+    
+    /**
+     * setPort.
+     *
+     * @param port port
+     */
+    public void setPort(final Integer port) {
+        this.port = port;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return Boolean.TRUE;
+        }
+
+        if (o == null || getClass() != o.getClass()) {
+            return Boolean.FALSE;
+        }
+
+        InstanceRegisterDTO that = (InstanceRegisterDTO) o;
+        return Objects.equals(getAppName(), that.getAppName())
+                && Objects.equals(getHost(), that.getHost())
+                && Objects.equals(getPort(), that.getPort());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getAppName(), getHost(), getPort());
+    }
+
+    @Override
+    public String toString() {
+        return "URIRegisterDTO{"
+                + "appName='"
+                + appName
+                + ", host='"
+                + host
+                + ", port="
+                + port
+                + '}';
+    }
+    
+    /**
+     * The type Builder.
+     */
+    public static final class Builder {
+
+        private String appName;
+
+        private String host;
+
+        private Integer port;
+
+        private Builder() {
+        }
+    
+        /**
+         * appName.
+         *
+         * @param appName appName
+         * @return Builder builder
+         */
+        public Builder appName(final String appName) {
+            this.appName = appName;
+            return this;
+        }
+    
+        /**
+         * host.
+         *
+         * @param host host
+         * @return Builder builder
+         */
+        public Builder host(final String host) {
+            this.host = host;
+            return this;
+        }
+    
+        /**
+         * port.
+         *
+         * @param port port
+         * @return Builder builder
+         */
+        public Builder port(final Integer port) {
+            this.port = port;
+            return this;
+        }
+    
+        /**
+         * build.
+         *
+         * @return Builder instance register dto
+         */
+        public InstanceRegisterDTO build() {
+            return new InstanceRegisterDTO(this);
+        }
+    }
+}
diff --git 
a/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/path/RegisterPathConstants.java
 
b/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/path/RegisterPathConstants.java
index 79cf881..ef269bd 100644
--- 
a/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/path/RegisterPathConstants.java
+++ 
b/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/path/RegisterPathConstants.java
@@ -80,7 +80,17 @@ public class RegisterPathConstants {
     public static String buildURIParentPath(final String rpcType, final String 
contextPath) {
         return String.join(SEPARATOR, ROOT_PATH, "uri", rpcType, contextPath);
     }
-
+    
+    /**
+     * Build instance parent path string.
+     * build child path of "/shenyu/register/instance/
+     *
+     * @return the string
+     */
+    public static String buildInstanceParentPath() {
+        return String.join(SEPARATOR, ROOT_PATH, "instance");
+    }
+    
     /**
      * Build real node string.
      *
@@ -91,7 +101,7 @@ public class RegisterPathConstants {
     public static String buildRealNode(final String nodePath, final String 
nodeName) {
         return String.join(SEPARATOR, nodePath, nodeName);
     }
-
+    
     /**
      * Build nacos instance service path string.
      * build child path of "shenyu.register.service.{rpcType}".
@@ -103,7 +113,7 @@ public class RegisterPathConstants {
         return String.join(SEPARATOR, ROOT_PATH, "service", rpcType)
                 .replace("/", DOT_SEPARATOR).substring(1);
     }
-
+    
     /**
      * Build nacos config service path string.
      * build child path of "shenyu.register.service.{rpcType}.{contextPath}".
@@ -121,7 +131,7 @@ public class RegisterPathConstants {
         }
         return serviceConfigPathAfterSubstring;
     }
-
+    
     /**
      * Build node name by DOT_SEPARATOR.
      *
diff --git a/shenyu-register-center/pom.xml 
b/shenyu-register-center/shenyu-register-instance/pom.xml
similarity index 67%
copy from shenyu-register-center/pom.xml
copy to shenyu-register-center/shenyu-register-instance/pom.xml
index cbffeac..ed95075 100644
--- a/shenyu-register-center/pom.xml
+++ b/shenyu-register-center/shenyu-register-instance/pom.xml
@@ -16,20 +16,22 @@
   ~ limitations under the License.
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
     <parent>
         <groupId>org.apache.shenyu</groupId>
-        <artifactId>shenyu</artifactId>
+        <artifactId>shenyu-register-center</artifactId>
         <version>2.4.2-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <artifactId>shenyu-register-center</artifactId>
+    <artifactId>shenyu-register-instance</artifactId>
     <packaging>pom</packaging>
-
+    
     <modules>
-        <module>shenyu-register-common</module>
-        <module>shenyu-register-client</module>
-        <module>shenyu-register-server</module>
+        <module>shenyu-register-instance-api</module>
+        <module>shenyu-register-instance-core</module>
+        <module>shenyu-register-instance-zookeeper</module>
     </modules>
-
+    
 </project>
\ No newline at end of file
diff --git a/shenyu-spring-boot-starter/pom.xml 
b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-api/pom.xml
similarity index 55%
copy from shenyu-spring-boot-starter/pom.xml
copy to 
shenyu-register-center/shenyu-register-instance/shenyu-register-instance-api/pom.xml
index 75c1713..ade9aaf 100644
--- a/shenyu-spring-boot-starter/pom.xml
+++ 
b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-api/pom.xml
@@ -16,29 +16,33 @@
   ~ limitations under the License.
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
     <parent>
         <groupId>org.apache.shenyu</groupId>
-        <artifactId>shenyu</artifactId>
+        <artifactId>shenyu-register-instance</artifactId>
         <version>2.4.2-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <artifactId>shenyu-spring-boot-starter</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>shenyu-spring-boot-starter-gateway</module>
-        <module>shenyu-spring-boot-starter-plugin</module>
-        <module>shenyu-spring-boot-starter-sync-data-center</module>
-        <module>shenyu-spring-boot-starter-client</module>
-    </modules>
+    <artifactId>shenyu-register-instance-api</artifactId>
 
     <dependencies>
         <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-configuration-processor</artifactId>
-            <optional>true</optional>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-spi</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-register-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-common</artifactId>
+            <version>${project.version}</version>
         </dependency>
     </dependencies>
-
-</project>
+    
+</project>
\ No newline at end of file
diff --git 
a/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-api/src/main/java/org/apache/shenyu/register/instance/api/ShenyuInstanceRegisterRepository.java
 
b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-api/src/main/java/org/apache/shenyu/register/instance/api/ShenyuInstanceRegisterRepository.java
new file mode 100644
index 0000000..785badd
--- /dev/null
+++ 
b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-api/src/main/java/org/apache/shenyu/register/instance/api/ShenyuInstanceRegisterRepository.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.shenyu.register.instance.api;
+
+import org.apache.shenyu.common.config.ShenyuConfig.InstanceConfig;
+import org.apache.shenyu.register.common.dto.InstanceRegisterDTO;
+import org.apache.shenyu.spi.SPI;
+
+/**
+ * Shenyu instance register repository.
+ */
+@SPI
+public interface ShenyuInstanceRegisterRepository {
+
+    /**
+     * Init.
+     *
+     * @param config the config
+     */
+    default void init(InstanceConfig config) {
+    }
+    
+    /**
+     * Persist instance.
+     *
+     * @param instance instance
+     */
+    void persistInstance(InstanceRegisterDTO instance);
+    
+    /**
+     * Close.
+     */
+    default void close() {
+    }
+}
diff --git a/shenyu-spring-boot-starter/pom.xml 
b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-core/pom.xml
similarity index 58%
copy from shenyu-spring-boot-starter/pom.xml
copy to 
shenyu-register-center/shenyu-register-instance/shenyu-register-instance-core/pom.xml
index 75c1713..a0793a7 100644
--- a/shenyu-spring-boot-starter/pom.xml
+++ 
b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-core/pom.xml
@@ -16,29 +16,28 @@
   ~ limitations under the License.
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
     <parent>
         <groupId>org.apache.shenyu</groupId>
-        <artifactId>shenyu</artifactId>
+        <artifactId>shenyu-register-instance</artifactId>
         <version>2.4.2-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <artifactId>shenyu-spring-boot-starter</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>shenyu-spring-boot-starter-gateway</module>
-        <module>shenyu-spring-boot-starter-plugin</module>
-        <module>shenyu-spring-boot-starter-sync-data-center</module>
-        <module>shenyu-spring-boot-starter-client</module>
-    </modules>
+    <artifactId>shenyu-register-instance-core</artifactId>
 
     <dependencies>
         <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-configuration-processor</artifactId>
-            <optional>true</optional>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-spi</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-register-instance-zookeeper</artifactId>
+            <version>${project.version}</version>
         </dependency>
     </dependencies>
 
-</project>
+</project>
\ No newline at end of file
diff --git 
a/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-core/src/main/java/org/apache/shenyu/register/instance/core/ShenyuInstanceRegisterRepositoryFactory.java
 
b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-core/src/main/java/org/apache/shenyu/register/instance/core/ShenyuInstanceRegisterRepositoryFactory.java
new file mode 100644
index 0000000..9c5a961
--- /dev/null
+++ 
b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-core/src/main/java/org/apache/shenyu/register/instance/core/ShenyuInstanceRegisterRepositoryFactory.java
@@ -0,0 +1,47 @@
+/*
+ * 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.shenyu.register.instance.core;
+
+import 
org.apache.shenyu.register.instance.api.ShenyuInstanceRegisterRepository;
+import org.apache.shenyu.spi.ExtensionLoader;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * The type Shenyu instance register repository factory.
+ */
+public final class ShenyuInstanceRegisterRepositoryFactory {
+    
+    private static final Map<String, ShenyuInstanceRegisterRepository> 
REPOSITORY_MAP = new ConcurrentHashMap<>();
+    
+    /**
+     * New instance shenyu instance register repository.
+     *
+     * @param registerType the config
+     * @return the shenyu instance register repository
+     */
+    public static ShenyuInstanceRegisterRepository newInstance(final String 
registerType) {
+        if (!REPOSITORY_MAP.containsKey(registerType)) {
+            ShenyuInstanceRegisterRepository result = 
ExtensionLoader.getExtensionLoader(ShenyuInstanceRegisterRepository.class).getJoin(registerType);
+            REPOSITORY_MAP.put(registerType, result);
+            return result;
+        }
+        return REPOSITORY_MAP.get(registerType);
+    }
+}
diff --git a/shenyu-spring-boot-starter/pom.xml 
b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-zookeeper/pom.xml
similarity index 51%
copy from shenyu-spring-boot-starter/pom.xml
copy to 
shenyu-register-center/shenyu-register-instance/shenyu-register-instance-zookeeper/pom.xml
index 75c1713..337212c 100644
--- a/shenyu-spring-boot-starter/pom.xml
+++ 
b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-zookeeper/pom.xml
@@ -16,29 +16,36 @@
   ~ limitations under the License.
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
     <parent>
         <groupId>org.apache.shenyu</groupId>
-        <artifactId>shenyu</artifactId>
+        <artifactId>shenyu-register-instance</artifactId>
         <version>2.4.2-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <artifactId>shenyu-spring-boot-starter</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>shenyu-spring-boot-starter-gateway</module>
-        <module>shenyu-spring-boot-starter-plugin</module>
-        <module>shenyu-spring-boot-starter-sync-data-center</module>
-        <module>shenyu-spring-boot-starter-client</module>
-    </modules>
+    <artifactId>shenyu-register-instance-zookeeper</artifactId>
 
     <dependencies>
         <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-configuration-processor</artifactId>
-            <optional>true</optional>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-register-instance-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.101tec</groupId>
+            <artifactId>zkclient</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
     </dependencies>
-
-</project>
+</project>
\ No newline at end of file
diff --git 
a/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-zookeeper/src/main/java/org/apache/shenyu/register/instance/zookeeper/ZookeeperInstanceRegisterRepository.java
 
b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-zookeeper/src/main/java/org/apache/shenyu/register/instance/zookeeper/ZookeeperInstanceRegisterRepository.java
new file mode 100644
index 0000000..94d34d7
--- /dev/null
+++ 
b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-zookeeper/src/main/java/org/apache/shenyu/register/instance/zookeeper/ZookeeperInstanceRegisterRepository.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.shenyu.register.instance.zookeeper;
+
+import org.I0Itec.zkclient.IZkStateListener;
+import org.I0Itec.zkclient.ZkClient;
+import org.apache.shenyu.common.config.ShenyuConfig.InstanceConfig;
+import org.apache.shenyu.common.constant.Constants;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.register.common.dto.InstanceRegisterDTO;
+import org.apache.shenyu.register.common.path.RegisterPathConstants;
+import 
org.apache.shenyu.register.instance.api.ShenyuInstanceRegisterRepository;
+import org.apache.shenyu.spi.Join;
+import org.apache.zookeeper.Watcher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * The type Zookeeper instance register repository.
+ */
+@Join
+public class ZookeeperInstanceRegisterRepository implements 
ShenyuInstanceRegisterRepository {
+
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(ZookeeperInstanceRegisterRepository.class);
+
+    private ZkClient zkClient;
+
+    private final Map<String, String> nodeDataMap = new HashMap<>();
+
+    @Override
+    public void init(final InstanceConfig config) {
+        Properties props = config.getProps();
+        int sessionTimeout = 
Integer.parseInt(props.getProperty("sessionTimeout", "3000"));
+        int connectionTimeout = 
Integer.parseInt(props.getProperty("connectionTimeout", "3000"));
+        this.zkClient = new ZkClient(config.getServerLists(), sessionTimeout, 
connectionTimeout);
+        this.zkClient.subscribeStateChanges(new ZkStateListener());
+    }
+    
+    @Override
+    public void persistInstance(final InstanceRegisterDTO instance) {
+        String uriNodeName = buildURINodeName(instance);
+        String instancePath = RegisterPathConstants.buildInstanceParentPath();
+        if (!zkClient.exists(instancePath)) {
+            zkClient.createPersistent(instancePath, true);
+        }
+        String realNode = RegisterPathConstants.buildRealNode(instancePath, 
uriNodeName);
+        if (!zkClient.exists(realNode)) {
+            String nodeData = GsonUtils.getInstance().toJson(instance);
+            nodeDataMap.put(realNode, nodeData);
+            zkClient.createEphemeral(realNode, nodeData);
+        }
+    }
+    
+    @Override
+    public void close() {
+        zkClient.close();
+    }
+
+    private String buildURINodeName(final InstanceRegisterDTO instance) {
+        String host = instance.getHost();
+        int port = instance.getPort();
+        return String.join(Constants.COLONS, host, Integer.toString(port));
+    }
+
+    private class ZkStateListener implements IZkStateListener {
+        @Override
+        public void handleStateChanged(final Watcher.Event.KeeperState 
keeperState) {
+            if (Watcher.Event.KeeperState.SyncConnected.equals(keeperState)) {
+                nodeDataMap.forEach((k, v) -> {
+                    if (!zkClient.exists(k)) {
+                        zkClient.createEphemeral(k, v);
+                        LOGGER.info("zookeeper client register success: {}", 
v);
+                    }
+                });
+            }
+        }
+
+        @Override
+        public void handleNewSession() {
+        }
+
+        @Override
+        public void handleSessionEstablishmentError(final Throwable throwable) 
{
+        }
+    }
+}
diff --git 
a/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-zookeeper/src/main/resources/META-INF/shenyu/org.apache.shenyu.register.instance.api.ShenyuInstanceRegisterRepository
 
b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-zookeeper/src/main/resources/META-INF/shenyu/org.apache.shenyu.register.instance.api.ShenyuInstanceRegisterRepository
new file mode 100644
index 0000000..92fbfb1
--- /dev/null
+++ 
b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-zookeeper/src/main/resources/META-INF/shenyu/org.apache.shenyu.register.instance.api.ShenyuInstanceRegisterRepository
@@ -0,0 +1,17 @@
+# 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.
+
+zookeeper=org.apache.shenyu.register.instance.zookeeper.ZookeeperInstanceRegisterRepository
diff --git a/shenyu-spring-boot-starter/pom.xml 
b/shenyu-spring-boot-starter/pom.xml
index 75c1713..9a1ec86 100644
--- a/shenyu-spring-boot-starter/pom.xml
+++ b/shenyu-spring-boot-starter/pom.xml
@@ -31,6 +31,7 @@
         <module>shenyu-spring-boot-starter-plugin</module>
         <module>shenyu-spring-boot-starter-sync-data-center</module>
         <module>shenyu-spring-boot-starter-client</module>
+        <module>shenyu-spring-boot-starter-instance</module>
     </modules>
 
     <dependencies>
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-instance/pom.xml 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-instance/pom.xml
new file mode 100644
index 0000000..d1e844a
--- /dev/null
+++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-instance/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <parent>
+        <groupId>org.apache.shenyu</groupId>
+        <artifactId>shenyu-spring-boot-starter</artifactId>
+        <version>2.4.2-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>shenyu-spring-boot-starter-instance</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-register-instance-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-webflux</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-instance/src/main/java/org/apache/shenyu/springboot/starter/instance/InstanceRegisterListener.java
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-instance/src/main/java/org/apache/shenyu/springboot/starter/instance/InstanceRegisterListener.java
new file mode 100644
index 0000000..30bffaa
--- /dev/null
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-instance/src/main/java/org/apache/shenyu/springboot/starter/instance/InstanceRegisterListener.java
@@ -0,0 +1,87 @@
+/*
+ * 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.shenyu.springboot.starter.instance;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shenyu.common.config.ShenyuConfig.InstanceConfig;
+import org.apache.shenyu.common.exception.ShenyuException;
+import org.apache.shenyu.common.utils.IpUtils;
+import org.apache.shenyu.register.common.dto.InstanceRegisterDTO;
+import 
org.apache.shenyu.register.instance.api.ShenyuInstanceRegisterRepository;
+import 
org.apache.shenyu.register.instance.core.ShenyuInstanceRegisterRepositoryFactory;
+import org.springframework.boot.web.context.WebServerInitializedEvent;
+import org.springframework.context.ApplicationListener;
+
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * The type Instance register listener.
+ */
+public class InstanceRegisterListener implements 
ApplicationListener<WebServerInitializedEvent> {
+    
+    private final AtomicBoolean registered = new AtomicBoolean(false);
+    
+    private final String host;
+    
+    private final String appName;
+    
+    private final Properties props;
+    
+    private final ShenyuInstanceRegisterRepository repository;
+    
+    /**
+     * Instantiates a new Instance register listener.
+     *
+     * @param config the config
+     */
+    public InstanceRegisterListener(final InstanceConfig config) {
+        String registerType = config.getRegisterType();
+        String serverLists = config.getServerLists();
+        if (StringUtils.isBlank(registerType) || 
StringUtils.isBlank(serverLists)) {
+            throw new ShenyuException("please config the registerType and 
serverList");
+        }
+        repository = 
ShenyuInstanceRegisterRepositoryFactory.newInstance(config.getRegisterType());
+        repository.init(config);
+        this.props = config.getProps();
+        String name = props.getProperty("name");
+        this.appName = StringUtils.isBlank(name) ? "shenyu-gateway" : name;
+        String host = props.getProperty("host");
+        this.host = StringUtils.isBlank(host) ? IpUtils.getHost() : host;
+    }
+    
+    @Override
+    public void onApplicationEvent(final WebServerInitializedEvent event) {
+        if (!registered.compareAndSet(false, true)) {
+            return;
+        }
+        String configPort = props.getProperty("port");
+        int port = StringUtils.isBlank(configPort) ? 
event.getWebServer().getPort() : Integer.parseInt(configPort);
+        InstanceRegisterDTO registerDTO = buildInstanceRegisterDTO(port);
+        repository.persistInstance(registerDTO);
+    }
+    
+    private InstanceRegisterDTO buildInstanceRegisterDTO(final int port) {
+        String host = IpUtils.isCompleteHost(this.host) ? this.host : 
IpUtils.getHost(this.host);
+        return InstanceRegisterDTO.builder()
+                .appName(appName)
+                .host(host)
+                .port(port)
+                .build();
+    }
+}
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-instance/src/main/java/org/apache/shenyu/springboot/starter/instance/ShenyuInstanceConfiguration.java
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-instance/src/main/java/org/apache/shenyu/springboot/starter/instance/ShenyuInstanceConfiguration.java
new file mode 100644
index 0000000..0ab5853
--- /dev/null
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-instance/src/main/java/org/apache/shenyu/springboot/starter/instance/ShenyuInstanceConfiguration.java
@@ -0,0 +1,42 @@
+/*
+ * 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.shenyu.springboot.starter.instance;
+
+import org.apache.shenyu.common.config.ShenyuConfig;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * The type Shenyu instance configuration.
+ */
+@Configuration
+public class ShenyuInstanceConfiguration {
+    
+    /**
+     * Instance register listener.
+     *
+     * @param config the config
+     * @return the instance register listener
+     */
+    @Bean
+    @ConditionalOnProperty(name = "shenyu.instance.enabled", havingValue = 
"true")
+    public InstanceRegisterListener instanceRegisterListener(final 
ShenyuConfig config) {
+        return new InstanceRegisterListener(config.getInstance());
+    }
+}
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-instance/src/main/resources/META-INF/spring.factories
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-instance/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..4b4777c
--- /dev/null
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-instance/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,3 @@
+# Auto Configure
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+org.apache.shenyu.springboot.starter.instance.ShenyuInstanceConfiguration
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-instance/src/main/resources/META-INF/spring.provides
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-instance/src/main/resources/META-INF/spring.provides
new file mode 100644
index 0000000..23291ec
--- /dev/null
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-instance/src/main/resources/META-INF/spring.provides
@@ -0,0 +1 @@
+provides: shenyu-spring-boot-starter-instance
\ No newline at end of file

Reply via email to