You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2021/03/09 06:57:13 UTC

[servicecomb-docs] 02/02: [SCB-2211]add documents to show reactive support of java chassis

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

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-docs.git

commit 3d95779f7f4e10548bb62e16db87a25d72f814ce
Author: libuao68 <bi...@qq.com>
AuthorDate: Tue Mar 9 14:51:25 2021 +0800

    [SCB-2211]add documents to show reactive support of java chassis
---
 .../build-consumer/develop-consumer-using-rpc.md   | 10 +++-
 .../zh_CN/docs/build-provider/catalog.md           |  1 +
 .../zh_CN/docs/build-provider/reactive.md          | 55 ++++++++++++++++++++++
 .../zh_CN/docs/build-provider/thread-pool.md       | 18 ++++++-
 4 files changed, 80 insertions(+), 4 deletions(-)

diff --git a/java-chassis-reference/zh_CN/docs/build-consumer/develop-consumer-using-rpc.md b/java-chassis-reference/zh_CN/docs/build-consumer/develop-consumer-using-rpc.md
index b308390..8f7b2bb 100644
--- a/java-chassis-reference/zh_CN/docs/build-consumer/develop-consumer-using-rpc.md
+++ b/java-chassis-reference/zh_CN/docs/build-consumer/develop-consumer-using-rpc.md
@@ -1,16 +1,18 @@
-# 使用透明RPC方式开发服务消费者
+# 使用RPC方式开发服务消费者
 
 ## 概念阐述
 
 透明RPC开发模式允许用户通过简单的java interface像本地调用一样进行服务调用。  
 透明RPC仅仅是一种开发模式:
+
 * 与使用highway还是RESTful传输没有关联
 * 与producer使用透明RPC/Jax-RS还是SpringMVC模式开发没有关联
 * 也与producer代码是否实现这个interface没有关联。  
   
-透明RPC开发模式与spring cloud的feign类似,不过更简单,因为不必在这个interface中增加任何RESTful annotation。
+透明RPC开发模式与spring boot的feign类似,不过更简单,因为不必在这个interface中增加任何RESTful annotation。
 
 ## 在spring bean中通过@RpcReference声明
+
 ```java
 @Component
 public class SomeBean {
@@ -22,13 +24,16 @@ public class SomeBean {
   ......
 }
 ```
+
 ## 脱离spring bean,直接通过api声明
 ```java
 Hello hello = Invoker.createProxy("helloService", "helloSchema", Hello.class);
 ```
 
 ## reactive
+
 只需要使用jdk的CompletableFuture对返回值进行包装即可
+
 ```java
 interface Hello {
   CompletableFuture<String> sayHi(String name);
@@ -37,6 +42,7 @@ interface Hello {
 
 同一个interface中,可以同时声明同一个方法的reactive和同步原型  
 因为要求方法名与契约中的operationId一一对应,而仅有返回值类型不同,在java中是非法的,所以需要修改方法名,并通过swagger annotation来声明真正的operationId
+
 ```java
 interface Hello {
   String sayHi(String name);
diff --git a/java-chassis-reference/zh_CN/docs/build-provider/catalog.md b/java-chassis-reference/zh_CN/docs/build-provider/catalog.md
index b8b7bdc..035f1c8 100644
--- a/java-chassis-reference/zh_CN/docs/build-provider/catalog.md
+++ b/java-chassis-reference/zh_CN/docs/build-provider/catalog.md
@@ -5,6 +5,7 @@
 * [用SpringMVC开发微服务](springmvc.md)
 * [用透明RPC开发微服务](transparent-rpc.md)
 * [只发布interface的方法为服务接口](use-interface.md)
+* [异步处理](reactive.md)
 * [使用 Context 参数](context-param.md)
 * [多个返回值和错误码](multi-code.md)
 * [使用Swagger注解](swagger-annotation.md)
diff --git a/java-chassis-reference/zh_CN/docs/build-provider/reactive.md b/java-chassis-reference/zh_CN/docs/build-provider/reactive.md
new file mode 100644
index 0000000..9db2e14
--- /dev/null
+++ b/java-chassis-reference/zh_CN/docs/build-provider/reactive.md
@@ -0,0 +1,55 @@
+# 异步处理
+
+异步处理可以更加充分的利用CPU,提升应用程序的性能。相对于同步处理,异步处理的开发过程更加复杂,出现的问题也更加难于定位。Java Chassis
+提供了非常灵活的异步处理机制,使得开发者能够选择性的使用同步处理和异步处理。
+
+## 定义异步处理的接口和使用异步访问
+
+在Provider端,Spring MVC、JAX RS和RPC的异步接口定义类似,都使用`CompletableFuture`来声明异步接口。以透明RPC为例,定义方法如下:
+
+```java
+  public CompletableFuture<String> sayHello(String name) {
+    CompletableFuture<String> future = new CompletableFuture<>();
+    future.complete(name);
+    return future;
+  }
+```
+
+在Consumer端,可以使用透明RPC、InvokerUtils、AsyncRestTemplate来使用异步。以透明RPC为例,首先声明接口:
+
+```java
+public interface Hello {
+  @ApiOperation(nickname = "sayHello", value = "")
+  CompletableFuture<String> sayHelloAsync(String name);
+
+  String sayHello(String name);
+}
+```
+
+上面的例子同时定义了异步访问的接口和同步访问的接口,它们可以用来访问Provider的同一个接口。 使用异步接口和使用同步接口的过程一样:
+
+```java
+  @RpcReference(microserviceName = "name", schemaId = "Hello")
+  public Hello hello;
+```
+
+## 异步逻辑执行的线程池
+
+声明为异步接口,并不会改变业务逻辑入口被执行的线程。比如在Provider端,业务逻辑的入口还是在同步线程池中执行的,Edge Service在event-loop执行。
+改变入口逻辑的执行线程,需要修改方法的默认线程池。异步接口执行完毕,回调逻辑在业务自定义的异步执行线程池执行。 
+
+详细情况参考[线程池](thread-pool.md)。 
+
+异步逻辑在更加复杂场景下的执行过程,请参考[reactive](../general-development/reactive.md)。
+
+## 有关 event-loop 线程的特殊说明
+
+在Edge Service等场景,或者在Provider使用了异步线程池的场景,所有的业务逻辑都是在event-loop执行的。在event-loop执行的业务代码,不能存在
+任何阻塞操作,否则会破坏event-loop的事件派发,导致死锁。 这些场景访问其他微服务,必须采用异步接口。 event-loop执行阻塞操作导致死锁的情况,
+或者导致性能下降的情况,需要在满足一定的并发条件才能够出现,不小心使用会给业务可靠性带来很大的风险。 Java Chassis针对常见的错误也提供了一些
+检测机制,比如在event-loop执行同步Consumer调用的时候,会报告异常,让开发者及时发现问题。 
+
+
+ 
+
+
diff --git a/java-chassis-reference/zh_CN/docs/build-provider/thread-pool.md b/java-chassis-reference/zh_CN/docs/build-provider/thread-pool.md
index 09a99d4..862b9fd 100644
--- a/java-chassis-reference/zh_CN/docs/build-provider/thread-pool.md
+++ b/java-chassis-reference/zh_CN/docs/build-provider/thread-pool.md
@@ -19,10 +19,15 @@ Java Chassis 提供了一个全局的内置线程池, 如果业务有特殊的
   * 指定schema专用的线程池: `servicecomb.executors.Provider.${schemaId}: custom-executor`
   * 指定operation专用的线程池: `servicecomb.executors.Provider.${schemaId}.${operationId}: custom-executor`
  
-## ServiceComb内置线程池
+## Java Chassis 内置线程池
+
+Java Chassis提供了两个内置的线程池,`servicecomb.executor.groupThreadPool` 和 `servicecomb.executor.reactive`。 前者
+是同步线程池,在Consumer和Provider默认启用;后者是异步线程池,在Edge Service默认启用。 
+
+### 同步线程池
 
 一般的线程池都是所有线程共享一个任务队列,在这种情况下,所有网络线程需要向同一个队列申请请求入队,线程池中的所有线程需要从同一个队列中抢任务执行,对于高吞吐的场景,这会导致竞争冲突,形成性能瓶颈  
-所以,为了提升性能,ServiceComb内置线程池实际是真正线程池的包装,允许在其内部配置多组线程池,且每个网络线程绑定一组线程池,以减小竞争冲突  
+所以,为了提升性能,Java Chassis内置线程池实际是真正线程池的包装,允许在其内部配置多组线程池,且每个网络线程绑定一组线程池,以减小竞争冲突  
 ![](../assets/producer-default-executor.png)
 
 * 1.2.0之前的版本
@@ -44,3 +49,12 @@ Java Chassis 提供了一个全局的内置线程池, 如果业务有特殊的
 | servicecomb.executor.default.maxIdleSecond-per-group| 60                | 每组线程池中超过coreThreads-per-group的线程,如果idle超时,则会销毁该线程 |
 | servicecomb.executor.default.maxQueueSize-per-group | Integer.MAX_VALUE | 每组线程池中任务队列的最大长度                                            |
 | servicecomb.rest.server.requestWaitInPoolTimeout    | 30000             |在同步线程中排队等待执行的超时时间,单位为毫秒         |
+
+### 异步线程池
+
+所谓的异步线程池,实际上是没有提供额外的线程池。 所有的业务逻辑直接在 event-loop 线程池执行。 使用异步线程池,业务代码不能够存在阻塞操作。
+常见的阻塞操作包括
+
+* 使用同步API,调用其他微服务,比如 RestTemplate、透明RPC等。
+* 特别耗时的任务。比如等待IO、等待锁、Sleep等。
+