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)