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

albumenj pushed a commit to branch refactor/next-2
in repository https://gitbox.apache.org/repos/asf/dubbo-website.git


The following commit(s) were added to refs/heads/refactor/next-2 by this push:
     new 75acae3d83 add development's document (#2230)
75acae3d83 is described below

commit 75acae3d8349b1ad8eac3cc7b1a41daf875d18fa
Author: Starfish-Ning <[email protected]>
AuthorDate: Tue Feb 14 14:46:52 2023 +0800

    add development's document (#2230)
    
    Co-authored-by: liuningbo <liuningbo.nbugs.com>
---
 content/zh-cn/overview/tasks/develop/async.md      | 157 ++++++++++++++++++++-
 content/zh-cn/overview/tasks/develop/context.md    |  62 +++++++-
 content/zh-cn/overview/tasks/develop/generic.md    |  66 ++++++++-
 .../overview/tasks/develop/service_reference.md    | 124 +++++++++++++++-
 .../zh-cn/overview/tasks/develop/version_group.md  |  68 +++++++++
 5 files changed, 468 insertions(+), 9 deletions(-)

diff --git a/content/zh-cn/overview/tasks/develop/async.md 
b/content/zh-cn/overview/tasks/develop/async.md
index 5b1eb726b6..3bc1b89683 100644
--- a/content/zh-cn/overview/tasks/develop/async.md
+++ b/content/zh-cn/overview/tasks/develop/async.md
@@ -1,7 +1,160 @@
 ---
 type: docs
 title: "异步调用"
-linkTitle: "异步调用"
+linkTitle: "Provider端和Consumer端异步调用"
 weight: 3
-description: ""
+description: "某些情况下希望dubbo接口异步调用,避免不必要的等待。"
 ---
+## 异步调用
+Dubbo异步调用分为Provider端异步调用和Consumer端异步调用。
+Provider端异步执行将阻塞的业务从Dubbo内部线程池切换到业务自定义线程,
+避免Dubbo线程池的过度占用,有助于避免不同服务间的互相影响。异步执行无异于节省资源或提升RPC响应性能。
+
+*<font color='#FF7D00' size=4 > 注意 </font>*
+
+> Provider 端异步执行和 Consumer 端异步调用是相互独立的,你可以任意正交组合两端配置
+> + Consumer同步 - Provider同步
+> + Consumer异步 - Provider同步
+> + Consumer同步 - Provider异步
+> + Consumer异步 - Provider异步
+
+## 使用场景
+* 对于Provider端来说,如果接口比较耗时,避免dubbo线程被阻塞,可以使用异步将线程切换到业务线程。
+* 对于Consumer端来说,调用Dubbo接口没有严格时序上的关系、不是原子操作、不影响逻辑情况下可以使用异步调用。
+
+
+## Provider异步
+
+### 1、使用CompletableFuture实现异步
+
+接口定义:
+```java
+public interface AsyncService {
+    /**
+     * 同步调用方法
+     */
+    String invoke(String param);
+    /**
+     * 异步调用方法
+     */
+    CompletableFuture<String> asyncInvoke(String param);
+}
+
+```
+服务实现:
+```java
+@DubboService
+public class AsyncServiceImpl implements AsyncService {
+
+    @Override
+    public String invoke(String param) {
+        try {
+            long time = ThreadLocalRandom.current().nextLong(1000);
+            Thread.sleep(time);
+            StringBuilder s = new StringBuilder();
+            s.append("AsyncService invoke 
param:").append(param).append(",sleep:").append(time);
+            return s.toString();
+        }
+        catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+        }
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<String> asyncInvoke(String param) {
+        // 建议为supplyAsync提供自定义线程池
+        return CompletableFuture.supplyAsync(() -> {
+            try {
+                // Do something
+                long time = ThreadLocalRandom.current().nextLong(1000);
+                Thread.sleep(time);
+                StringBuilder s = new StringBuilder();
+                s.append("AsyncService asyncInvoke 
param:").append(param).append(",sleep:").append(time);
+                return s.toString();
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+            }
+            return null;
+        });
+    }
+}
+
+```
+通过 return CompletableFuture.supplyAsync() ,业务执行已从 Dubbo 线程切换到业务线程,避免了对 Dubbo 
线程池的阻塞。
+
+### 2、使用AsyncContext实现异步
+
+Dubbo 提供了一个类似 Servlet 3.0 的异步接口AsyncContext,在没有 CompletableFuture 
签名接口的情况下,也可以实现 Provider 端的异步执行。
+
+接口定义:
+```java
+public interface AsyncService {
+    String sayHello(String name);
+}
+
+```
+
+服务实现:
+
+```java
+public class AsyncServiceImpl implements AsyncService {
+    public String sayHello(String name) {
+        final AsyncContext asyncContext = RpcContext.startAsync();
+        new Thread(() -> {
+            // 如果要使用上下文,则必须要放在第一句执行
+            asyncContext.signalContextSwitch();
+            try {
+                Thread.sleep(500);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            // 写回响应
+            asyncContext.write("Hello " + name + ", response from provider.");
+        }).start();
+        return null;
+    }
+}
+
+```
+
+## Consumer异步
+```java
+@DubboReference
+private AsyncService asyncService;
+
+@Override
+public void run(String... args) throws Exception {
+    //调用异步接口
+    CompletableFuture<String> future1 = asyncService.asyncInvoke("async call 
request1");
+    future1.whenComplete((v, t) -> {
+        if (t != null) {
+            t.printStackTrace();
+        } else {
+            System.out.println("AsyncTask Response-1: " + v);
+        }
+    });
+    //两次调用并非顺序返回
+    CompletableFuture<String> future2 = asyncService.asyncInvoke("async call 
request2");
+    future2.whenComplete((v, t) -> {
+        if (t != null) {
+            t.printStackTrace();
+        } else {
+            System.out.println("AsyncTask Response-2: " + v);
+        }
+    });
+    //consumer异步调用
+    CompletableFuture<String> future3 =  CompletableFuture.supplyAsync(() -> {
+        return asyncService.invoke("invoke call request3");
+    });
+    future3.whenComplete((v, t) -> {
+        if (t != null) {
+            t.printStackTrace();
+        } else {
+            System.out.println("AsyncTask Response-3: " + v);
+        }
+    });
+
+    System.out.println("AsyncTask Executed before response return.");
+}
+```
diff --git a/content/zh-cn/overview/tasks/develop/context.md 
b/content/zh-cn/overview/tasks/develop/context.md
index d867aee995..b751527fc4 100644
--- a/content/zh-cn/overview/tasks/develop/context.md
+++ b/content/zh-cn/overview/tasks/develop/context.md
@@ -1,7 +1,65 @@
 ---
 type: docs
 title: "上下文参数传递"
-linkTitle: "上下文参数"
+linkTitle: "上下文参数传递"
 weight: 5
-description: ""
+description: "通过 Dubbo 中的 Attachment 在服务消费方和提供方之间传递参数"
 ---
+## 上下文参数传递
+在 Dubbo 3 中,RpcContext 
被拆分为四大模块(ServerContext、ClientAttachment、ServerAttachment 和 ServiceContext)。
+
+它们分别承担了不同的职责:
+
+* ServiceContext:在 Dubbo 内部使用,用于传递调用链路上的参数信息,如 invoker 对象等
+* ClientAttachment:在 Client 端使用,往 ClientAttachment 中写入的参数将被传递到 Server 端
+* ServerAttachment:在 Server 端使用,从 ServerAttachment 中读取的参数是从 Client 中传递过来的
+* ServerContext:在 Client 端和 Server 端使用,用于从 Server 端回传 Client 端使用,Server 端写入到 
ServerContext 的参数在调用结束后可以在 Client 端的 ServerContext 获取到
+
+## 使用场景
+1、Dubbo系统间调用时,想传递一些通用参数,可通过Dubbo提供的扩展如Filter等实现统一的参数传递
+
+2、Dubbo系统间调用时,想传递接口定义之外的参数,可在调用接口前使用setAttachment传递参数。
+
+## 使用方式
+setAttachment 设置的 KV 对,在完成下面一次远程调用会被清空,即多次远程调用要多次设置。
+
+接口定义:
+```java
+public interface ContextService {
+    String invoke(String param);
+}
+
+```
+服务实现:
+```java
+@DubboService
+public class ContextServiceImpl implements ContextService{
+    @Override
+    public String invoke(String param) {
+        //ServerAttachment接收客户端传递过来的参数
+        Map<String, Object> serverAttachments = 
RpcContext.getServerAttachment().getObjectAttachments();
+        System.out.println("ContextService serverAttachments:" + 
JSON.toJSONString(serverAttachments));
+        //往客户端传递参数
+        RpcContext.getServerContext().setAttachment("serverKey","serverValue");
+        StringBuilder s = new StringBuilder();
+        s.append("ContextService param:").append(param);
+        return s.toString();
+    }
+}
+
+```
+
+接口调用:
+```java
+    //往服务端传递参数
+    
RpcContext.getClientAttachment().setAttachment("clientKey1","clientValue1");
+    String res = contextService.invoke("context1");
+    //接收传递回来参数
+    Map<String, Object> clientAttachment = 
RpcContext.getServerContext().getObjectAttachments();
+    System.out.println("ContextTask clientAttachment:" + 
JSON.toJSONString(clientAttachment));
+    System.out.println("ContextService Return : " + res);
+
+```
+
+*<font color='#FF7D00' size=4 > 注意 </font>*
+> path, group, version, dubbo, token, timeout 几个 key 是保留字段,请使用其它值。
\ No newline at end of file
diff --git a/content/zh-cn/overview/tasks/develop/generic.md 
b/content/zh-cn/overview/tasks/develop/generic.md
index ce11529b39..7a655156a1 100644
--- a/content/zh-cn/overview/tasks/develop/generic.md
+++ b/content/zh-cn/overview/tasks/develop/generic.md
@@ -1,7 +1,69 @@
 ---
 type: docs
-title: "泛化调用"
+title: "开发服务"
 linkTitle: "泛化调用"
 weight: 6
-description: ""
+description: "在调用方没有服务方提供的 API(SDK)的情况下,对服务方进行调用"
 ---
+## 泛化调用
+泛化调用(客户端泛化调用)是指在调用方没有服务方提供的 API(SDK)的情况下,对服务方进行调用,并且可以正常拿到调用结果。
+
+## 使用场景
+调用方没有接口及模型类元,知道服务的接口的全限定类名和方法名的情况下,可以通过泛化调用调用对应接口。
+比如:实现一个通用的服务测试框架
+
+## 使用方式
+
+本示例中使用"发布和调用" 中示例代码
+
+接口定义:
+```java
+public interface DevelopService {
+    String invoke(String param);
+}
+```
+
+接口实现1:
+```java
+@DubboService(group = "group1",version = "1.0")
+public class DevelopProviderServiceV1 implements DevelopService{
+    @Override
+    public String invoke(String param) {
+        StringBuilder s = new StringBuilder();
+        s.append("ServiceV1 param:").append(param);
+        return s.toString();
+    }
+}
+```
+
+## 客户端调用
+
+```java
+@Component
+public class GenericTask implements CommandLineRunner {
+
+    @Override
+    public void run(String... args) throws Exception {
+        GenericService genericService = 
buildGenericService("org.apache.dubbo.samples.develop.DevelopService","group2","2.0");
+        //传入需要调用的方法,参数类型列表,参数列表
+        Object result = genericService.$invoke("invoke", new 
String[]{"java.lang.String"}, new Object[]{"g1"});
+        System.out.println("GenericTask Response: " + 
JSON.toJSONString(result));
+    }
+
+    private GenericService buildGenericService(String interfaceClass, String 
group, String version) {
+        ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
+        reference.setInterface(interfaceClass);
+        reference.setVersion(version);
+        //开启泛化调用
+        reference.setGeneric("true");
+        reference.setTimeout(30000);
+        reference.setGroup(group);
+        ReferenceCache cache = SimpleReferenceCache.getCache();
+        try {
+            return cache.get(reference);
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+}
+```
\ No newline at end of file
diff --git a/content/zh-cn/overview/tasks/develop/service_reference.md 
b/content/zh-cn/overview/tasks/develop/service_reference.md
index a8ff03010e..911d4d05a2 100644
--- a/content/zh-cn/overview/tasks/develop/service_reference.md
+++ b/content/zh-cn/overview/tasks/develop/service_reference.md
@@ -1,7 +1,125 @@
 ---
 type: docs
-title: "发布和调用 Dubbo 服务"
-linkTitle: "发布和调用"
+title: "开发服务"
+linkTitle: "发布和调用 Dubbo 服务"
 weight: 2
-description: ""
+description: "通过示例简单展示一个Dubbo服务的发布和调用"
 ---
+## 发布和调用
+通过一个简单的Springboot实例代码,展示Dubbo服务的发布和调用
+
+本文将基于 Dubbo Samples 示例演示如何快速搭建并部署一个微服务应用。
+代码地址:[dubbo-samples-develop](https://github.com/apache/dubbo-samples/10-task/dubbo-samples-develop)
+代码分为三个模块,如下图:
+![project](/imgs/v3/develop/develop-project.png)
+
+## 准备
+本示例代码基于Springboot 3.0
+
+1、首先需要一个可用的注册中心Zookeeper,Nacos,Redis均可。
+
+2、新建一个maven工程,添加如下依赖
+```xml
+        <!-- registry dependency -->
+        <dependency>
+            <groupId>com.alibaba.nacos</groupId>
+            <artifactId>nacos-client</artifactId>
+            <version>${nacos.version}</version>
+        </dependency>
+
+        <!-- dubbo dependency-->
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-spring-boot-starter</artifactId>
+            <version>${dubbo.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+
+```
+本示例使用的注册中心为Nacos,使用ZK请将nacos-client包替换为对应版本zk客户端包。
+
+## 发布服务
+1、定义服务接口
+```java
+public interface DevelopService {
+    String invoke(String param);
+}
+```
+2、服务接口实现
+```java
+@DubboService(group = "group1",version = "1.0")
+public class DevelopProviderServiceV1 implements DevelopService{
+    @Override
+    public String invoke(String param) {
+        StringBuilder s = new StringBuilder();
+        s.append("ServiceV1 param:").append(param);
+        return s.toString();
+    }
+}
+```
+使用@DubboService 注解,Dubbo会将对应的服务注册到spring,
+在spring启动后调用对应的服务导出方法,将服务注册到注册中心,
+这样Consumer端才能发现我们发布的服务并调用
+
+3、添加Dubbo配置
+
+添加application.properties相关配置,也可新建dubbo.properties保存dubbo相关配置,内容如下:
+```properties
+dubbo.application.name=provider
+
+# Enable token verification for each invocation
+dubbo.provider.token=false
+
+# Specify the registry address
+# dubbo.registry.address=nacos://localhost:8848?username=nacos&password=nacos
+dubbo.registry.address=nacos://${nacos.address:localhost}:8848?username=nacos&password=nacos
+
+dubbo.protocol.name=dubbo
+dubbo.protocol.port=20881
+```
+
+4、启动服务
+
+创建Springboot启动类,需添加@EnableDubbo注解,开启Dubbo自动配置功能
+```java
+@EnableDubbo
+@SpringBootApplication
+public class DevelopApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(DevelopApplication.class, args);
+    }
+}
+
+```
+启动成功后,在注册中心可以看到对应的服务列表,如图:
+![serviceList](/imgs/v3/develop/develop-service-list.png)
+
+## 调用服务
+
+创建DemoTask类,通过@DubboReference注解对需要调用的服务进行引入。即可像调用本地方法一样调用远程服务了。
+
+```java
+//实现CommandLineRunner 让Springboot启动后调用run方法
+@Component
+public class DemoTask implements CommandLineRunner {
+    @DubboReference(group = "group1",version = "1.0")
+    private DevelopService developService;
+
+    @Override
+    public void run(String... args) throws Exception {
+        //调用DevelopService的group1分组实现
+        System.out.println("Dubbo Remote Return ======> " + 
developService.invoke("1"));
+    }
+}
+```
+
+启动服务 打印
+
+`Dubbo Remote Return ======> ServiceV1 param:1`
+
+说明服务调用成功
diff --git a/content/zh-cn/overview/tasks/develop/version_group.md 
b/content/zh-cn/overview/tasks/develop/version_group.md
index b8787b672d..2883384442 100644
--- a/content/zh-cn/overview/tasks/develop/version_group.md
+++ b/content/zh-cn/overview/tasks/develop/version_group.md
@@ -5,3 +5,71 @@ linkTitle: "版本与分组"
 weight: 4
 description: ""
 ---
+## 版本与分组
+Dubbo服务中,接口并不能唯一确定一个服务,只有接口+分组+版本号才能唯一确定一个服务。
+
+## 使用场景
+* 
当同一个接口针对不同的业务场景、不同的使用需求或者不同的功能模块等场景,可使用服务分组来区分不同的实现方式。同时,这些不同实现所提供的服务是可并存的,也支持互相调用。
+* 当接口实现需要升级又要保留原有实现的情况下,即出现不兼容升级时,我们可以使用不同版本号进行区分。
+
+
+## 使用方式
+使用 @DubboService 注解,添加 group 参数和 version 参数
+本示例中使用"发布和调用" 中示例代码
+
+接口定义:
+```java
+public interface DevelopService {
+    String invoke(String param);
+}
+```
+
+接口实现1:
+```java
+@DubboService(group = "group1",version = "1.0")
+public class DevelopProviderServiceV1 implements DevelopService{
+    @Override
+    public String invoke(String param) {
+        StringBuilder s = new StringBuilder();
+        s.append("ServiceV1 param:").append(param);
+        return s.toString();
+    }
+}
+```
+接口实现2:
+```java
+@DubboService(group = "group2",version = "2.0")
+public class DevelopProviderServiceV2 implements DevelopService{
+    @Override
+    public String invoke(String param) {
+        StringBuilder s = new StringBuilder();
+        s.append("ServiceV2 param:").append(param);
+        return s.toString();
+    }
+}
+```
+
+启动服务后,可以在注册中心看到对应的服务列表,如下:
+![serviceList](/imgs/v3/develop/develop-service-list.png)
+
+
+客户端接口调用:
+
+> 使用 @DubboReference 注解,添加 group 参数和 version 参数
+
+```java
+@DubboReference(group = "group1",version = "1.0")
+private DevelopService developService;
+
+@DubboReference(group = "group2",version = "2.0")
+private DevelopService developServiceV2;
+
+@Override
+public void run(String... args) throws Exception {
+    //调用DevelopService的group1分组实现
+    System.out.println("Dubbo Remote Return ======> " + 
developService.invoke("1"));
+    //调用DevelopService的另一个实现
+    System.out.println("Dubbo Remote Return ======> " + 
developServiceV2.invoke("2"));
+}
+```
+

Reply via email to