You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by jo...@apache.org on 2023/09/17 03:19:16 UTC

[shenyu] branch master updated: add ingress-controller integration websocket test (#5160)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 925be2c90e add ingress-controller integration websocket test (#5160)
925be2c90e is described below

commit 925be2c90ef305f74bd9be355c820355b75f4cae
Author: Runqi Zhao <40...@users.noreply.github.com>
AuthorDate: Sun Sep 17 11:19:11 2023 +0800

    add ingress-controller integration websocket test (#5160)
    
    * add ingress-controller integration websocket test
    
    * add ingress-controller integration websocket test
    
    * add ingress-controller integration websocket test
    
    ---------
    
    Co-authored-by: Kunshuai Zhu <jo...@gmail.com>
---
 .../integrated-test-k8s-ingress-websocket.yml      | 135 +++++++++
 .../k8s/ingress.yml                                |  35 +++
 .../shenyu-example-spring-annotation-websocket.yml |  75 +++++
 .../pom.xml                                        |  46 +++
 shenyu-integrated-test/pom.xml                     |   1 +
 .../Dockerfile                                     |  29 ++
 .../deploy/deploy-shenyu.yaml                      | 107 +++++++
 .../deploy/kind-config.yaml                        |  36 +++
 .../pom.xml                                        | 150 ++++++++++
 .../script/healthcheck.sh                          |  36 +++
 .../script/services.list                           |  17 ++
 .../WebsocketIngressIntegratedBootstrap.java       |  34 +++
 .../src/main/resources/application.yml             | 329 +++++++++++++++++++++
 .../k8s/ingress/websocket/WebsocketPluginTest.java |  70 +++++
 14 files changed, 1100 insertions(+)

diff --git a/.github/workflows/integrated-test-k8s-ingress-websocket.yml b/.github/workflows/integrated-test-k8s-ingress-websocket.yml
new file mode 100644
index 0000000000..96978d896a
--- /dev/null
+++ b/.github/workflows/integrated-test-k8s-ingress-websocket.yml
@@ -0,0 +1,135 @@
+# 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.
+
+name: it-k8s
+
+on:
+  pull_request:
+  push:
+    branches:
+      - master
+
+jobs:
+  ingress-controller-websocket:
+    runs-on: ubuntu-latest
+    if: (github.repository == 'apache/shenyu')
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          submodules: true
+
+      - uses: dorny/paths-filter@v2
+        id: filter
+        with:
+          filters: '.github/filters.yml'
+          list-files: json
+
+      - name: Clean Space
+        if: steps.filter.outputs.changed == 'true'
+        run: |
+          sudo rm -rf /usr/share/dotnet
+          sudo rm -rf /opt/ghc
+          sudo rm -rf "/usr/local/share/boost"
+          sudo rm -rf "$AGENT_TOOLSDIRECTORY"
+
+      - name: Cache Maven Repos
+        if: steps.filter.outputs.changed == 'true'
+        uses: actions/cache@v3
+        with:
+          path: ~/.m2/repository
+          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+          restore-keys: |
+            ${{ runner.os }}-maven-
+
+      - uses: actions/setup-java@v3
+        if: steps.filter.outputs.changed == 'true'
+        with:
+          java-version: 8
+          distribution: 'temurin'
+
+      - name: Install Go
+        uses: actions/setup-go@v3
+        with:
+          go-version: 1.17.x
+
+      - name: Install k8s
+        if: steps.filter.outputs.changed == 'true'
+        run: |
+          go install sigs.k8s.io/kind@v0.14.0
+          curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.24.14/bin/linux/amd64/kubectl && sudo install kubectl /usr/local/bin/kubectl
+          kind create cluster --image=kindest/node:v1.21.1 --config=./shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/deploy/kind-config.yaml
+          
+
+      - name: Cache Maven Repos
+        if: steps.filter.outputs.changed == 'true'
+        uses: actions/cache@v3
+        with:
+          path: ~/.m2/repository
+          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+          restore-keys: |
+            ${{ runner.os }}-maven-
+
+      - uses: actions/setup-java@v3
+        if: steps.filter.outputs.changed == 'true'
+        with:
+          java-version: 8
+          distribution: 'temurin'
+
+      - name: Build with Maven
+        if: steps.filter.outputs.changed == 'true'
+        run: ./mvnw -B clean install -Dmaven.javadoc.skip=true -Dmaven.test.skip=true
+
+      - name: Build integrated tests
+        if: steps.filter.outputs.changed == 'true'
+        run: ./mvnw -B clean install -Pit -DskipTests -f ./shenyu-integrated-test/pom.xml
+
+      - name: Build examples
+        if: steps.filter.outputs.changed == 'true'
+        run: ./mvnw -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -f ./shenyu-examples/pom.xml
+
+      - name: Build k8s Cluster
+        if: steps.filter.outputs.changed == 'true'
+        run: |
+          kind load docker-image "shenyu-example-spring-annotation-websocket:latest"
+          kind load docker-image "apache/shenyu-integrated-test-k8s-ingress-websocket:latest"
+          kubectl apply -f ./shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/deploy/deploy-shenyu.yaml
+          kubectl apply -f ./shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/k8s/shenyu-example-spring-annotation-websocket.yml
+          kubectl apply -f ./shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/k8s/ingress.yml
+
+      - name: Wait for k8s Cluster Start up
+        if: steps.filter.outputs.changed == 'true'
+        run: |
+          bash ./shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/script/healthcheck.sh
+
+      - name: Run test
+        id: test
+        if: steps.filter.outputs.changed == 'true'
+        run: ./mvnw test -Pit -f ./shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/pom.xml
+        continue-on-error: true
+
+      - name: Cluster Test after Healthcheck
+        if: steps.filter.outputs.changed == 'true'
+        run: |
+          kubectl get all
+          kubectl get all -n shenyu-ingress
+          kubectl get events --all-namespaces
+          kubectl logs -l app=shenyu-ingress-controller -n shenyu-ingress --tail=-1
+          if [[ ${{steps.test.outcome}} == "failure" ]]; then
+            echo "Test Failed"
+            exit 1
+          else
+            echo "Test Successful"
+            exit 0
+          fi
diff --git a/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/k8s/ingress.yml b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/k8s/ingress.yml
new file mode 100644
index 0000000000..daa4e552f0
--- /dev/null
+++ b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/k8s/ingress.yml
@@ -0,0 +1,35 @@
+# 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: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  annotations:
+    kubernetes.io/ingress.class: shenyu
+    shenyu.apache.org/loadbalancer: random
+    shenyu.apache.org/plugin-web-socket-enabled : "true"
+  name: demo-ingress
+spec:
+  rules:
+    - http:
+        paths:
+          - backend:
+              service:
+                name: shenyu-example-spring-annotation-websocket
+                port:
+                  number: 8001
+            path: /**
+            pathType: ImplementationSpecific
diff --git a/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/k8s/shenyu-example-spring-annotation-websocket.yml b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/k8s/shenyu-example-spring-annotation-websocket.yml
new file mode 100644
index 0000000000..30db439e44
--- /dev/null
+++ b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/k8s/shenyu-example-spring-annotation-websocket.yml
@@ -0,0 +1,75 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: shenyu-example-spring-annotation-websocket-deployment
+  labels:
+    app: shenyu-example-spring-annotation-websocket
+    all: shenyu-example-spring-annotation-websocket
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: shenyu-example-spring-annotation-websocket
+      all: shenyu-example-spring-annotation-websocket
+  strategy: {}
+  template:
+    metadata:
+      labels:
+        app: shenyu-example-spring-annotation-websocket
+        all: shenyu-example-spring-annotation-websocket
+    spec:
+      containers:
+        - image: shenyu-example-spring-annotation-websocket
+          name: shenyu-example-spring-annotation-websocket
+          livenessProbe:
+            exec:
+              command:
+                - wget -q -O - http://localhost:8001/actuator/health | grep UP || exit 1
+            initialDelaySeconds: 10
+            failureThreshold: 3
+            timeoutSeconds: 2
+          env:
+            - name: shenyu.register.serverLists
+              value: http://shenyu-admin:9095
+          ports:
+            - containerPort: 8001
+          imagePullPolicy: IfNotPresent
+      restartPolicy: Always
+status: {}
+
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: shenyu-example-spring-annotation-websocket
+  labels:
+    app: shenyu-example-spring-annotation-websocket
+    all: shenyu-example-spring-annotation-websocket
+spec:
+  selector:
+    app: shenyu-example-spring-annotation-websocket
+    all: shenyu-example-spring-annotation-websocket
+  type: NodePort
+  ports:
+    - name: "8001"
+      port: 8001
+      targetPort: 8001
+      nodePort: 31190
+status:
+  loadBalancer: {}
diff --git a/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/pom.xml b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/pom.xml
index 3e6683d29c..ed515f1aea 100644
--- a/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/pom.xml
+++ b/shenyu-examples/shenyu-examples-websocket/shenyu-example-spring-annotation-websocket/pom.xml
@@ -61,12 +61,58 @@
     </dependencies>
 
     <build>
+        <finalName>shenyu-example-spring-annotation-websocket</finalName>
         <plugins>
             <plugin>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <mainClass>org.apache.shenyu.examples.websocket.TestAnnotationWebsocketApplication</mainClass>
+                    <executable>true</executable>
+                </configuration>
             </plugin>
         </plugins>
     </build>
 
+    <profiles>
+        <profile>
+            <id>example</id>
+            <properties>
+                <docker.buildArg.APP_NAME>shenyu-example-spring-annotation-websocket</docker.buildArg.APP_NAME>
+                <docker.image.tag.repo>shenyu-example-spring-annotation-websocket</docker.image.tag.repo>
+                <docker.image.tag.tagName>latest</docker.image.tag.tagName>
+            </properties>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>io.fabric8</groupId>
+                        <artifactId>docker-maven-plugin</artifactId>
+                        <version>${docker-maven-plugin.version}</version>
+                        <configuration>
+                            <images>
+                                <image>
+                                    <name>shenyu-example-spring-annotation-websocket</name>
+                                    <build>
+                                        <contextDir>${project.basedir}</contextDir>
+                                    </build>
+                                </image>
+                            </images>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>start</id>
+                                <goals>
+                                    <goal>build</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
 </project>
diff --git a/shenyu-integrated-test/pom.xml b/shenyu-integrated-test/pom.xml
index 4e70e6e764..a24d82677e 100644
--- a/shenyu-integrated-test/pom.xml
+++ b/shenyu-integrated-test/pom.xml
@@ -49,6 +49,7 @@
         <module>shenyu-integrated-test-k8s-ingress-spring-cloud</module>
         <module>shenyu-integrated-test-k8s-ingress-motan</module>
         <module>shenyu-integrated-test-k8s-ingress-apache-dubbo</module>
+        <module>shenyu-integrated-test-k8s-ingress-websocket</module>
     </modules>
 
     <properties>
diff --git a/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/Dockerfile b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/Dockerfile
new file mode 100644
index 0000000000..152a7d0f4d
--- /dev/null
+++ b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/Dockerfile
@@ -0,0 +1,29 @@
+# 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.
+
+FROM openjdk:8-jre-alpine
+
+ENV APP_NAME shenyu-integrated-test-k8s-ingress-websocket
+ENV LOCAL_PATH /opt/${APP_NAME}
+
+RUN mkdir -p ${LOCAL_PATH}
+
+ADD target/${APP_NAME}.jar ${LOCAL_PATH}
+
+WORKDIR ${LOCAL_PATH}
+EXPOSE 9195
+
+CMD java -jar ${APP_NAME}.jar
diff --git a/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/deploy/deploy-shenyu.yaml b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/deploy/deploy-shenyu.yaml
new file mode 100644
index 0000000000..91af69e6c3
--- /dev/null
+++ b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/deploy/deploy-shenyu.yaml
@@ -0,0 +1,107 @@
+# 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: v1
+kind: Namespace
+metadata:
+  name: shenyu-ingress
+---
+apiVersion: v1
+automountServiceAccountToken: true
+kind: ServiceAccount
+metadata:
+  name: shenyu-ingress-controller
+  namespace: shenyu-ingress
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: shenyu-ingress-controller
+  namespace: shenyu-ingress
+  labels:
+    app: shenyu-ingress-controller
+    all: shenyu-ingress-controller
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: shenyu-ingress-controller
+  template:
+    metadata:
+      labels:
+        app: shenyu-ingress-controller
+    spec:
+      containers:
+      - name: shenyu-ingress-controller
+        image: apache/shenyu-integrated-test-k8s-ingress-websocket:latest
+        ports:
+        - containerPort: 9195
+        imagePullPolicy: IfNotPresent
+      serviceAccountName: shenyu-ingress-controller
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: shenyu-ingress-controller
+  namespace: shenyu-ingress
+spec:
+  selector:
+    app: shenyu-ingress-controller
+  type: NodePort
+  ports:
+    - port: 9195
+      targetPort: 9195
+      nodePort: 30095
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: shenyu-ingress-controller
+rules:
+- apiGroups:
+  - ""
+  resources:
+  - namespaces
+  - services
+  - endpoints
+  - secrets
+  - pods
+  verbs:
+  - get
+  - list
+  - watch
+- apiGroups:
+  - networking.k8s.io
+  resources:
+  - ingresses
+  verbs:
+  - get
+  - list
+  - watch
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: shenyu-ingress-controller
+  namespace: shenyu-ingress
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: shenyu-ingress-controller
+subjects:
+- kind: ServiceAccount
+  name: shenyu-ingress-controller
+  namespace: shenyu-ingress
diff --git a/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/deploy/kind-config.yaml b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/deploy/kind-config.yaml
new file mode 100644
index 0000000000..18b7da990e
--- /dev/null
+++ b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/deploy/kind-config.yaml
@@ -0,0 +1,36 @@
+# 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.
+
+kind: Cluster
+apiVersion: kind.x-k8s.io/v1alpha4
+nodes:
+  - role: control-plane
+    kubeadmConfigPatches:
+      - |
+        kind: InitConfiguration
+        nodeRegistration:
+          kubeletExtraArgs:
+            node-labels: "ingress-ready=true"
+    extraPortMappings:
+      - containerPort: 80
+        hostPort: 80
+        protocol: TCP
+      - containerPort: 443
+        hostPort: 443
+        protocol: TCP
+      - containerPort: 30095
+        hostPort: 30095
+        protocol: TCP
\ No newline at end of file
diff --git a/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/pom.xml b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/pom.xml
new file mode 100644
index 0000000000..386c9a6eab
--- /dev/null
+++ b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/pom.xml
@@ -0,0 +1,150 @@
+<?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">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>shenyu-integrated-test</artifactId>
+        <groupId>org.apache.shenyu</groupId>
+        <version>2.6.1-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>shenyu-integrated-test-k8s-ingress-websocket</artifactId>
+    <name>shenyu-integrated-test-k8s-ingress-websocket</name>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <websocket.version>1.5.1</websocket.version>
+    </properties>
+
+    <dependencies>
+        <!--shenyu websocket plugin start-->
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-spring-boot-starter-plugin-websocket</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!--shenyu websocket plugin end-->
+
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-integrated-test-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-spring-boot-starter-plugin-httpclient</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-spring-boot-starter-plugin-global</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-spring-boot-starter-plugin-uri</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-spring-boot-starter-plugin-general-context</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- shenyu kubernetes controller begin -->
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-spring-boot-starter-k8s</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- shenyu kubernetes controller end -->
+    </dependencies>
+
+    <profiles>
+        <profile>
+            <id>it</id>
+            <properties>
+                <docker.buildArg.APP_NAME>shenyu-integrated-test-k8s-ingress-websocket</docker.buildArg.APP_NAME>
+                <docker.image.tag.repo>apache/shenyu-integrated-test-k8s-ingress-websocket</docker.image.tag.repo>
+                <docker.image.tag.tagName>latest</docker.image.tag.tagName>
+            </properties>
+            <build>
+                <finalName>shenyu-integrated-test-k8s-ingress-websocket</finalName>
+                <plugins>
+                    <plugin>
+                        <groupId>org.springframework.boot</groupId>
+                        <artifactId>spring-boot-maven-plugin</artifactId>
+                        <version>${spring-boot.version}</version>
+                        <executions>
+                            <execution>
+                                <phase>package</phase>
+                                <goals>
+                                    <goal>repackage</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                        <configuration>
+                            <mainClass>
+                                org.apache.shenyu.integrated.test.k8s.ingress.websocket.WebsocketIngressIntegratedBootstrap
+                            </mainClass>
+                            <executable>true</executable>
+                        </configuration>
+                    </plugin>
+                    <plugin>
+                        <groupId>io.fabric8</groupId>
+                        <artifactId>docker-maven-plugin</artifactId>
+                        <version>${docker-maven-plugin.version}</version>
+                        <configuration>
+                            <images>
+                                <image>
+                                    <name>apache/shenyu-integrated-test-k8s-ingress-websocket</name>
+                                    <build>
+                                        <contextDir>${project.basedir}</contextDir>
+                                    </build>
+                                </image>
+                            </images>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>start</id>
+                                <goals>
+                                    <goal>build</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <skipTests>false</skipTests>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+</project>
\ No newline at end of file
diff --git a/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/script/healthcheck.sh b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/script/healthcheck.sh
new file mode 100644
index 0000000000..896e784144
--- /dev/null
+++ b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/script/healthcheck.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+#
+# 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.
+#
+
+PRGDIR=`dirname "$0"`
+for service in `grep -v -E "^$|^#" ${PRGDIR}/services.list`
+do
+    for loop in `seq 1 30`
+    do
+        status=`curl -o /dev/null -s -w %{http_code} $service`
+        echo -e "curl $service response $status"
+
+        if [ $status -eq 200  ]; then
+            break
+        fi
+
+        sleep 2
+    done
+done
+
+sleep 20
+echo -e "\n-------------------"
diff --git a/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/script/services.list b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/script/services.list
new file mode 100644
index 0000000000..6537f8c026
--- /dev/null
+++ b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/script/services.list
@@ -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.
+
+http://localhost:31190/new/feature/get/mapping/path
diff --git a/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/src/main/java/org/apache/shenyu/integrated/test/k8s/ingress/websocket/WebsocketIngressIntegratedBootstrap.java b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/src/main/java/org/apache/shenyu/integrated/test/k8s/ingress/websocket/WebsocketIngressIntegratedBootstrap.java
new file mode 100644
index 0000000000..b72ced6c53
--- /dev/null
+++ b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/src/main/java/org/apache/shenyu/integrated/test/k8s/ingress/websocket/WebsocketIngressIntegratedBootstrap.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.integrated.test.k8s.ingress.websocket;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class WebsocketIngressIntegratedBootstrap {
+
+    /**
+     * main mathod of app.
+     *
+     * @param args args
+     */
+    public static void main(final String[] args) {
+        SpringApplication.run(WebsocketIngressIntegratedBootstrap.class);
+    }
+}
diff --git a/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/src/main/resources/application.yml b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/src/main/resources/application.yml
new file mode 100644
index 0000000000..854a16e169
--- /dev/null
+++ b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/src/main/resources/application.yml
@@ -0,0 +1,329 @@
+# 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.
+
+server:
+  port: 9195
+  address: 0.0.0.0
+
+spring:
+  main:
+    allow-bean-definition-overriding: true
+  application:
+    name: shenyu-bootstrap
+  codec:
+    max-in-memory-size: 2MB
+  cloud:
+    discovery:
+      enabled: false
+    nacos:
+      discovery:
+        server-addr: 127.0.0.1:8848 # Spring Cloud Alibaba Dubbo use this.
+        enabled: false
+        namespace: ShenyuRegisterCenter
+
+# if you want use ribbon please config every server.
+#springCloud-test:
+#  ribbon:
+#    NIWSServerListClassName: com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
+
+eureka:
+  client:
+    enabled: false
+    serviceUrl:
+      defaultZone: http://localhost:8761/eureka/
+  instance:
+    prefer-ip-address: true
+
+#  security:
+#    oauth2:
+#      client:
+#        registration:
+#          <your client-registration-id>:
+#            client-id: <your client-id>
+#            client-secret: <your client-secret>
+#        provider:
+#          <your client-registration-id>:
+#            authorization-uri: <your authorization-uri>
+#            token-uri: <your access-token-uri>
+#            user-info-uri: <your user-info-uri>
+#            jwk-set-uri: <your jwk-set-uri>
+
+management:
+  health:
+    redis:
+      enabled: false
+    elasticsearch:
+      enabled: false
+  endpoint:
+    health:
+      enabled: true
+      show-details: always
+  endpoints:
+    web:
+      exposure:
+        include: "*" # or health,info
+        
+
+shenyu:
+  selectorMatchCache:
+    ## selector L1 cache
+    cache:
+      enabled: false
+      initialCapacity: 10000 # initial capacity in cache
+      maximumSize: 10000 # max size in cache
+    ## selector L2 cache, use trie as L2 cache
+    trie:
+      enabled: false
+      cacheSize: 128 # the number of plug-ins
+      matchMode: antPathMatch
+  ruleMatchCache:
+    ## rule L1 cache
+    cache:
+      enabled: true
+      initialCapacity: 10000 # initial capacity in cache
+      maximumSize: 65536 # max size in cache
+    ## rule L2 cache, use trie as L2 cache
+    trie:
+      enabled: false
+      cacheSize: 1024 # the number of selectors
+      matchMode: antPathMatch
+  netty:
+    http:
+      # set to false, user can custom the netty tcp server config.
+      webServerFactoryEnabled: true
+      selectCount: 1
+      workerCount: 8
+      accessLog: false
+      serverSocketChannel:
+        soRcvBuf: 87380
+        soBackLog: 128
+        soReuseAddr: false
+        connectTimeoutMillis: 10000
+        writeBufferHighWaterMark: 65536
+        writeBufferLowWaterMark: 32768
+        writeSpinCount: 16
+        autoRead: false
+        allocType: "pooled"
+        messageSizeEstimator: 8
+        singleEventExecutorPerGroup: true
+      socketChannel:
+        soKeepAlive: false
+        soReuseAddr: false
+        soLinger: -1
+        tcpNoDelay: true
+        soRcvBuf: 87380
+        soSndBuf: 16384
+        ipTos: 0
+        allowHalfClosure: false
+        connectTimeoutMillis: 10000
+        writeBufferHighWaterMark: 65536
+        writeBufferLowWaterMark: 32768
+        writeSpinCount: 16
+        autoRead: false
+        allocType: "pooled"
+        messageSizeEstimator: 8
+        singleEventExecutorPerGroup: true
+      sni:
+        enabled: false
+        mod: k8s #manul
+        defaultK8sSecretNamespace: shenyu-ingress
+        defaultK8sSecretName: default-cert
+#        mod: manual
+#        certificates:
+#          - domain: 'localhost'
+#            keyCertChainFile: '/Users/zhukunshuai/Desktop/cert/example.com+1.pem'
+#            keyFile: '/Users/zhukunshuai/Desktop/cert/example.com+1-key.pem'
+#          - domain: 'example.com'
+#            keyCertChainFile: '/Users/zhukunshuai/Desktop/cert/example.com+1.pem'
+#            keyFile: '/Users/zhukunshuai/Desktop/cert/example.com+1-key.pem'
+  httpclient:
+    strategy: netty
+#    connectTimeout: 45000
+#    responseTimeout: 3000
+#    readerIdleTime: 3000
+#    writerIdleTime: 3000
+#    allIdleTime: 3000
+#    readTimeout: 3000
+#    writeTimeout: 3000
+#    wiretap: false
+#    keepAlive: false
+#    maxInMemorySize: 1 #1mb
+#    pool:
+#      type: ELASTIC
+#      name: proxy
+#      maxConnections: 16
+#      acquireTimeout: 45000
+#      maxIdleTime: 3000
+#    proxy:
+#      host:
+#      port:
+#      username:
+#      password:
+#      nonProxyHostsPattern:
+#    ssl:
+#      useInsecureTrustManager: true
+#      keyStoreType: PKCS12
+#      keyStorePath: classpath:keystore.p12
+#      keyStorePassword: 123456
+#      keyStoreProvider:
+#      keyPassword: 123456
+#      trustedX509Certificates:
+#      handshakeTimeout:
+#      closeNotifyFlushTimeout:
+#      closeNotifyReadTimeout:
+#      defaultConfigurationType:
+#    threadPool:
+#      prefix: shenyu
+#      selectCount: 1
+#      workerCount: 8
+#      daemon: true
+  register:
+    enabled: false
+    registerType: zookeeper #etcd #consul
+    serverLists: localhost:2181 #http://localhost:2379 #localhost:8848
+    props:
+  cross:
+    enabled: true
+    allowedHeaders:
+    allowedMethods: "*"
+    allowedAnyOrigin: true # the same of Access-Control-Allow-Origin: "*"
+#    allowedOrigin:
+      # format : schema://prefix spacer domain
+      # Access-Control-Allow-Origin: "http://a.apache.org,http://b.apache.org"
+#      spacer: "."
+#      domain: apache.org
+#      prefixes:
+#        - a # a.apache.org
+#        - b # b.apache.org
+#      origins:
+#        - c.apache.org
+#        - d.apache.org
+#        - http://e.apache.org
+#      originRegex: ^http(|s)://(.*\.|)abc.com$
+    allowedExpose: ""
+    maxAge: "18000"
+    allowCredentials: true
+
+  switchConfig:
+    local: true
+    collapseSlashes: false
+  file:
+    enabled: true
+    maxSize : 10
+#  sync:
+#    websocket:
+#      urls: ws://localhost:9095/websocket
+#      allowOrigin: ws://localhost:9195
+#    apollo:
+#      appId: shenyu
+#      meta: http://localhost:8080
+#      env: dev
+#      clusterName: test
+#      namespace: application
+#    zookeeper:
+#      url: localhost:2181
+#      sessionTimeout: 5000
+#      connectionTimeout: 2000
+#    http:
+#      url: http://localhost:9095
+#      username:
+#      password:
+#    nacos:
+#      url: localhost:8848
+#      namespace: 1c10d748-af86-43b9-8265-75f487d20c6c
+#      username:
+#      password:
+#      acm:
+#        enabled: false
+#        endpoint: acm.aliyun.com
+#        namespace:
+#        accessKey:
+#        secretKey:
+#    etcd:
+#      url: http://localhost:2379
+#    consul:
+#      url: http://localhost:8500
+#      waitTime: 1000
+#      watchDelay: 1000
+  exclude:
+    enabled: false
+    paths:
+      - /favicon.ico
+  fallback:
+    enabled: false
+    paths:
+      - /fallback/hystrix
+      - /fallback/resilience4j
+      - /fallback/sentinel
+  health:
+    enabled: true
+    paths:
+      - /actuator
+      - /health_check
+  extPlugin:
+    path:
+    enabled: true
+    threads: 1
+    scheduleTime: 300
+    scheduleDelay: 30
+  scheduler:
+    enabled: false
+    type: fixed
+    threads: 16
+  upstreamCheck:
+    enabled: false
+    poolSize: 10
+    timeout: 3000
+    healthyThreshold: 1
+    unhealthyThreshold: 1
+    interval: 5000
+    printEnabled: true
+    printInterval: 60000
+  springCloudCache:
+    enabled: false
+  ribbon:
+    serverListRefreshInterval: 10000
+  metrics:
+    enabled: false
+    name : prometheus
+    host: 127.0.0.1
+    port: 8090
+    jmxConfig:
+    props:
+      jvm_enabled: true
+#  plugins:
+#    rate-limiter.enabled: false
+  local:
+    enabled: false
+    sha512Key: "BA3253876AED6BC22D4A6FF53D8406C6AD864195ED144AB5C87621B6C233B548BAEAE6956DF346EC8C17F5EA10F35EE3CBC514797ED7DDD3145464E2A0BAB413"
+#  sharedPool:
+#    enable: true
+#    prefix: "shenyu-shared"
+#    corePoolSize: 200
+#    maximumPoolSize: 2000
+#    keepAliveTime: 60000
+#    # 1GB
+#    maxWorkQueueMemory: 1073741824
+#    # 256MB
+#    maxFreeMemory: 268435456
+
+logging:
+  level:
+    root: info
+    org.springframework.boot: info
+    org.apache.ibatis: info
+    org.apache.shenyu.bonuspoint: info
+    org.apache.shenyu.lottery: info
+    org.apache.shenyu: info
diff --git a/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/src/test/java/org/apache/shenyu/integrated/test/k8s/ingress/websocket/WebsocketPluginTest.java b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/src/test/java/org/apache/shenyu/integrated/test/k8s/ingress/websocket/WebsocketPluginTest.java
new file mode 100644
index 0000000000..a0acb4852b
--- /dev/null
+++ b/shenyu-integrated-test/shenyu-integrated-test-k8s-ingress-websocket/src/test/java/org/apache/shenyu/integrated/test/k8s/ingress/websocket/WebsocketPluginTest.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.integrated.test.k8s.ingress.websocket;
+
+import org.apache.shenyu.integratedtest.common.AbstractPluginDataInit;
+import org.java_websocket.client.WebSocketClient;
+import org.java_websocket.handshake.ServerHandshake;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+public class WebsocketPluginTest extends AbstractPluginDataInit {
+
+    private static final Logger LOG = LoggerFactory.getLogger(WebsocketPluginTest.class);
+
+    private static final String WEBSOCKET_URI = "ws://localhost:30095/myWs";
+
+    @Test
+    public void testWebsocket() throws URISyntaxException, InterruptedException {
+        final String sendMessage = "Shenyu says hello to you!";
+        ArrayBlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(1);
+        WebSocketClient webSocketClient = new WebSocketClient(new URI(WEBSOCKET_URI)) {
+            @Override
+            public void onOpen(final ServerHandshake serverHandshake) {
+            }
+
+            @Override
+            public void onMessage(final String s) {
+                LOG.info("websocket client received message : {}", s);
+                blockingQueue.add(s);
+            }
+
+            @Override
+            public void onClose(final int i, final String s, final boolean b) {
+            }
+
+            @Override
+            public void onError(final Exception e) {
+            }
+        };
+        webSocketClient.connectBlocking();
+        webSocketClient.send(sendMessage);
+        String receivedMessage = blockingQueue.poll(10, TimeUnit.SECONDS);
+        assertThat(receivedMessage, is("server send messageļ¼š" + sendMessage));
+    }
+
+}