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 2020/03/30 01:27:14 UTC

[servicecomb-docs] branch master updated: [SCB-1831] add examples to use DiscoveryTree and InvocationContext

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


The following commit(s) were added to refs/heads/master by this push:
     new 1959a30  [SCB-1831] add examples to use DiscoveryTree and InvocationContext
1959a30 is described below

commit 1959a30aaf04c5d9c4efd5e89a5c3d56e9169b50
Author: liubao <bi...@qq.com>
AuthorDate: Sat Mar 28 17:36:38 2020 +0800

    [SCB-1831] add examples to use DiscoveryTree and InvocationContext
---
 .../zh_CN/docs/general-development/context.md      | 152 +++++++++++++++++----
 java-chassis-reference/zh_CN/docs/start/design.md  |   2 +-
 2 files changed, 129 insertions(+), 25 deletions(-)

diff --git a/java-chassis-reference/zh_CN/docs/general-development/context.md b/java-chassis-reference/zh_CN/docs/general-development/context.md
index 1b4b97a..1f2b698 100644
--- a/java-chassis-reference/zh_CN/docs/general-development/context.md
+++ b/java-chassis-reference/zh_CN/docs/general-development/context.md
@@ -1,36 +1,140 @@
 # 使用Context传递控制消息
 
-ServiceComb提供了Context在微服务之间传递数据。Context是key/value对,只能够使用String类型的数据。由于Context会序列化为json格式并通过HTTP Header传递,因此也不支持ASCII之外的字符,其他字符需要开发者先自行编码再传递。Context在一次请求中,会在请求链上传递,不需要重新设置。[access log](../build-provider/access-log-configuration.md)的trace id等功能都基于这个特性实现的。
+Context 用于在微服务之间和微服务内部传递上下文数据。 Context 是 key/value 对,只能够使用 String 类型。
+Context 会序列化为 json 格式并通过 HTTP Header 传递,因此也不支持 ASCII 之外的字符,其他字符需要开发者先自行编码再传递。
+Context 在一次请求中,会在请求链上传递,不需要重新设置。[access log](../build-provider/access-log-configuration.md)的 trace id 等
+功能都基于这个特性实现的。
 
-## 场景描述
-* 在认证场景,Edge Service认证通过以后,需要将会话ID、用户名称等信息传递给微服务,实现鉴权等逻辑
-* 灰度发布场景,需要结合自定义的tag实现引流,tag信息需要传递给微服务
+## 使用 Context 的场景
 
-## 使用参考
+* 在认证场景,Edge Service 认证通过以后,需要将会话 ID、用户名称等信息传递给微服务,实现鉴权等逻辑。
+* 灰度发布场景,需要结合自定义的 tag 实现引流,tag 信息需要传递给微服务。
+* 开发 Handler 处理链的时候,一个 Handler 需要将计算结果传递给下一个 Handler。
 
-* 在Hanlder中获取和设置Context
+## 使用参考
 
-Handler包含了Invocation对象,可以直接调用invocation.addContext和invocation.getContext设置。
+* 在 Hanlder 中获取和设置Context
+    Handler 包含了 Invocation 对象,可以直接调用 invocation.addContext 和 invocation.getContext 。
 
 * 在服务接口中获取Context
 
-通过接口注入
-```
-public Response cseResponse(InvocationContext c1)
-```
-或者
-```
-ContextUtils.getInvocationContext()
-```
+    通过接口注入
+    
+        ```
+        public Response cseResponse(InvocationContext c1)
+        ```
+    或者
+    
+        ```
+        ContextUtils.getInvocationContext()
+        ```
 
 * 在Edge Service中设置Context
 
-通过重载EdgeInvocation
-```
-EdgeInvocation edgeInvocation = new EdgeInvocation() {
-  protected void createInvocation() {
-    super.createInvocation();
-    this.invocation.addContext("hello", "world");
-  }
-};
-```
\ No newline at end of file
+    通过重载EdgeInvocation
+    
+        ```
+        EdgeInvocation edgeInvocation = new EdgeInvocation() {
+          protected void createInvocation() {
+            super.createInvocation();
+            this.invocation.addContext("hello", "world");
+          }
+        };
+        ```
+        
+## 案例: 使用 Context 和 DiscoveryTree 实现轮询调用一个微服务的所有实例
+
+通常微服务的调用,是将请求发送到一个实例,这个实例是根据负载均衡策略决定的,业务开发不可控制。为了实现轮询调用一个微服务的所有实例,
+首先需要获取一个微服务的所有实例列表,然后逐个调用。 LoadBalance 模块支持通过 Context 传递 Endpoint 信息, 如果 Endpoint 已经
+设置, 可以跳过负载均衡判断, 使用用户自己指定的 Endpoint。 
+
+* 使用 DiscoveryTree 获取微服务实例列表
+
+        ```java
+        public class TestDateTimeSchema {
+          private DiscoveryTree discoveryTree = new DiscoveryTree();
+        
+          public TestDateTimeSchema() {
+            discoveryTree.addFilter(new CustomEndpointDiscoveryFilter());
+            discoveryTree.sort();
+          }
+          
+          private void testDateTimeSchemaMulticast() throws Exception {
+            DiscoveryContext context = new DiscoveryContext();
+            VersionedCache serversVersionedCache = discoveryTree.discovery(context, "springmvctest", "springmvc", "0+");
+            List<String> enpoints = serversVersionedCache.data(); // 获取到实例列表,可以给下面的处理流程使用
+          }
+        }
+        
+        public class CustomEndpointDiscoveryFilter extends AbstractEndpointDiscoveryFilter {
+          @Override
+          protected String findTransportName(DiscoveryContext context, DiscoveryTreeNode parent) {
+            //only need rest endpoints
+            return "rest";
+          }
+        
+          @Override
+          protected Object createEndpoint(String transportName, String endpoint, MicroserviceInstance instance) {
+            return endpoint;
+          }
+        
+          @Override
+          public int getOrder() {
+            return 0;
+          }
+        }
+        ```
+    
+    上面的代码通过 DiscoveryTree 发现实例列表, 并且实现了 CustomEndpointDiscoveryFilter , 将发现的实例信息转换为 cache 的返回
+    类型, 即 String。
+    
+* 通过 InvocationContext 传递 Endpoint 信息给 Load Balance, 每次调用访问用户指定的 Endpoint。
+    访问 InvocationContext 分几种场景, 参考文章上面提到的情况。 在 Consumer 调用的场景下, 可能不在一个 Provider 的处理上下文中,
+    这个时候系统中还没有 InvocationContext 实例, 这个时候可以新创建一个实例, 新创建的实例信息会复制到系统内部。 
+    
+    使用 RPC Consumer 传递 InvocationContext 的例子:
+    
+        ```java
+          interface DateTimeSchemaWithContextInf {
+            Date getDate(InvocationContext context, Date date);
+          }
+      
+          @RpcReference(microserviceName = "springmvc", schemaId = "DateTimeSchema")
+          private DateTimeSchemaWithContextInf dateTimeSchemaWithContextInf;
+      
+          // code slip
+          for (String endpoint : enpoints) {
+            InvocationContext invocationContext = new InvocationContext();
+            invocationContext.addLocalContext(LoadbalanceHandler.SERVICECOMB_SERVER_ENDPOINT, parseEndpoint(endpoint));
+            Date date = new Date();
+            TestMgr.check(date.getTime(), dateTimeSchemaWithContextInf.getDate(invocationContext, date).getTime());
+          }
+      
+          // code slip
+          private Endpoint parseEndpoint(String endpointUri) throws Exception {
+            URI formatUri = new URI(endpointUri);
+            Transport transport = SCBEngine.getInstance().getTransportManager().findTransport(formatUri.getScheme());
+            return new Endpoint(transport, endpointUri);
+          }
+        ``` 
+     
+     使用 RestTemplate 传递  InvocationContext 的例子:
+        
+        ```
+        for (String endpoint : enpoints) {
+          CseHttpEntity<?> entity = new CseHttpEntity<>(null);
+          InvocationContext invocationContext = new InvocationContext();
+          invocationContext.addLocalContext(LoadbalanceHandler.SERVICECOMB_SERVER_ENDPOINT, parseEndpoint(endpoint));
+          entity.setContext(invocationContext);
+    
+          Date date = new Date();
+          String dateValue = RestObjectMapperFactory.getRestObjectMapper().convertToString(date);
+          TestMgr.check(date.getTime(),
+              restTemplate
+                  .exchange("cse://springmvc/dateTime/getDate?date={1}", HttpMethod.GET,
+                      entity, Date.class, dateValue).getBody().getTime());
+         }
+         ```
+
+    ***注意:*** 2.0.2 版本开始, LoadbalanceHandler.SERVICECOMB_SERVER_ENDPOINT 传递的类型是 Endpoint, 早期版本可以直接传递 String 类型, 
+    LoadBalance 模块会将 String 类型转换为 Endpoint。 在有大量 Endpoint 的情况, 提前使用 Endpoint 类型能够减少类型转换,节省处理时间。
diff --git a/java-chassis-reference/zh_CN/docs/start/design.md b/java-chassis-reference/zh_CN/docs/start/design.md
index 6413dfa..e40ec0b 100644
--- a/java-chassis-reference/zh_CN/docs/start/design.md
+++ b/java-chassis-reference/zh_CN/docs/start/design.md
@@ -99,7 +99,7 @@ Java Chassis 可以部署运行于 JSP/Servlet 容器里面, 在这个场景
 ## Java Chassis 与 Spring Cloud 
 
 Java Chassis 和 Spring Cloud 都实现了微服务架构模式, 相比而言, Java Chassis 是一个更加紧凑的实现, 开箱即用, 而 Spring Cloud 则是
-相对松散的实现, 整合了大量的 Hystrix 组件。 
+相对松散的实现, 整合了大量的 Netflix 组件。 
 
 微服务架构模式关注微服务内部和微服务之间的设计, 也关注微服务与微服务基础设施之间的关系。 Java Chassis 微服务基础设施包括服务注册和发现,
 服务配置管理, 灰度发布和契约管理等功能。 Spring Cloud 可以使用 [spring-cloud-huawei](https://github.com/huaweicloud/spring-cloud-huawei)