You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by al...@apache.org on 2024/07/30 13:00:17 UTC
(dubbo) branch 3.3 updated: Support stream in servlet mode (#14469)
This is an automated email from the ASF dual-hosted git repository.
albumenj pushed a commit to branch 3.3
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.3 by this push:
new 3a72599c9c Support stream in servlet mode (#14469)
3a72599c9c is described below
commit 3a72599c9c08ead011f69c55eac84fe23ad034e5
Author: Sean Yang <ox...@gmail.com>
AuthorDate: Tue Jul 30 21:00:11 2024 +0800
Support stream in servlet mode (#14469)
* Support stream in servlet mode
* Compatible with netty version 4.1.101.Final
---
.../apache/dubbo/config/nested/Http3Config.java | 12 +-
.../apache/dubbo/config/nested/ServletConfig.java | 27 +---
.../dubbo-demo-spring-boot-provider/pom.xml | 5 -
.../src/main/resources/application.yml | 14 +--
.../pom.xml | 77 ++++--------
.../dubbo/springboot/demo/servlet/ApiConsumer.java | 107 ++++++++++++++++
.../springboot/demo/servlet/GreeterService.java | 44 +++++++
.../demo/servlet/GreeterServiceImpl.java | 82 ++++++++++++
.../dubbo/springboot/demo/servlet/HelloReply.java | 34 +++++
.../springboot/demo/servlet/HelloRequest.java | 34 +++++
.../demo/servlet/ProviderApplication.java | 32 +++++
.../src/main/resources/application.yml | 19 +--
.../src/main/resources/log4j2.xml | 29 +++++
dubbo-demo/dubbo-demo-spring-boot/pom.xml | 1 +
dubbo-plugin/dubbo-triple-servlet/pom.xml | 31 +++++
.../protocol/tri/rest/support/servlet/Helper.java | 12 ++
.../servlet/ServletHttpMessageAdapterFactory.java | 4 +-
.../protocol/tri/servlet/ServletStreamChannel.java | 106 ++++++++++++----
.../rpc/protocol/tri/servlet/TripleFilter.java | 139 +++++++++++++++------
.../http12/AbstractServerHttpChannelObserver.java | 10 +-
.../rpc/protocol/tri/TripleHttp2Protocol.java | 21 ++--
.../dubbo-spring-boot-3-autoconfigure/pom.xml | 59 +--------
.../DubboTriple3AutoConfiguration.java | 8 +-
.../dubbo-spring-boot-autoconfigure/pom.xml | 16 +--
.../DubboTripleAutoConfiguration.java | 4 -
.../dubbo-spring-boot-starter/pom.xml | 5 -
dubbo-spring-boot/pom.xml | 18 ++-
27 files changed, 671 insertions(+), 279 deletions(-)
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/nested/Http3Config.java b/dubbo-common/src/main/java/org/apache/dubbo/config/nested/Http3Config.java
index 757516196f..1d6a87767f 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/nested/Http3Config.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/nested/Http3Config.java
@@ -23,10 +23,10 @@ public class Http3Config implements Serializable {
private static final long serialVersionUID = -4443828713331129834L;
/**
- * Enable http3 support
+ * Whether to enable HTTP/3 support
* <p>The default value is false.
*/
- private Boolean enable;
+ private Boolean enabled;
/**
* See <a href="https://docs.rs/quiche/0.6.0/quiche/struct.Config.html#method.set_initial_max_data">set_initial_max_data</a>.
@@ -115,12 +115,12 @@ public class Http3Config implements Serializable {
*/
private String ccAlgorithm;
- public Boolean getEnable() {
- return enable;
+ public Boolean getEnabled() {
+ return enabled;
}
- public void setEnable(Boolean enable) {
- this.enable = enable;
+ public void setEnabled(Boolean enabled) {
+ this.enabled = enabled;
}
public Integer getInitialMaxData() {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/nested/ServletConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/nested/ServletConfig.java
index 30b67ebf57..6bcbe50b60 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/nested/ServletConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/nested/ServletConfig.java
@@ -23,17 +23,10 @@ public class ServletConfig implements Serializable {
private static final long serialVersionUID = 1091478303358670173L;
/**
- * Enable servlet support, requests are transport through the servlet container,
- * which only supports unary calls due to protocol limitations
+ * Whether to enable servlet support, requests are transport through the servlet container
* <p>The default value is false.
*/
- private Boolean enable;
-
- /**
- * The timeout in milliseconds for the servlet async timeout.
- * <p>The default value is 180_000.
- */
- private Integer timeout;
+ private Boolean enabled;
/**
* The URL patterns that the servlet filter will be registered for.
@@ -47,20 +40,12 @@ public class ServletConfig implements Serializable {
*/
private Integer filterOrder;
- public Boolean getEnable() {
- return enable;
- }
-
- public void setEnable(Boolean enable) {
- this.enable = enable;
- }
-
- public Integer getTimeout() {
- return timeout;
+ public Boolean getEnabled() {
+ return enabled;
}
- public void setTimeout(Integer timeout) {
- this.timeout = timeout;
+ public void setEnabled(Boolean enabled) {
+ this.enabled = enabled;
}
public String[] getFilterUrlPatterns() {
diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/pom.xml b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/pom.xml
index 88b6160ba4..2c0d523449 100644
--- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/pom.xml
+++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/pom.xml
@@ -92,11 +92,6 @@
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
-
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/src/main/resources/application.yml b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/src/main/resources/application.yml
index e2642b6612..b1789be60f 100644
--- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/src/main/resources/application.yml
+++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/src/main/resources/application.yml
@@ -21,14 +21,9 @@ spring:
dubbo:
application:
name: ${spring.application.name}
- qos-enable: false
protocol:
- name: tri
+ name: dubbo
port: -1
- #port: ${server.port}
- triple:
- servlet:
- enable: true
registry:
id: zk-registry
address: zookeeper://127.0.0.1:2181
@@ -46,10 +41,3 @@ dubbo:
exporter:
enabled: true
enable-metadata: true
-
-server:
- port: 8081
- http2:
- enabled: true
- tomcat:
- keep-alive-timeout: 180000
diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/pom.xml b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/pom.xml
similarity index 67%
copy from dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/pom.xml
copy to dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/pom.xml
index 88b6160ba4..33c0414d0b 100644
--- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/pom.xml
+++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/pom.xml
@@ -24,96 +24,65 @@
<relativePath>../pom.xml</relativePath>
</parent>
- <artifactId>dubbo-demo-spring-boot-provider</artifactId>
-
- <properties>
- <skip_maven_deploy>true</skip_maven_deploy>
- </properties>
+ <artifactId>dubbo-demo-spring-boot-servlet</artifactId>
<dependencies>
- <dependency>
- <groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-demo-spring-boot-interface</artifactId>
- <version>${project.parent.version}</version>
- </dependency>
-
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<version>${project.version}</version>
</dependency>
-
- <dependency>
- <groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-configcenter-zookeeper</artifactId>
- <version>${project.version}</version>
- </dependency>
-
- <dependency>
- <groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-metadata-report-zookeeper</artifactId>
- <version>${project.version}</version>
- </dependency>
-
<dependency>
<groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-config-spring</artifactId>
+ <artifactId>dubbo-rpc-triple</artifactId>
<version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-java-util</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-java</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
-
<dependency>
<groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-remoting-netty4</artifactId>
+ <artifactId>dubbo-triple-servlet</artifactId>
<version>${project.version}</version>
</dependency>
-
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-serialization-hessian2</artifactId>
<version>${project.version}</version>
</dependency>
-
<dependency>
<groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-serialization-fastjson2</artifactId>
+ <artifactId>dubbo-config-spring</artifactId>
<version>${project.version}</version>
</dependency>
- <!-- Observability -->
<dependency>
<groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-tracing-otel-zipkin-spring-boot-starter</artifactId>
+ <artifactId>dubbo-spring-boot-autoconfigure</artifactId>
<version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
-
<dependency>
<groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-qos</artifactId>
+ <artifactId>dubbo-spring-boot-3-autoconfigure</artifactId>
<version>${project.version}</version>
</dependency>
-
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
-
- <dependency>
- <groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-spring-boot-starter</artifactId>
- <version>${project.version}</version>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- <exclusions>
- <exclusion>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
@@ -125,7 +94,6 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
- <version>${spring-boot-maven-plugin.version}</version>
<executions>
<execution>
<goals>
@@ -136,5 +104,4 @@
</plugin>
</plugins>
</build>
-
</project>
diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/ApiConsumer.java b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/ApiConsumer.java
new file mode 100644
index 0000000000..a16fdd0722
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/ApiConsumer.java
@@ -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.
+ */
+package org.apache.dubbo.springboot.demo.servlet;
+
+import org.apache.dubbo.common.constants.CommonConstants;
+import org.apache.dubbo.common.stream.StreamObserver;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.ProtocolConfig;
+import org.apache.dubbo.config.ReferenceConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.bootstrap.DubboBootstrap;
+
+import java.util.concurrent.CompletableFuture;
+
+public class ApiConsumer {
+
+ public static void main(String[] args) throws InterruptedException {
+ ReferenceConfig<GreeterService> referenceConfig = new ReferenceConfig<>();
+ referenceConfig.setInterface(GreeterService.class);
+ referenceConfig.setCheck(false);
+ referenceConfig.setProtocol(CommonConstants.TRIPLE);
+ referenceConfig.setLazy(true);
+ referenceConfig.setTimeout(100000);
+
+ DubboBootstrap bootstrap = DubboBootstrap.getInstance();
+ bootstrap
+ .application(new ApplicationConfig("dubbo-demo-triple-api-consumer"))
+ .registry(new RegistryConfig("zookeeper://127.0.0.1:2181"))
+ .protocol(new ProtocolConfig(CommonConstants.TRIPLE, -1))
+ .reference(referenceConfig)
+ .start();
+
+ GreeterService greeterService = referenceConfig.get();
+ System.out.println("dubbo referenceConfig started");
+ System.out.println("Call sayHello");
+ HelloReply reply = greeterService.sayHello(buildRequest("triple"));
+ System.out.println("sayHello reply: " + reply.getMessage());
+
+ System.out.println("Call sayHelloAsync");
+ CompletableFuture<String> sayHelloAsync = greeterService.sayHelloAsync("triple");
+ sayHelloAsync.thenAccept(value -> System.out.println("sayHelloAsync reply: " + value));
+
+ StreamObserver<HelloReply> responseObserver = new StreamObserver<HelloReply>() {
+ @Override
+ public void onNext(HelloReply reply) {
+ System.out.println("sayHelloServerStream onNext: " + reply.getMessage());
+ }
+
+ @Override
+ public void onError(Throwable t) {
+ System.out.println("sayHelloServerStream onError: " + t.getMessage());
+ }
+
+ @Override
+ public void onCompleted() {
+ System.out.println("sayHelloServerStream onCompleted");
+ }
+ };
+ System.out.println("Call sayHelloServerStream");
+ greeterService.sayHelloServerStream(buildRequest("triple"), responseObserver);
+
+ StreamObserver<HelloReply> biResponseObserver = new StreamObserver<HelloReply>() {
+ @Override
+ public void onNext(HelloReply reply) {
+ System.out.println("biRequestObserver onNext: " + reply.getMessage());
+ }
+
+ @Override
+ public void onError(Throwable t) {
+ System.out.println("biResponseObserver onError: " + t.getMessage());
+ }
+
+ @Override
+ public void onCompleted() {
+ System.out.println("biResponseObserver onCompleted");
+ }
+ };
+ System.out.println("Call biRequestObserver");
+ StreamObserver<HelloRequest> biRequestObserver = greeterService.sayHelloBiStream(biResponseObserver);
+ for (int i = 0; i < 5; i++) {
+ biRequestObserver.onNext(buildRequest("triple" + i));
+ }
+ biRequestObserver.onCompleted();
+
+ Thread.sleep(2000);
+ }
+
+ private static HelloRequest buildRequest(String name) {
+ HelloRequest request = new HelloRequest();
+ request.setName(name);
+ return request;
+ }
+}
diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/GreeterService.java b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/GreeterService.java
new file mode 100644
index 0000000000..e777429e71
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/GreeterService.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.springboot.demo.servlet;
+
+import org.apache.dubbo.common.stream.StreamObserver;
+
+import java.util.concurrent.CompletableFuture;
+
+public interface GreeterService {
+
+ /**
+ * Sends a greeting
+ */
+ HelloReply sayHello(HelloRequest request);
+
+ /**
+ * Sends a greeting asynchronously
+ */
+ CompletableFuture<String> sayHelloAsync(String request);
+
+ /**
+ * Sends a greeting with server streaming
+ */
+ void sayHelloServerStream(HelloRequest request, StreamObserver<HelloReply> responseObserver);
+
+ /**
+ * Sends greetings with bi streaming
+ */
+ StreamObserver<HelloRequest> sayHelloBiStream(StreamObserver<HelloReply> responseObserver);
+}
diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/GreeterServiceImpl.java b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/GreeterServiceImpl.java
new file mode 100644
index 0000000000..a9f3ac608f
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/GreeterServiceImpl.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.springboot.demo.servlet;
+
+import org.apache.dubbo.common.stream.StreamObserver;
+import org.apache.dubbo.config.annotation.DubboService;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@DubboService
+public class GreeterServiceImpl implements GreeterService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(GreeterServiceImpl.class);
+
+ @Override
+ public HelloReply sayHello(HelloRequest request) {
+ LOG.info("Received sayHello request: {}", request.getName());
+ return toReply("Hello " + request.getName());
+ }
+
+ @Override
+ public CompletableFuture<String> sayHelloAsync(String name) {
+ LOG.info("Received sayHelloAsync request: {}", name);
+ return CompletableFuture.supplyAsync(() -> "Hello " + name);
+ }
+
+ @Override
+ public void sayHelloServerStream(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
+ LOG.info("Received sayHelloServerStream request");
+ for (int i = 1; i < 6; i++) {
+ LOG.info("sayHelloServerStream onNext: {} {} times", request.getName(), i);
+ responseObserver.onNext(toReply("Hello " + request.getName() + ' ' + i + " times"));
+ }
+ LOG.info("sayHelloServerStream onCompleted");
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public StreamObserver<HelloRequest> sayHelloBiStream(StreamObserver<HelloReply> responseObserver) {
+ LOG.info("Received sayHelloBiStream request");
+ return new StreamObserver<HelloRequest>() {
+ @Override
+ public void onNext(HelloRequest request) {
+ LOG.info("sayHelloBiStream onNext: {}", request.getName());
+ responseObserver.onNext(toReply("Hello " + request.getName()));
+ }
+
+ @Override
+ public void onError(Throwable throwable) {
+ LOG.error("sayHelloBiStream onError", throwable);
+ }
+
+ @Override
+ public void onCompleted() {
+ LOG.info("sayHelloBiStream onCompleted");
+ }
+ };
+ }
+
+ private static HelloReply toReply(String message) {
+ HelloReply reply = new HelloReply();
+ reply.setMessage(message);
+ return reply;
+ }
+}
diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/HelloReply.java b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/HelloReply.java
new file mode 100644
index 0000000000..580d5336c5
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/HelloReply.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.springboot.demo.servlet;
+
+import java.io.Serializable;
+
+public class HelloReply implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private String message;
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+}
diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/HelloRequest.java b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/HelloRequest.java
new file mode 100644
index 0000000000..a17fb810dd
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/HelloRequest.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.springboot.demo.servlet;
+
+import java.io.Serializable;
+
+public class HelloRequest implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/ProviderApplication.java b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/ProviderApplication.java
new file mode 100644
index 0000000000..a3876c7e7d
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/ProviderApplication.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.springboot.demo.servlet;
+
+import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@EnableDubbo
+public class ProviderApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ProviderApplication.class, args);
+ System.out.println("dubbo service started");
+ }
+}
diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/src/main/resources/application.yml b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/resources/application.yml
similarity index 73%
copy from dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/src/main/resources/application.yml
copy to dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/resources/application.yml
index e2642b6612..e03758b7cc 100644
--- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/src/main/resources/application.yml
+++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/resources/application.yml
@@ -16,7 +16,7 @@
spring:
application:
- name: dubbo-springboot-demo-provider
+ name: dubbo-springboot-demo-servlet
dubbo:
application:
@@ -24,28 +24,13 @@ dubbo:
qos-enable: false
protocol:
name: tri
- port: -1
- #port: ${server.port}
+ port: ${server.port}
triple:
servlet:
enable: true
registry:
id: zk-registry
address: zookeeper://127.0.0.1:2181
- config-center:
- address: zookeeper://127.0.0.1:2181
- metadata-report:
- address: zookeeper://127.0.0.1:2181
- metrics:
- protocol: prometheus
- enable-jvm: true
- enable-registry: true
- aggregation:
- enabled: true
- prometheus:
- exporter:
- enabled: true
- enable-metadata: true
server:
port: 8081
diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/resources/log4j2.xml b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/resources/log4j2.xml
new file mode 100644
index 0000000000..69e1321d22
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/resources/log4j2.xml
@@ -0,0 +1,29 @@
+<?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.
+ -->
+<Configuration status="WARN">
+ <Appenders>
+ <Console name="Console" target="SYSTEM_OUT" follow="true">
+ <PatternLayout pattern="%style{%d{HH:mm:ss.SSS}}{Magenta} %style{|-}{White}%highlight{%-5p} [%t] %style{%40.40c}{Cyan}:%style{%-3L}{Blue} %style{-|}{White} %m%n%rEx{filters(jdk.internal.reflect,java.lang.reflect,sun.reflect)}" disableAnsi="false" charset="UTF-8"/>
+ </Console>
+ </Appenders>
+ <Loggers>
+ <Root level="info">
+ <AppenderRef ref="Console"/>
+ </Root>
+ </Loggers>
+</Configuration>
diff --git a/dubbo-demo/dubbo-demo-spring-boot/pom.xml b/dubbo-demo/dubbo-demo-spring-boot/pom.xml
index 5396c1e0fc..126f18552a 100644
--- a/dubbo-demo/dubbo-demo-spring-boot/pom.xml
+++ b/dubbo-demo/dubbo-demo-spring-boot/pom.xml
@@ -29,6 +29,7 @@
<module>dubbo-demo-spring-boot-consumer</module>
<module>dubbo-demo-spring-boot-provider</module>
<module>dubbo-demo-spring-boot-interface</module>
+ <module>dubbo-demo-spring-boot-servlet</module>
</modules>
<properties>
diff --git a/dubbo-plugin/dubbo-triple-servlet/pom.xml b/dubbo-plugin/dubbo-triple-servlet/pom.xml
index ab55ef6942..f15f9a1332 100644
--- a/dubbo-plugin/dubbo-triple-servlet/pom.xml
+++ b/dubbo-plugin/dubbo-triple-servlet/pom.xml
@@ -106,6 +106,7 @@
}]]></replacevalue>
</replace>
<replace file="${sources_directory}/rest/support/servlet/jakarta/ServletHttpMessageAdapterFactory.java" token="-100" value="-200" />
+ <replace file="${sources_directory}/rest/support/servlet/jakarta/FilterAdapter.java" token=""servlet" value=""jakarta-servlet" />
</target>
</configuration>
</execution>
@@ -132,5 +133,35 @@
</plugins>
</build>
</profile>
+ <profile>
+ <id>release</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>enforce-generate-jakarta</id>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <rules>
+ <requireFilesExist>
+ <files>
+ <file>${sources_directory}/servlet/jakarta/TripleFilter.java</file>
+ </files>
+ </requireFilesExist>
+ </rules>
+ <fail>true</fail>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
</profiles>
</project>
diff --git a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/servlet/Helper.java b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/servlet/Helper.java
index b7c6c218e0..a341fa686a 100644
--- a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/servlet/Helper.java
+++ b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/servlet/Helper.java
@@ -20,8 +20,11 @@ import org.apache.dubbo.common.io.StreamUtils;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.remoting.http12.HttpCookie;
import org.apache.dubbo.remoting.http12.HttpRequest.FileUpload;
+import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.protocol.tri.rest.RestException;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
import javax.servlet.http.Part;
import java.io.FileOutputStream;
@@ -142,4 +145,13 @@ final class Helper {
return Collections.emptyList();
}
}
+
+ public static ServletContext createDummyServletContext(FrameworkModel frameworkModel) {
+ return new DummyServletContext(frameworkModel);
+ }
+
+ public static FilterConfig createDummyFilterConfig(
+ String filterName, FrameworkModel frameworkModel, ServletContext servletContext) {
+ return new DummyFilterConfig(filterName, frameworkModel, servletContext);
+ }
}
diff --git a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/servlet/ServletHttpMessageAdapterFactory.java b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/servlet/ServletHttpMessageAdapterFactory.java
index 1862593203..b10579ad81 100644
--- a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/servlet/ServletHttpMessageAdapterFactory.java
+++ b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/servlet/ServletHttpMessageAdapterFactory.java
@@ -37,7 +37,7 @@ public final class ServletHttpMessageAdapterFactory
public ServletHttpMessageAdapterFactory(FrameworkModel frameworkModel) {
this.frameworkModel = frameworkModel;
- servletContext = new DummyServletContext(frameworkModel);
+ servletContext = Helper.createDummyServletContext(frameworkModel);
httpSessionFactory = getHttpSessionFactory(frameworkModel);
}
@@ -61,6 +61,6 @@ public final class ServletHttpMessageAdapterFactory
}
public FilterConfig adaptFilterConfig(String filterName) {
- return new DummyFilterConfig(filterName, frameworkModel, servletContext);
+ return Helper.createDummyFilterConfig(filterName, frameworkModel, servletContext);
}
}
diff --git a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java
index d5f0c7d39f..d6beb3a567 100644
--- a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java
+++ b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java
@@ -16,17 +16,21 @@
*/
package org.apache.dubbo.rpc.protocol.tri.servlet;
-import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
+import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.remoting.http12.HttpHeaderNames;
import org.apache.dubbo.remoting.http12.HttpHeaders;
import org.apache.dubbo.remoting.http12.HttpMetadata;
import org.apache.dubbo.remoting.http12.HttpOutputMessage;
import org.apache.dubbo.remoting.http12.HttpVersion;
+import org.apache.dubbo.remoting.http12.exception.HttpStatusException;
import org.apache.dubbo.remoting.http12.h2.H2StreamChannel;
import org.apache.dubbo.remoting.http12.h2.Http2Header;
import org.apache.dubbo.remoting.http12.h2.Http2OutputMessage;
import org.apache.dubbo.remoting.http12.h2.Http2OutputMessageFrame;
+import org.apache.dubbo.rpc.TriRpcStatus;
+import org.apache.dubbo.rpc.TriRpcStatus.Code;
+import org.apache.dubbo.rpc.protocol.tri.TripleHeaderEnum;
import javax.servlet.AsyncContext;
import javax.servlet.ServletOutputStream;
@@ -42,38 +46,81 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.CompletableFuture;
-import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_IO_EXCEPTION;
-
final class ServletStreamChannel implements H2StreamChannel {
- private static final ErrorTypeAwareLogger LOG = LoggerFactory.getErrorTypeAwareLogger(ServletStreamChannel.class);
+ private static final Logger LOG = LoggerFactory.getLogger(ServletStreamChannel.class);
private final HttpServletRequest request;
private final HttpServletResponse response;
private final AsyncContext context;
+ private boolean isGrpc;
+
ServletStreamChannel(HttpServletRequest request, HttpServletResponse response, AsyncContext context) {
this.request = request;
this.response = response;
this.context = context;
}
+ public void setGrpc(boolean isGrpc) {
+ this.isGrpc = isGrpc;
+ }
+
+ public void writeError(int code, Throwable throwable) {
+ if (response.isCommitted() && code == Code.DEADLINE_EXCEEDED.code) {
+ return;
+ }
+ try {
+ if (isGrpc) {
+ response.setTrailerFields(() -> {
+ Map<String, String> map = new HashMap<>();
+ map.put(TripleHeaderEnum.STATUS_KEY.getHeader(), String.valueOf(code));
+ return map;
+ });
+ return;
+ }
+ try {
+ if (throwable instanceof HttpStatusException) {
+ response.setStatus(((HttpStatusException) throwable).getStatusCode());
+ response.getOutputStream().close();
+ } else {
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+ } catch (Throwable t) {
+ LOG.info("Failed to send response", t);
+ }
+ } finally {
+ context.complete();
+ }
+ }
+
@Override
public CompletableFuture<Void> writeResetFrame(long errorCode) {
+ if (isGrpc) {
+ writeError(TriRpcStatus.httpStatusToGrpcCode((int) errorCode).code, null);
+ return completed();
+ }
+
try {
if (errorCode == 0L) {
response.getOutputStream().close();
- } else if (errorCode >= 300 && errorCode < 600) {
+ return completed();
+ }
+ if (response.isCommitted()) {
+ return completed();
+ }
+ if (errorCode >= 300 && errorCode < 600) {
response.sendError((int) errorCode);
} else {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
} catch (Throwable t) {
- LOG.error(COMMON_IO_EXCEPTION, "", "", "Failed to close response", t);
+ LOG.info("Failed to close response", t);
} finally {
context.complete();
}
- return CompletableFuture.completedFuture(null);
+
+ return completed();
}
@Override
@@ -94,31 +141,36 @@ final class ServletStreamChannel implements H2StreamChannel {
}
return map;
});
- } else {
- for (Entry<String, List<String>> entry : headers.entrySet()) {
- String key = entry.getKey();
- List<String> values = entry.getValue();
- if (HttpHeaderNames.STATUS.getName().equals(key)) {
- response.setStatus(Integer.parseInt(values.get(0)));
- continue;
- }
- if (values.size() == 1) {
- response.setHeader(key, values.get(0));
- } else {
- for (int i = 0, size = values.size(); i < size; i++) {
- response.addHeader(key, values.get(i));
- }
+ return completed();
+ }
+
+ if (response.isCommitted()) {
+ return completed();
+ }
+
+ for (Entry<String, List<String>> entry : headers.entrySet()) {
+ String key = entry.getKey();
+ List<String> values = entry.getValue();
+ if (HttpHeaderNames.STATUS.getName().equals(key)) {
+ response.setStatus(Integer.parseInt(values.get(0)));
+ continue;
+ }
+ if (values.size() == 1) {
+ response.setHeader(key, values.get(0));
+ } else {
+ for (int i = 0, size = values.size(); i < size; i++) {
+ response.addHeader(key, values.get(i));
}
}
}
} catch (Throwable t) {
- LOG.error(COMMON_IO_EXCEPTION, "", "", "Failed to write header", t);
+ LOG.info("Failed to write header", t);
} finally {
if (endStream) {
context.complete();
}
}
- return CompletableFuture.completedFuture(null);
+ return completed();
}
@Override
@@ -133,13 +185,13 @@ final class ServletStreamChannel implements H2StreamChannel {
bos.writeTo(out);
out.flush();
} catch (Throwable t) {
- LOG.error(COMMON_IO_EXCEPTION, "", "", "Failed to write message", t);
+ LOG.info("Failed to write message", t);
} finally {
if (endStream) {
context.complete();
}
}
- return CompletableFuture.completedFuture(null);
+ return completed();
}
@Override
@@ -154,4 +206,8 @@ final class ServletStreamChannel implements H2StreamChannel {
@Override
public void flush() {}
+
+ private static CompletableFuture<Void> completed() {
+ return CompletableFuture.completedFuture(null);
+ }
}
diff --git a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java
index b009588853..18af427d1f 100644
--- a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java
+++ b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java
@@ -18,15 +18,14 @@ package org.apache.dubbo.rpc.protocol.tri.servlet;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.io.StreamUtils;
-import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
+import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.remoting.http12.h2.H2StreamChannel;
import org.apache.dubbo.remoting.http12.h2.Http2InputMessageFrame;
import org.apache.dubbo.remoting.http12.h2.Http2ServerTransportListenerFactory;
import org.apache.dubbo.remoting.http12.h2.Http2TransportListener;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.PathResolver;
+import org.apache.dubbo.rpc.TriRpcStatus.Code;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.protocol.tri.ServletExchanger;
import org.apache.dubbo.rpc.protocol.tri.TripleConstant;
@@ -40,38 +39,37 @@ import org.apache.dubbo.rpc.protocol.tri.rest.mapping.DefaultRequestMappingRegis
import org.apache.dubbo.rpc.protocol.tri.rest.mapping.RequestMappingRegistry;
import javax.servlet.AsyncContext;
+import javax.servlet.AsyncEvent;
+import javax.servlet.AsyncListener;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
+import javax.servlet.ReadListener;
import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
+import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.util.Arrays;
import java.util.Set;
-import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_IO_EXCEPTION;
-import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR;
-
public class TripleFilter implements Filter {
- private static final ErrorTypeAwareLogger LOG = LoggerFactory.getErrorTypeAwareLogger(TripleFilter.class);
+ private static final Logger LOG = LoggerFactory.getLogger(TripleFilter.class);
private PathResolver pathResolver;
private RequestMappingRegistry mappingRegistry;
- private int defaultTimeout;
@Override
public void init(FilterConfig config) {
FrameworkModel frameworkModel = FrameworkModel.defaultModel();
pathResolver = frameworkModel.getDefaultExtension(PathResolver.class);
mappingRegistry = frameworkModel.getBeanFactory().getOrRegisterBean(DefaultRequestMappingRegistry.class);
- String timeoutString = config.getInitParameter("timeout");
- defaultTimeout = StringUtils.isEmpty(timeoutString) ? 180_000 : Integer.parseInt(timeoutString);
}
@Override
@@ -85,37 +83,24 @@ public class TripleFilter implements Filter {
return;
}
- AsyncContext context = request.startAsync();
+ AsyncContext context = request.startAsync(request, response);
+ ServletStreamChannel channel = new ServletStreamChannel(hRequest, hResponse, context);
try {
- H2StreamChannel streamChannel = new ServletStreamChannel(hRequest, hResponse, context);
Http2TransportListener listener = determineHttp2ServerTransportListenerFactory(request.getContentType())
- .newInstance(streamChannel, ServletExchanger.getUrl(), FrameworkModel.defaultModel());
+ .newInstance(channel, ServletExchanger.getUrl(), FrameworkModel.defaultModel());
- context.setTimeout(resolveTimeout(hRequest, listener instanceof GrpcHttp2ServerTransportListener));
+ boolean isGrpc = listener instanceof GrpcHttp2ServerTransportListener;
+ channel.setGrpc(isGrpc);
+ context.setTimeout(resolveTimeout(hRequest, isGrpc));
+ context.addListener(new TripleAsyncListener(channel));
+ ServletInputStream is = request.getInputStream();
+ is.setReadListener(new TripleReadListener(listener, channel, is));
+ response.getOutputStream().setWriteListener(new TripleWriteListener(channel));
listener.onMetadata(new HttpMetadataAdapter(hRequest));
-
- ByteArrayOutputStream os;
- try {
- os = new ByteArrayOutputStream(1024);
- StreamUtils.copy(request.getInputStream(), os);
- } catch (Throwable t) {
- LOG.error(COMMON_IO_EXCEPTION, "", "", "Failed to read input", t);
- try {
- hResponse.sendError(HttpServletResponse.SC_BAD_REQUEST);
- } finally {
- context.complete();
- }
- return;
- }
- listener.onData(new Http2InputMessageFrame(new ByteArrayInputStream(os.toByteArray()), true));
} catch (Throwable t) {
- LOG.error(INTERNAL_ERROR, "", "", "Failed to process request", t);
- try {
- hResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- } finally {
- context.complete();
- }
+ LOG.info("Failed to process request", t);
+ channel.writeError(Code.UNKNOWN.code, t);
}
}
@@ -160,7 +145,7 @@ public class TripleFilter implements Filter {
return GenericHttp2ServerTransportListenerFactory.INSTANCE;
}
- private int resolveTimeout(HttpServletRequest request, boolean isGrpc) {
+ private static int resolveTimeout(HttpServletRequest request, boolean isGrpc) {
try {
if (isGrpc) {
String timeoutString = request.getHeader(GrpcHeaderNames.GRPC_TIMEOUT.getName());
@@ -178,6 +163,84 @@ public class TripleFilter implements Filter {
}
} catch (Throwable ignored) {
}
- return defaultTimeout;
+ return 0;
+ }
+
+ private static final class TripleAsyncListener implements AsyncListener {
+
+ private final ServletStreamChannel streamChannel;
+
+ TripleAsyncListener(ServletStreamChannel streamChannel) {
+ this.streamChannel = streamChannel;
+ }
+
+ @Override
+ public void onComplete(AsyncEvent event) {}
+
+ @Override
+ public void onTimeout(AsyncEvent event) {
+ streamChannel.writeError(Code.DEADLINE_EXCEEDED.code, event.getThrowable());
+ }
+
+ @Override
+ public void onError(AsyncEvent event) {
+ streamChannel.writeError(Code.CANCELLED.code, event.getThrowable());
+ }
+
+ @Override
+ public void onStartAsync(AsyncEvent event) {}
+ }
+
+ private static final class TripleReadListener implements ReadListener {
+
+ private final Http2TransportListener listener;
+ private final ServletStreamChannel channel;
+ private final ServletInputStream input;
+ private final byte[] buffer = new byte[4 * 1024];
+
+ TripleReadListener(Http2TransportListener listener, ServletStreamChannel channel, ServletInputStream input) {
+ this.listener = listener;
+ this.channel = channel;
+ this.input = input;
+ }
+
+ @Override
+ public void onDataAvailable() throws IOException {
+ while (input.isReady()) {
+ int length = input.read(buffer);
+ if (length == -1) {
+ return;
+ }
+ byte[] copy = Arrays.copyOf(buffer, length);
+ listener.onData(new Http2InputMessageFrame(new ByteArrayInputStream(copy), false));
+ }
+ }
+
+ @Override
+ public void onAllDataRead() {
+ listener.onData(new Http2InputMessageFrame(StreamUtils.EMPTY, true));
+ }
+
+ @Override
+ public void onError(Throwable t) {
+ channel.writeError(Code.CANCELLED.code, t);
+ }
+ }
+
+ private static final class TripleWriteListener implements WriteListener {
+
+ private final ServletStreamChannel channel;
+
+ TripleWriteListener(ServletStreamChannel channel) {
+ this.channel = channel;
+ }
+
+ @Override
+ public void onWritePossible() {}
+
+ @Override
+ public void onError(Throwable t) {
+ channel.writeError(Code.CANCELLED.code, t);
+ }
}
}
diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java
index 3cb9f90e49..1ed6b3e450 100644
--- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java
@@ -188,9 +188,13 @@ public abstract class AbstractServerHttpChannelObserver implements CustomizableH
}
protected final String resolveStatusCode(Throwable throwable) {
- return throwable instanceof HttpStatusException
- ? String.valueOf(((HttpStatusException) throwable).getStatusCode())
- : HttpStatus.INTERNAL_SERVER_ERROR.getStatusString();
+ if (throwable == null) {
+ return HttpStatus.OK.getStatusString();
+ }
+ if (throwable instanceof HttpStatusException) {
+ return String.valueOf(((HttpStatusException) throwable).getStatusCode());
+ }
+ return HttpStatus.INTERNAL_SERVER_ERROR.getStatusString();
}
protected final ErrorResponse buildErrorResponse(String statusCode, Throwable throwable) {
diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java
index 011881ddc9..aeb3e7f3be 100644
--- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java
@@ -47,7 +47,6 @@ import java.util.List;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
-import io.netty.handler.codec.http.HttpDecoderConfig;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.HttpServerUpgradeHandler;
@@ -89,7 +88,7 @@ public class TripleHttp2Protocol extends AbstractWireProtocol implements ScopeMo
@Override
public void configClientPipeline(URL url, ChannelOperator operator, ContextOperator contextOperator) {
TripleConfig tripleConfig = ConfigManager.getProtocol(url).getTriple();
- final Http2FrameCodec codec = Http2FrameCodecBuilder.forClient()
+ Http2FrameCodec codec = Http2FrameCodecBuilder.forClient()
.gracefulShutdownTimeoutMillis(10000)
.initialSettings(new Http2Settings()
.headerTableSize(tripleConfig.getHeaderTableSize())
@@ -131,13 +130,15 @@ public class TripleHttp2Protocol extends AbstractWireProtocol implements ScopeMo
}
}
+ @SuppressWarnings("deprecation")
private void configurerHttp1Handlers(URL url, List<ChannelHandler> handlers) {
TripleConfig tripleConfig = ConfigManager.getProtocol(url).getTriple();
- final HttpServerCodec sourceCodec = new HttpServerCodec(new HttpDecoderConfig()
- .setMaxChunkSize(tripleConfig.getMaxChunkSize())
- .setMaxHeaderSize(tripleConfig.getMaxHeaderSize())
- .setMaxInitialLineLength(tripleConfig.getMaxInitialLineLength())
- .setInitialBufferSize(tripleConfig.getInitialBufferSize()));
+ HttpServerCodec sourceCodec = new HttpServerCodec(
+ tripleConfig.getMaxInitialLineLength(),
+ tripleConfig.getMaxHeaderSize(),
+ tripleConfig.getMaxChunkSize(),
+ false,
+ tripleConfig.getInitialBufferSize());
handlers.add(new ChannelHandlerPretender(sourceCodec));
// Triple protocol http1 upgrade support
handlers.add(new ChannelHandlerPretender(new HttpServerUpgradeHandler(
@@ -169,7 +170,7 @@ public class TripleHttp2Protocol extends AbstractWireProtocol implements ScopeMo
return new Http2MultiplexHandler(new ChannelInitializer<Http2StreamChannel>() {
@Override
protected void initChannel(Http2StreamChannel ch) {
- final ChannelPipeline p = ch.pipeline();
+ ChannelPipeline p = ch.pipeline();
p.addLast(new NettyHttp2FrameCodec());
p.addLast(new NettyHttp2ProtocolSelectorHandler(
url, frameworkModel, tripleConfig, GenericHttp2ServerTransportListenerFactory.INSTANCE));
@@ -179,8 +180,8 @@ public class TripleHttp2Protocol extends AbstractWireProtocol implements ScopeMo
private void configurerHttp2Handlers(URL url, List<ChannelHandler> handlers) {
TripleConfig tripleConfig = ConfigManager.getProtocol(url).getTriple();
- final Http2FrameCodec codec = buildHttp2FrameCodec(tripleConfig);
- final Http2MultiplexHandler handler = buildHttp2MultiplexHandler(url, tripleConfig);
+ Http2FrameCodec codec = buildHttp2FrameCodec(tripleConfig);
+ Http2MultiplexHandler handler = buildHttp2MultiplexHandler(url, tripleConfig);
handlers.add(new ChannelHandlerPretender(new HttpWriteQueueHandler()));
handlers.add(new ChannelHandlerPretender(codec));
handlers.add(new ChannelHandlerPretender(new FlushConsolidationHandler(64, true)));
diff --git a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/pom.xml
index 0e8435743a..e65cf6bf5f 100644
--- a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/pom.xml
+++ b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/pom.xml
@@ -60,70 +60,17 @@
<optional>true</optional>
</dependency>
- <dependency>
- <groupId>jakarta.servlet</groupId>
- <artifactId>jakarta.servlet-api</artifactId>
- <optional>true</optional>
- </dependency>
-
<dependency>
<groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-rpc-triple</artifactId>
+ <artifactId>dubbo-triple-servlet</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
- <groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-triple-servlet</artifactId>
- <version>${project.version}</version>
+ <groupId>jakarta.servlet</groupId>
+ <artifactId>jakarta.servlet-api</artifactId>
<optional>true</optional>
</dependency>
-
</dependencies>
-
- <build>
- <resources>
- <resource>
- <directory>src/main/resources</directory>
- <excludes>
- <exclude>**</exclude>
- </excludes>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <skipMain>true</skipMain>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
- <profiles>
- <profile>
- <id>jdk-version-ge-17</id>
- <activation>
- <jdk>[17,)</jdk>
- </activation>
- <build>
- <resources>
- <resource>
- <directory>src/main/resources</directory>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <skipMain>false</skipMain>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </profile>
- </profiles>
</project>
diff --git a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java
index 08df8da168..81ef0b0582 100644
--- a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java
+++ b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java
@@ -19,8 +19,6 @@ package org.apache.dubbo.spring.boot.autoconfigure;
import org.apache.dubbo.rpc.protocol.tri.ServletExchanger;
import org.apache.dubbo.rpc.protocol.tri.servlet.jakarta.TripleFilter;
-import java.util.Collections;
-
import jakarta.servlet.Filter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -46,13 +44,11 @@ public class DubboTriple3AutoConfiguration {
@Bean
public FilterRegistrationBean<TripleFilter> tripleProtocolFilter(
- @Value("${" + PREFIX + ".timeout:}") String timeout,
- @Value("${" + PREFIX + ".servlet-filter-url-patterns:/*}") String[] urlPatterns,
- @Value("${" + PREFIX + ".servlet-filter-order:-1000000}") int order,
+ @Value("${" + PREFIX + ".filter-url-patterns:/*}") String[] urlPatterns,
+ @Value("${" + PREFIX + ".filter-order:-1000000}") int order,
@Value("${server.port:8080}") int serverPort) {
ServletExchanger.bindServerPort(serverPort);
FilterRegistrationBean<TripleFilter> registrationBean = new FilterRegistrationBean<>();
- registrationBean.setInitParameters(Collections.singletonMap("timeout", timeout));
registrationBean.setFilter(new TripleFilter());
registrationBean.addUrlPatterns(urlPatterns);
registrationBean.setOrder(order);
diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml
index cca1fdfafc..4d85060d46 100644
--- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml
+++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml
@@ -71,24 +71,17 @@
<optional>true</optional>
</dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <scope>provided</scope>
- </dependency>
-
<dependency>
<groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-rpc-triple</artifactId>
+ <artifactId>dubbo-triple-servlet</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
- <groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-triple-servlet</artifactId>
- <version>${project.version}</version>
- <optional>true</optional>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <scope>provided</scope>
</dependency>
<!-- Test Dependencies -->
@@ -97,6 +90,5 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
-
</dependencies>
</project>
diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java
index 9f6139a7ba..c750552f68 100644
--- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java
+++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java
@@ -21,8 +21,6 @@ import org.apache.dubbo.rpc.protocol.tri.servlet.TripleFilter;
import javax.servlet.Filter;
-import java.util.Collections;
-
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -47,13 +45,11 @@ public class DubboTripleAutoConfiguration {
@Bean
public FilterRegistrationBean<TripleFilter> tripleProtocolFilter(
- @Value("${" + PREFIX + ".timeout:}") String timeout,
@Value("${" + PREFIX + ".filter-url-patterns:/*}") String[] urlPatterns,
@Value("${" + PREFIX + ".filter-order:-1000000}") int order,
@Value("${server.port:8080}") int serverPort) {
ServletExchanger.bindServerPort(serverPort);
FilterRegistrationBean<TripleFilter> registrationBean = new FilterRegistrationBean<>();
- registrationBean.setInitParameters(Collections.singletonMap("timeout", timeout));
registrationBean.setFilter(new TripleFilter());
registrationBean.addUrlPatterns(urlPatterns);
registrationBean.setOrder(order);
diff --git a/dubbo-spring-boot/dubbo-spring-boot-starter/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-starter/pom.xml
index a52cd9e2c0..b5f8958714 100644
--- a/dubbo-spring-boot/dubbo-spring-boot-starter/pom.xml
+++ b/dubbo-spring-boot/dubbo-spring-boot-starter/pom.xml
@@ -41,10 +41,5 @@
<artifactId>dubbo-spring-boot-autoconfigure</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-spring-boot-3-autoconfigure</artifactId>
- <version>${project.version}</version>
- </dependency>
</dependencies>
</project>
diff --git a/dubbo-spring-boot/pom.xml b/dubbo-spring-boot/pom.xml
index 96fb40c057..551725b991 100644
--- a/dubbo-spring-boot/pom.xml
+++ b/dubbo-spring-boot/pom.xml
@@ -32,7 +32,6 @@
<modules>
<module>dubbo-spring-boot-actuator</module>
<module>dubbo-spring-boot-autoconfigure</module>
- <module>dubbo-spring-boot-3-autoconfigure</module>
<module>dubbo-spring-boot-compatible</module>
<module>dubbo-spring-boot-starter</module>
<module>dubbo-spring-boot-starters</module>
@@ -190,5 +189,22 @@
<spring-boot.version>2.2.8.RELEASE</spring-boot.version>
</properties>
</profile>
+
+ <profile>
+ <id>jdk-version-ge-17</id>
+ <activation>
+ <jdk>[17,)</jdk>
+ </activation>
+ <modules>
+ <module>dubbo-spring-boot-3-autoconfigure</module>
+ </modules>
+ </profile>
+
+ <profile>
+ <id>release</id>
+ <modules>
+ <module>dubbo-spring-boot-3-autoconfigure</module>
+ </modules>
+ </profile>
</profiles>
</project>