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

xiaoyu 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 09c571cbc Features: new shenyu-proxy, partial implementation of the 
network layer. (#3074)
09c571cbc is described below

commit 09c571cbc2df0fa9449c23756b2e117cf7e6543f
Author: Sixh-PrFor <[email protected]>
AuthorDate: Mon Apr 18 14:03:07 2022 +0800

    Features: new shenyu-proxy, partial implementation of the network layer. 
(#3074)
    
    * New shenyu-proxy, partial implementation of the network layer.
    
    * New shenyu-proxy, partial implementation of the network layer.
    
    * New shenyu-proxy, partial implementation of the network layer.
    
    * fix: pls in english
    
    * fix: pls in english
    
    * channel business encapsulation
---
 pom.xml                                            |   1 +
 .../loadbalancer/cache/UpstreamCheckTaskTest.java  |   2 +-
 shenyu-proxy/pom.xml                               |  47 +++++++
 shenyu-proxy/proxy-remote/pom.xml                  |  41 ++++++
 .../apache/shenyu/proxy/remote/AbstractServer.java | 109 +++++++++++++++
 .../org/apache/shenyu/proxy/remote/Channel.java    |  76 +++++++++++
 .../apache/shenyu/proxy/remote/ChannelFuture.java  |  55 ++++++++
 .../apache/shenyu/proxy/remote/ChannelHandler.java |  63 +++++++++
 .../org/apache/shenyu/proxy/remote/Server.java     |  31 +++++
 .../apache/shenyu/proxy/remote/ServerConfig.java   |  70 ++++++++++
 .../shenyu/proxy/remote/netty/NettyChannel.java    | 150 +++++++++++++++++++++
 .../proxy/remote/netty/NettyChannelFuture.java     |  80 +++++++++++
 .../shenyu/proxy/remote/netty/NettyServer.java     | 136 +++++++++++++++++++
 .../proxy/remote/netty/NettyServerHandler.java     | 114 ++++++++++++++++
 .../shenyu/proxy/remote/NettyServerTest.java       |  33 +++++
 15 files changed, 1007 insertions(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index b7e276887..7c99cc567 100644
--- a/pom.xml
+++ b/pom.xml
@@ -42,6 +42,7 @@
         <module>shenyu-protocol</module>
         <module>shenyu-loadbalancer</module>
         <module>shenyu-dist</module>
+        <module>shenyu-proxy</module>
     </modules>
 
     <licenses>
diff --git 
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/cache/UpstreamCheckTaskTest.java
 
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/cache/UpstreamCheckTaskTest.java
index 5dbb5db52..51c0a21cd 100644
--- 
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/cache/UpstreamCheckTaskTest.java
+++ 
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/cache/UpstreamCheckTaskTest.java
@@ -84,7 +84,7 @@ public class UpstreamCheckTaskTest {
         // Let it coverage line 151~163.
         when(upstream.isHealthy()).thenReturn(false).thenReturn(true);
         // Even if the address could not connect, it will return false, that 
mean it will not coverage 151~163.
-        when(upstream.getUrl()).thenReturn("http://www.baidu.com";);
+        when(upstream.getUrl()).thenReturn("https://www.baidu.com";);
         // Manually run one time
         healthCheckTask.run();
         Awaitility.await().pollDelay(1, TimeUnit.SECONDS).untilAsserted(() -> 
assertFalse(healthCheckTask.getCheckStarted().get()));
diff --git a/shenyu-proxy/pom.xml b/shenyu-proxy/pom.xml
new file mode 100644
index 000000000..accee5c8f
--- /dev/null
+++ b/shenyu-proxy/pom.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <parent>
+        <artifactId>shenyu</artifactId>
+        <groupId>org.apache.shenyu</groupId>
+        <version>2.4.3-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>shenyu-proxy</artifactId>
+    <packaging>pom</packaging>
+    <modules>
+        <module>proxy-remote</module>
+    </modules>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+
+</project>
\ No newline at end of file
diff --git a/shenyu-proxy/proxy-remote/pom.xml 
b/shenyu-proxy/proxy-remote/pom.xml
new file mode 100644
index 000000000..b92a8118b
--- /dev/null
+++ b/shenyu-proxy/proxy-remote/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <parent>
+        <artifactId>shenyu-proxy</artifactId>
+        <groupId>org.apache.shenyu</groupId>
+        <version>2.4.3-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>proxy-remote</artifactId>
+    <dependencies>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-all</artifactId>
+        </dependency>
+    </dependencies>
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+
+</project>
\ No newline at end of file
diff --git 
a/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/AbstractServer.java
 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/AbstractServer.java
new file mode 100644
index 000000000..d2c905159
--- /dev/null
+++ 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/AbstractServer.java
@@ -0,0 +1,109 @@
+/*
+ * 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.proxy.remote;
+
+/**
+ * AbstractServer .
+ * start server abstraction.
+ */
+public abstract class AbstractServer implements Server, ChannelHandler {
+    
+    /**
+     * Handle related handlers.
+     */
+    private final ChannelHandler channelHandler;
+    
+    /**
+     * Instantiates a new Abstract server.
+     *
+     * @param channelHandler the channel handler
+     */
+    public AbstractServer(final ChannelHandler channelHandler) {
+        this.channelHandler = channelHandler;
+    }
+    
+    /**
+     * start a server.
+     *
+     * @param config Started config processing.
+     */
+    @Override
+    public void start(final ServerConfig config) {
+        this.start0(config.getPort());
+    }
+    
+    /**
+     * send a message.
+     *
+     * @param channel the channel
+     * @param message the message
+     */
+    @Override
+    public void sent(final Channel channel, final Object message) {
+        channelHandler.sent(channel, message);
+    }
+    
+    /**
+     * Handling of received messages.
+     *
+     * @param channel the channel
+     * @param message the message
+     */
+    @Override
+    public void receive(final Channel channel, final Object message) {
+        channelHandler.receive(channel, message);
+    }
+    
+    /**
+     * connect.
+     *
+     * @param channel the channel
+     */
+    @Override
+    public void connection(final Channel channel) {
+        channelHandler.connection(channel);
+    }
+    
+    /**
+     * Disconnect.
+     *
+     * @param channel the channel
+     */
+    @Override
+    public void disConnection(final Channel channel) {
+        channelHandler.disConnection(channel);
+    }
+    
+    /**
+     * An exception occurred.
+     *
+     * @param channel   the channel
+     * @param throwable the throwable
+     */
+    @Override
+    public void caught(final Channel channel, final Throwable throwable) {
+        channelHandler.caught(channel, throwable);
+    }
+    
+    /**
+     * start a server.
+     *
+     * @param port the port
+     */
+    protected abstract void start0(int port);
+}
diff --git 
a/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/Channel.java
 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/Channel.java
new file mode 100644
index 000000000..4ed21d346
--- /dev/null
+++ 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/Channel.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.shenyu.proxy.remote;
+
+import java.net.SocketAddress;
+
+/**
+ * Channel .
+ * Encapsulate the channel.
+ */
+public interface Channel {
+    
+    /**
+     * send.
+     * Send data to network channel.
+     *
+     * @param message the message
+     * @return the channel future
+     */
+    ChannelFuture send(Object message);
+    
+    /**
+     * Determine if it is connected.
+     *
+     * @return boolean boolean
+     */
+    boolean isConnected();
+    
+    /**
+     * remote address.
+     *
+     * @return socket address
+     */
+    SocketAddress remoteAddress();
+    
+    /**
+     * Local address socket address.
+     *
+     * @return the socket address
+     */
+    SocketAddress localAddress();
+    
+    /**
+     * Is opened boolean.
+     *
+     * @return the boolean
+     */
+    boolean isOpened();
+    
+    /**
+     * Is close boolean.
+     *
+     * @return the boolean
+     */
+    boolean isClose();
+    
+    /**
+     * Close.
+     */
+    void close();
+}
diff --git 
a/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/ChannelFuture.java
 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/ChannelFuture.java
new file mode 100644
index 000000000..6b9644d8d
--- /dev/null
+++ 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/ChannelFuture.java
@@ -0,0 +1,55 @@
+/*
+ * 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.proxy.remote;
+
+import java.util.function.Consumer;
+
+/**
+ * ChannelFuture .
+ * channel future.
+ */
+public interface ChannelFuture {
+    
+    /**
+     * Complete.
+     *
+     * @param consumer the consumer
+     */
+    void onComplete(Consumer<ChannelFuture> consumer);
+    
+    /**
+     * Is done boolean.
+     *
+     * @return the boolean
+     */
+    boolean isDone();
+    
+    /**
+     * Cause thread.
+     *
+     * @return the thread
+     */
+    Throwable cause();
+    
+    /**
+     * Is connected boolean.
+     *
+     * @return the boolean
+     */
+    boolean isConnected();
+}
diff --git 
a/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/ChannelHandler.java
 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/ChannelHandler.java
new file mode 100644
index 000000000..fc467d0ec
--- /dev/null
+++ 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/ChannelHandler.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.shenyu.proxy.remote;
+
+/**
+ * ChannelHandler .
+ * channel handler Processed event notifications.
+ */
+public interface ChannelHandler {
+    
+    /**
+     * send a message.
+     *
+     * @param channel the channel
+     * @param message the message
+     */
+    void sent(Channel channel, Object message);
+    
+    /**
+     * Handling of received messages.
+     *
+     * @param channel the channel
+     * @param message the message
+     */
+    void receive(Channel channel, Object message);
+    
+    /**
+     * connect.
+     *
+     * @param channel the channel
+     */
+    void connection(Channel channel);
+    
+    /**
+     * Disconnect.
+     *
+     * @param channel the channel
+     */
+    void disConnection(Channel channel);
+    
+    /**
+     * An exception occurred.
+     *
+     * @param channel   the channel
+     * @param throwable the throwable
+     */
+    void caught(Channel channel, Throwable throwable);
+}
diff --git 
a/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/Server.java
 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/Server.java
new file mode 100644
index 000000000..973d3e95f
--- /dev/null
+++ 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/Server.java
@@ -0,0 +1,31 @@
+/*
+ * 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.proxy.remote;
+
+/**
+ * Server .
+ */
+public interface Server extends ChannelHandler {
+    
+    /**
+     * start server.
+     *
+     * @param config config.
+     */
+    void start(ServerConfig config);
+}
diff --git 
a/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/ServerConfig.java
 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/ServerConfig.java
new file mode 100644
index 000000000..45c297a56
--- /dev/null
+++ 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/ServerConfig.java
@@ -0,0 +1,70 @@
+/*
+ * 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.proxy.remote;
+
+/**
+ * ServerConfig .
+ */
+public class ServerConfig {
+    
+    /**
+     * address.
+     */
+    private String address;
+    
+    /**
+     * port.
+     */
+    private Integer port;
+    
+    /**
+     * Gets address.
+     *
+     * @return the address
+     */
+    public String getAddress() {
+        return address;
+    }
+    
+    /**
+     * Sets address.
+     *
+     * @param address the address
+     */
+    public void setAddress(final String address) {
+        this.address = address;
+    }
+    
+    /**
+     * Gets port.
+     *
+     * @return the port
+     */
+    public Integer getPort() {
+        return port;
+    }
+    
+    /**
+     * Sets port.
+     *
+     * @param port the port
+     */
+    public void setPort(final Integer port) {
+        this.port = port;
+    }
+}
diff --git 
a/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/netty/NettyChannel.java
 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/netty/NettyChannel.java
new file mode 100644
index 000000000..0915d27b4
--- /dev/null
+++ 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/netty/NettyChannel.java
@@ -0,0 +1,150 @@
+/*
+ * 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.proxy.remote.netty;
+
+import io.netty.channel.ChannelFutureListener;
+import org.apache.shenyu.proxy.remote.Channel;
+import org.apache.shenyu.proxy.remote.ChannelFuture;
+
+import java.net.SocketAddress;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * NettyChannel .
+ */
+public class NettyChannel implements Channel {
+    
+    private static final ConcurrentMap<io.netty.channel.Channel, NettyChannel> 
CHANNEL_CACHE = new ConcurrentHashMap<>();
+    
+    private final io.netty.channel.Channel channel;
+    
+    /**
+     * Instantiates a new Netty channel.
+     *
+     * @param channel the channel
+     */
+    public NettyChannel(final io.netty.channel.Channel channel) {
+        this.channel = channel;
+    }
+    
+    /**
+     * send.
+     * Send data to network channel.
+     *
+     * @param message the message
+     * @return the channel future
+     */
+    @Override
+    public ChannelFuture send(final Object message) {
+        io.netty.channel.ChannelFuture channelFuture = 
channel.writeAndFlush(message);
+        return new NettyChannelFuture(channelFuture);
+    }
+    
+    /**
+     * Determine if it is connected.
+     *
+     * @return boolean boolean
+     */
+    @Override
+    public boolean isConnected() {
+        return channel.isActive();
+    }
+    
+    /**
+     * remote address.
+     *
+     * @return socket address
+     */
+    @Override
+    public SocketAddress remoteAddress() {
+        return channel.remoteAddress();
+    }
+    
+    /**
+     * Local address socket address.
+     *
+     * @return the socket address
+     */
+    @Override
+    public SocketAddress localAddress() {
+        return channel.localAddress();
+    }
+    
+    /**
+     * Is opened boolean.
+     *
+     * @return the boolean
+     */
+    @Override
+    public boolean isOpened() {
+        return channel.isOpen();
+    }
+    
+    /**
+     * Is close boolean.
+     *
+     * @return the boolean
+     */
+    @Override
+    public boolean isClose() {
+        return !this.isOpened();
+    }
+    
+    /**
+     * Close.
+     */
+    @Override
+    public void close() {
+        channel.close().addListener((ChannelFutureListener) channelFuture -> {
+            removeChannel(channel);
+        });
+    }
+    
+    /**
+     * Get a channel, create a Netty Channel if it doesn't exist.
+     *
+     * @param channel the channel nettyChannel.
+     * @return the or add channel
+     */
+    public static NettyChannel getOrAddChannel(final io.netty.channel.Channel 
channel) {
+        NettyChannel nettyChannel = CHANNEL_CACHE.get(channel);
+        
+        if (nettyChannel == null) {
+            NettyChannel ret = new NettyChannel(channel);
+            if (channel.isActive()) {
+                nettyChannel = CHANNEL_CACHE.putIfAbsent(channel, ret);
+            }
+            if (nettyChannel == null) {
+                nettyChannel = ret;
+            }
+        }
+        return nettyChannel;
+    }
+    
+    /**
+     * If the channel has been disconnected, it is removed from the cache.
+     *
+     * @param channel the channel
+     */
+    public static void removeChannel(final io.netty.channel.Channel channel) {
+        if (channel != null && !channel.isActive()) {
+            CHANNEL_CACHE.remove(channel);
+        }
+    }
+}
diff --git 
a/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/netty/NettyChannelFuture.java
 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/netty/NettyChannelFuture.java
new file mode 100644
index 000000000..92a0d5d54
--- /dev/null
+++ 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/netty/NettyChannelFuture.java
@@ -0,0 +1,80 @@
+/*
+ * 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.proxy.remote.netty;
+
+import org.apache.shenyu.proxy.remote.ChannelFuture;
+
+import java.util.function.Consumer;
+
+/**
+ * NettyChannelFuture .
+ * proxy wap channel future.
+ */
+public class NettyChannelFuture implements ChannelFuture {
+    
+    private io.netty.channel.ChannelFuture future;
+    
+    /**
+     * Instantiates a new Netty channel future..
+     *
+     * @param future future.
+     */
+    public NettyChannelFuture(final io.netty.channel.ChannelFuture future) {
+        this.future = future;
+    }
+    
+    /**
+     * Complete.
+     *
+     * @param consumer the consumer
+     */
+    @Override
+    public void onComplete(final Consumer<ChannelFuture> consumer) {
+    
+    }
+    
+    /**
+     * Is done boolean.
+     *
+     * @return the boolean
+     */
+    @Override
+    public boolean isDone() {
+        return false;
+    }
+    
+    /**
+     * Cause thread.
+     *
+     * @return the thread
+     */
+    @Override
+    public Throwable cause() {
+        return null;
+    }
+    
+    /**
+     * Is connected boolean.
+     *
+     * @return the boolean
+     */
+    @Override
+    public boolean isConnected() {
+        return false;
+    }
+}
diff --git 
a/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/netty/NettyServer.java
 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/netty/NettyServer.java
new file mode 100644
index 000000000..ef48e3af6
--- /dev/null
+++ 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/netty/NettyServer.java
@@ -0,0 +1,136 @@
+/*
+ * 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.proxy.remote.netty;
+
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.buffer.PooledByteBufAllocator;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.epoll.EpollEventLoopGroup;
+import io.netty.channel.epoll.EpollServerSocketChannel;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.codec.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpRequestDecoder;
+import io.netty.handler.codec.http.HttpResponseEncoder;
+import io.netty.handler.stream.ChunkedWriteHandler;
+import io.netty.handler.timeout.IdleStateHandler;
+import org.apache.shenyu.common.concurrent.ShenyuThreadFactory;
+import org.apache.shenyu.proxy.remote.AbstractServer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetSocketAddress;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * NettyServer .
+ * netty network management.
+ */
+public class NettyServer extends AbstractServer {
+    
+    private final Logger logger = LoggerFactory.getLogger(NettyServer.class);
+    
+    /**
+     * service starter.
+     */
+    private final ServerBootstrap server;
+    
+    /**
+     * service processing.
+     */
+    private EventLoopGroup boosGroup;
+    
+    /**
+     * task processing thread.
+     */
+    private EventLoopGroup workGroup;
+    
+    private final int threads = Runtime.getRuntime().availableProcessors() << 
1;
+    
+    
+    /**
+     * Instantiates a new Abstract server.
+     */
+    public NettyServer() {
+        super(null);
+        this.server = new ServerBootstrap();
+    }
+    
+    /**
+     * start a server.
+     *
+     * @param port the port
+     */
+    @Override
+    protected void start0(final int port) {
+        //Judge Linux system
+        if (isLinux()) {
+            boosGroup = new EpollEventLoopGroup(1, 
ShenyuThreadFactory.create("shenyu_proxy_server_boss_epoll", false));
+            workGroup = new EpollEventLoopGroup(threads, 
ShenyuThreadFactory.create("shenyu_proxy_server_work_epoll", false));
+            server.channel(EpollServerSocketChannel.class);
+        } else {
+            boosGroup = new NioEventLoopGroup(1, 
ShenyuThreadFactory.create("shenyu_proxy_server_boss_epoll", false));
+            workGroup = new NioEventLoopGroup(threads, 
ShenyuThreadFactory.create("shenyu_proxy_server_work_epoll", false));
+            server.channel(NioServerSocketChannel.class);
+        }
+        NettyServerHandler nettyServerHandler = new NettyServerHandler(this);
+        server.group(boosGroup, workGroup)
+                .option(ChannelOption.SO_BACKLOG, 65535)
+                .option(ChannelOption.SO_REUSEADDR, true)
+                .option(ChannelOption.SO_KEEPALIVE, true)
+                .option(ChannelOption.ALLOCATOR, 
PooledByteBufAllocator.DEFAULT)
+                .childOption(ChannelOption.TCP_NODELAY, true)
+                .childOption(ChannelOption.ALLOCATOR, 
PooledByteBufAllocator.DEFAULT)
+                .childHandler(new ChannelInitializer<Channel>() {
+                    @Override
+                    protected void initChannel(final Channel channel) {
+                        channel.pipeline().addLast(new IdleStateHandler(4000, 
0, 0, TimeUnit.MILLISECONDS));
+                        channel.pipeline().addLast("http-decoder", new 
HttpRequestDecoder());
+                        channel.pipeline().addLast("http-aggregator", new 
HttpObjectAggregator(65535));
+                        channel.pipeline().addLast("http-encoder", new 
HttpResponseEncoder());
+                        channel.pipeline().addLast("chunkedWriter", new 
ChunkedWriteHandler());
+                        channel.pipeline().addLast(nettyServerHandler);
+                    }
+                });
+        //setup information
+        try {
+            Channel channel = server.bind(port).sync().channel();
+            logger.info("Network listening,ip:{},port:{}", 
((InetSocketAddress) channel.localAddress()).getHostString(), port);
+            channel.closeFuture().sync();
+        } catch (InterruptedException e) {
+            logger.error("Error Network listening...... " + e.getMessage());
+            throw new RuntimeException("Error Network listening " + 
e.getMessage());
+        } finally {
+            boosGroup.shutdownGracefully();
+            workGroup.shutdownGracefully();
+        }
+    }
+    
+    /**
+     * Determine whether it is a Linux operating system.
+     *
+     * @return the boolean
+     */
+    public static boolean isLinux() {
+        final String oS = System.getProperty("os.name").toLowerCase();
+        return oS.contains("linux");
+    }
+}
diff --git 
a/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/netty/NettyServerHandler.java
 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/netty/NettyServerHandler.java
new file mode 100644
index 000000000..0a8a1b550
--- /dev/null
+++ 
b/shenyu-proxy/proxy-remote/src/main/java/org/apache/shenyu/proxy/remote/netty/NettyServerHandler.java
@@ -0,0 +1,114 @@
+/*
+ * 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.proxy.remote.netty;
+
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelPromise;
+import io.netty.handler.timeout.IdleState;
+import io.netty.handler.timeout.IdleStateEvent;
+
+/**
+ * NettyServerHandler .
+ * Processing of netty server.
+ *
+ * @author sixh chenbin
+ */
[email protected]
+public class NettyServerHandler extends ChannelDuplexHandler {
+    
+    private final org.apache.shenyu.proxy.remote.ChannelHandler channelHandler;
+    
+    public NettyServerHandler(final 
org.apache.shenyu.proxy.remote.ChannelHandler channelHandler) {
+        this.channelHandler = channelHandler;
+    }
+    
+    @Override
+    public void channelActive(final ChannelHandlerContext ctx) throws 
Exception {
+        super.channelActive(ctx);
+        NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel());
+        try {
+            channelHandler.connection(channel);
+        } finally {
+            NettyChannel.removeChannel(ctx.channel());
+        }
+    }
+    
+    @Override
+    public void channelInactive(final ChannelHandlerContext ctx) throws 
Exception {
+        super.channelInactive(ctx);
+        try {
+            NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel());
+            channelHandler.disConnection(channel);
+        } finally {
+            NettyChannel.removeChannel(ctx.channel());
+        }
+    }
+    
+    @Override
+    public void channelRead(final ChannelHandlerContext ctx, final Object msg) 
throws Exception {
+        NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel());
+        try {
+            channelHandler.receive(channel, msg);
+        } finally {
+            NettyChannel.removeChannel(ctx.channel());
+        }
+    }
+    
+    @Override
+    public void write(final ChannelHandlerContext ctx,
+                      final Object msg, final ChannelPromise promise) throws 
Exception {
+        super.write(ctx, msg, promise);
+        NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel());
+        try {
+            channelHandler.sent(channel, msg);
+        } finally {
+            NettyChannel.removeChannel(ctx.channel());
+        }
+    }
+    
+    @Override
+    public void userEventTriggered(final ChannelHandlerContext ctx, final 
Object evt) throws Exception {
+        if (evt instanceof IdleStateEvent) {
+            IdleState state = ((IdleStateEvent) evt).state();
+            NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel());
+            try {
+                switch (state) {
+                    case READER_IDLE:
+                    case WRITER_IDLE:
+                    case ALL_IDLE:
+                        channel.close();
+                        return;
+                    default:
+                        break;
+                }
+            } finally {
+                NettyChannel.removeChannel(ctx.channel());
+            }
+        }
+        super.userEventTriggered(ctx, evt);
+    }
+    
+    @Override
+    public void exceptionCaught(final ChannelHandlerContext ctx, final 
Throwable cause) throws Exception {
+        NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel());
+        channelHandler.caught(channel, cause);
+    }
+    
+}
diff --git 
a/shenyu-proxy/proxy-remote/src/test/java/org/apache/shenyu/proxy/remote/NettyServerTest.java
 
b/shenyu-proxy/proxy-remote/src/test/java/org/apache/shenyu/proxy/remote/NettyServerTest.java
new file mode 100644
index 000000000..706a45aa7
--- /dev/null
+++ 
b/shenyu-proxy/proxy-remote/src/test/java/org/apache/shenyu/proxy/remote/NettyServerTest.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.proxy.remote;
+
+import org.junit.Test;
+
+/**
+ * NettyServerTest .
+ */
+public class NettyServerTest {
+    
+    /**
+     * Test server startup.
+     */
+    @Test
+    public void testServer() {
+    }
+}

Reply via email to