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 0a8edf7 adding migrating 1.x to 2.x guide (#111)
0a8edf7 is described below
commit 0a8edf7f9f92e19a3b5173a9179769fa96a85404
Author: bao liu <[email protected]>
AuthorDate: Mon Feb 10 09:51:26 2020 +0800
adding migrating 1.x to 2.x guide (#111)
* adding migrating 1.x to 2.x guide
* add RestTemplate usage notice
* 增加highway和AsyncRestTemplate的变更说明
---
java-chassis-reference/zh_CN/SUMMARY.md | 1 +
java-chassis-reference/zh_CN/upgrading/1_to_2.md | 211 +++++++++++++++++++++++
2 files changed, 212 insertions(+)
diff --git a/java-chassis-reference/zh_CN/SUMMARY.md
b/java-chassis-reference/zh_CN/SUMMARY.md
index fd4fca5..7c3b866 100644
--- a/java-chassis-reference/zh_CN/SUMMARY.md
+++ b/java-chassis-reference/zh_CN/SUMMARY.md
@@ -86,5 +86,6 @@
* [处理链参考](references-handlers/intruduction.md)
* [负载均衡](references-handlers/loadbalance.md)
* [公钥认证](references-handlers/publickey.md)
+* [1.x迁移2.x指南](upgrading/1_to_2.md)
* [常见问题](question-and-answer/question_answer.md)
* [微服务接口兼容常见问题](question-and-answer/interface-compatibility.md)
diff --git a/java-chassis-reference/zh_CN/upgrading/1_to_2.md
b/java-chassis-reference/zh_CN/upgrading/1_to_2.md
new file mode 100644
index 0000000..d4cacd4
--- /dev/null
+++ b/java-chassis-reference/zh_CN/upgrading/1_to_2.md
@@ -0,0 +1,211 @@
+# 1.x迁移2.x指南
+
+## 变更点说明
+
+* Highway通信协议的变更
+Highway通信协议是2.x的变更是最大的。如果业务采用了Highway通信协议,需要确保所有相关的consumer和provider都必须升级,低版本的consumer和高版本的provider之间无法直接通信。此外,从代码风格的层面,还有如下一些变更。
+
+ 1. 空字符串和null的传输:由于protobuffer协议对于空字符串和null在序列化的时候,都是为空,反序列化的结果都是null。
因此应用程序的业务逻辑不应该通过空字符串和null表达不一样的语义。尽管对于REST,程序底层支持这样的区分,仍然不建议将业务逻辑构筑在这个假设之上,从而避免很多的陷阱。
+
+ 2.
如果请求参数或者返回值是一个POJO,假设Person,REST可以返回null,但是HIGHWAY始终会创建一个Person对象返回。导致这个差异是REST和HIGHWAY序列化流程差异导致的。因此业务逻辑也尽可能不要依赖于null对象提供语义。
+
+ 3. 在contrast
first编程模式情况下,用户先写契约,然后通过契约生成代码,并将契约文件放到microservices/{microservice
name}/{schema
id}.yaml文件中,这种情况下不会通过代码生成契约。通常通过工具生成代码,工具生成的数据类型和契约的数据类型匹配,但是如果这种场景的代码经过修改,并且yaml中的数据类型是number,而代码中的类型是Integer,在HIGHWAY通信模式下会报告错误。
protobuffer不支持将Integer类型采用Double的方式序列化。在contract
first编程模式下,建议通过生成工具生成代码,这样用户就不用了解swagger数据类型和JAVA数据类型映射的细节,避免一些陷阱。
+
+ 4. HIGWHAY的数据类型定义不支持一些特殊字符串,比如 "H.264"和"MPEG-2"在OPEN
API里面是合法的参数名称,但是在protobuffer里面是不合法的参数名称。带有"."和"-"的参数名字不能用于HIGHWAY。如果存在,第一次访问这个接口的时候,会报告:
"io.protostuff.compiler.parser.ParserException: Could not parse syntax"异常。
+
+ 5.
对于ENUM的使用一个需要特别注意的地方,protobuffer采用int来序列化ENUN,int的默认值(即0)不会序列化,那么反序列化的时候,ENUM的缺省值必须为第一个值。应用程序需要将null和第一个缺省值当成一样的语义对待。比较好的做法是在程序里面显示的给ENUM字段赋缺省值。
+
+ 6.
HIGHWAY不支持数组参数存在null值的情况。比如如果一个接口的参数是String[],那么里面的元素不能为null,否则序列化和反序列化会失败。
+
+ 7.
对于primitive类型,并且接口声明为@Required,由于HIGHWAY并不会序列化缺省值,比如0等,在Consumer端传递的参数值为0的时候,Provider端并不能区分这个值是传递了0,还是没有传递。因此HIGHWAY会忽略@Required声明,使用缺省值0。
+
+ 8. 如果一个属性的名称采用一个小写字母开头,并且只有一个小写字母,即使生成的getter/setter是合法的,
swagger生成的属性名称还是会出现错误。应该尽可能避免使用这样的属性名称。必须使用的场景,需要显示的使用@JsonProperty声明。
+
+```
+public class SpecialNameModel {
+ // names starts with only one lower case , although getter/setter generated
by IDE is correct,
+ // will cause jackson generate incorrect swagger names.
+ // @JsonProperty must be used to make json work in a predictable way.
+ @JsonProperty("aIntName")
+ private int aIntName;
+
+ public int getaIntName() {
+ return aIntName;
+ }
+
+ public void setaIntName(int aIntName) {
+ this.aIntName = aIntName;
+ }
+}
+```
+
+***优秀实践***:
+
+ 1.
一个@RpcSchema或者@RestSchema定义的所有接口,如果部分接口HIGHWAY不支持,并且用户可能将部分接口作为HIGHWAY发布,建议将这些接口放到独立的类里面,使用不一样的Schema
ID进行区分,比如"MySchemaHighwayOnly", "MySchemaRestOnly", "MySchema"。
+
+比如:
+```
+public enum Media {
+ @JsonProperty("AAC")
+ AAC,
+ @JsonProperty
+ FLAC,
+ @JsonProperty("H.264")
+ H_264,
+ @JsonProperty("MPEG-2")
+ MPEG_2,
+ WMV
+}
+```
+因为protobuffer的IDL文件不支持 ., -等字符,所以上述例子中的H.264和MPEG-2名称不能够用于HIGHWAY的ENUM类型。
+
+
+* RestTemplate的使用
+
+对于下面的consumer和provider代码:
+
+```
+// provider
+
+ @PostMapping(path = "/object")
+ public Object testObject(@RequestBody Object input)
+
+// consumer
+ Object result = restTemplate.postForObject(prefix + "/object", new
EmptyObject(), EmptyObject.class);
+```
+
+1.x版本返回的result类型为Map。 2.x版本返回的类型和postForObject指定的类型一致,上面的示例中,结果为EmptyObject类似。
+
+下面的代码,1.x和2.x版本运行的结果是一样的:
+
+```
+List<GenericObjectParam<List<RecursiveObjectParam>>> response =
consumers.getSCBRestTemplate()
+ postForObject("/testListObjectParam", request, List.class);
+```
+
+前提条件是GenericObjectParam和RecursiveObjectParam在consumer的classpath中存在对应的类,并且package和服务端定义的类一样。如果不一样response类型为List<Map>,上面的代码会抛出类型转换异常。
+
+2.x版本在保持兼容的情况下,支持下面的用法:
+
+```
+HttpEntity<SpringmvcBasicRequestModel> requestEntity = new
HttpEntity<>(requestModel, null);
+List<SpringmvcBasicResponseModel> responseModelList =
+ consumers.getSCBRestTemplate().exchange("/postListObject",
HttpMethod.POST, requestEntity,
+ new ParameterizedTypeReference<List<SpringmvcBasicResponseModel>>() {
+ }).getBody();
+```
+
+这种方式的语义根据清晰,在使用泛型的时候,建议采用这种用法。
+
+可以看出java-chassis对于RestTemplate使用的语义在2.x和Spring
MVC保持了一致,同时兼容了1.x的用法。细心的开发者可能注意到了1.x的运行结果Spring
MVC是得不到的,这是因为1.x版本可以根据契约类型反序列化对象。2.x也支持这种方式,新增了"调用类型"覆盖"契约类型"的方式,这种方式根据对于consumer和provider之间的编译依赖更小。
+
+* AsyncRestTemplate的使用
+
+1.x 和 2.x 中AsyncRestTemplate的使用方式一样,没有变化。但是由于2.x只支持spring 5版本,而spring
5将AsyncRestTemplate标记为废弃状态,开发者在后续开发过程中尽可能不要使用AsyncRestTemplate。可以使用CompletableFuture来替代,可以参考这个[例子](https://github.com/apache/servicecomb-samples/pull/41/files)。
+
+## 常见问题
+
+### 运行错误
+
+* java-chassis运行时依赖于接口定义里面的名字
+
+为了更好的基于swagger对服务进行治理,以及提高客户端代码书写的灵活性,java-chassis要求书写的接口定义代码在编译的时候,带上参数名称信息,否则会报告如下错误:
+
+```
+Caused by: java.lang.IllegalStateException: parameter name is not present,
method=org.apache.servicecomb.samples.porter.file.api.InternalAccessEndpoint:localAccess
+solution:
+ change pom.xml, add compiler argument: -parameters, for example:
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <compilerArgument>-parameters</compilerArgument>
+ </configuration>
+ </plugin>
+```
+
+解决该问题可以通过配置maven compiler plugin, 加上-parameters参数。如果在IDE下面运行,需要设置 build ->
java compilers 在编译参数里面增加-parameters。
+
+* spring 5变更
+
+cse.bean.xml文件如果采用了classpath查找定义文件
+
+```
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
classpath:org/springframework/beans/factory/xml/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
+ http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+```
+
+会报告下面的错误:
+
+```
+[main][WARN][org.springframework.beans.factory.xml.XmlBeanDefinitionReader:48]
Ignored XML validation warning
+org.xml.sax.SAXParseException: schema_reference.4: 无法读取方案文档
'classpath:org/springframework/beans/factory/xml/spring-beans-3.0.xsd', 原因为 1)
无法找到文档; 2) 无法读取文档; 3) 文档的根元素不是 <xsd:schema>。
+ at
com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)
~[?:1.8.0_131]
+ at
com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.warning(ErrorHandlerWrapper.java:99)
[?:1.8.0_131]
+ at
com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:392)
[?:1.8.0_131]
+```
+
+修改为:
+
+```
+<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
+```
+
+* SCBEngine使用时机
+
+代码
+
+```
+@RestSchema(schemaId = "inspector")
+@Path("/inspector")
+public class InspectorEndpoint {
+ private InspectorConfig inspectorConfig;
+
+ public InspectorEndpoint() {
+ this.inspectorConfig =
SCBEngine.getInstance().getPriorityPropertyManager().createConfigObject(InspectorConfig.class);
+ }
+```
+
+```
+Caused by: java.lang.NullPointerException
+ at org.apache.servicecomb.core.SCBEngine.<init>(SCBEngine.java:126)
+ at org.apache.servicecomb.core.SCBEngine.getInstance(SCBEngine.java:159)
+ at
org.apache.servicecomb.samples.porter.file.api.InspectorEndpoint.<init>(InspectorEndpoint.java:82)
+ at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
+ at
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
+ at
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
+ at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
+```
+
+不能够在bean的初始化里面使用SCBEngine的实例。这个实例业务需要在事件AFTER_REGISTRY等处理函数中使用。
+
+### 编译错误
+
+2.x相对于1.x升级了大量三方件,包括netty, vert.x, spring, spring
boot等,直接引用这些组件的代码可能编译失败。同时还对代码进行了一定重构,有些代码使用了java-chassis未公开接口,使用这些接口可能编译失败。下面是一些常见的问题。下面一些PR的修改可以参考:
+
+ *
[升级netty&vertx](https://github.com/apache/servicecomb-java-chassis/pull/1394)
+ * [升级jackson](https://github.com/apache/servicecomb-java-chassis/pull/1381)
+ * [删除spring 4和spring boot
1的支持](https://github.com/apache/servicecomb-java-chassis/pull/1415)
+ * [调整2.x版本spring boot
starter名字](https://github.com/apache/servicecomb-java-chassis/pull/1439)
+
+下面是一些场景的问题:
+
+ *
CseContext.getInstance().getTransportManager().findTransport(Const.RESTFUL)编译失败,修改为SCBEngine.getInstance().getTransportManager().findTransport(Const.RESTFUL)
+
+ * router.routeWithRegex(regex).handler(CookieHandler.create())
提示CookieHandler deprecated,删除这行代码即可,新版本的vert.x已经默认提供了cookie处理。
+
+ * Warning:(25, 24) java: io.vertx.ext.web中的io.vertx.ext.web.Cookie已过时,
修改为io.vertx.core.http.Cookie
+
+
+