blob: 6657867a279e39d843e21ddd3e01ab912505dc56 [file] [log] [blame]
<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="shortcut icon" href="../../img/favicon.ico" />
<title>1.3.0 升级 2.0.0指导 - ServiceComb Java Chassis 开发指南</title>
<link rel="stylesheet" href="../../css/theme.css" />
<link rel="stylesheet" href="../../css/theme_extra.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/styles/github.min.css" />
<script>
// Current page data
var mkdocs_page_name = "1.3.0 \u5347\u7ea7 2.0.0\u6307\u5bfc";
var mkdocs_page_input_path = "featured-topics/upgrading/1_3_0T2_0_0.md";
var mkdocs_page_url = null;
</script>
<script src="../../js/jquery-3.6.0.min.js" defer></script>
<!--[if lt IE 9]>
<script src="../../js/html5shiv.min.js"></script>
<![endif]-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</head>
<body class="wy-body-for-nav" role="document">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
<div class="wy-side-scroll">
<div class="wy-side-nav-search">
<a href="../../index.html" class="icon icon-home"> ServiceComb Java Chassis 开发指南
</a>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../toc.html">目录</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../index.html">概述</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../start/catalog.html">快速入门</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../start/design.html">设计选型参考</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../build-provider/definition/service-definition.html">微服务定义</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../build-provider/catalog.html">开发服务提供者</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../build-consumer/catalog.html">开发服务消费者</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../general-development/catalog.html">通用功能开发</a>
</li>
</ul>
<p class="caption"><span class="caption-text">多样化的通信协议功能参考</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../transports/introduction.html">多协议介绍</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../transports/rest-over-servlet.html">REST over Servlet</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../transports/rest-over-vertx.html">REST over Vertx</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../transports/http2.html">REST over HTTP2</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../transports/highway-rpc.html">Highway</a>
</li>
</ul>
<p class="caption"><span class="caption-text">多样化的服务注册与发现功能参考</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../registry/introduction.html">注册发现说明</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../registry/service-center.html">使用服务中心</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../registry/local-registry.html">本地注册发现</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../registry/distributed.html">去中心化注册发现</a>
</li>
</ul>
<p class="caption"><span class="caption-text">管理服务配置</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../config/general-config.html">通用配置说明</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../config/read-config.html">在程序中读取配置信息</a>
</li>
</ul>
<p class="caption"><span class="caption-text">服务治理功能参考</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../references-handlers/intruduction.html">处理链介绍</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../references-handlers/loadbalance.html">负载均衡</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../references-handlers/ratelimit.html">限流</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../references-handlers/router.html">灰度发布</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../references-handlers/fault-injection.html">故障注入</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../references-handlers/governance.html">流量特征治理</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../references-handlers/fail-retry.html">快速失败和重试</a>
</li>
</ul>
<p class="caption"><span class="caption-text">网关功能参考</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../edge/open-service.html">介绍</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../edge/by-servicecomb-sdk.html">使用 Edge Service 做网关</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../edge/zuul.html">使用 `zuul` 和 `spring cloud gateway` 做网关</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../edge/nginx.html">nginx 网关简单介绍</a>
</li>
</ul>
<p class="caption"><span class="caption-text">安全特性参考</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../references-handlers/publickey.html">公钥认证</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../security/tls.html">使用TLS通信</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../security/shi-yong-rsa-ren-zheng.html">使用RSA认证</a>
</li>
</ul>
<p class="caption"><span class="caption-text">服务打包和运行</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../packaging/standalone.html">以standalone模式打包</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../packaging/web-container.html">以WEB容器模式打包</a>
</li>
</ul>
<p class="caption"><span class="caption-text">专题文章</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../using-java-chassis-in-spring-boot/using-java-chassis-in-spring-boot.html">在Spring Boot中使用java chassis</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../features.html">新功能介绍系列文章</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../compatibility.html">兼容问题和兼容性策略</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../upgrading.html">升级指导系列文章</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../performance.html">性能问题分析和调优</a>
</li>
</ul>
<p class="caption"><span class="caption-text">常用配置项参考</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../config-reference/rest-transport-client.html">REST Transport Client 配置项</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../config-reference/config-center-client.html">Config Center Client 配置项</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../config-reference/service-center-client.html">Service Center Client 配置项</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../config-reference/kie-client.html">ServiceComb Kie Client 配置项</a>
</li>
</ul>
<p class="caption"><span class="caption-text">常见问题</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../question-and-answer/faq.html">FAQ</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../question-and-answer/question_answer.html">Q & A</a>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../question-and-answer/interface-compatibility.html">微服务接口兼容常见问题</a>
</li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" role="navigation" aria-label="Mobile navigation menu">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../../index.html">ServiceComb Java Chassis 开发指南</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content"><div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="../../index.html" class="icon icon-home" alt="Docs"></a> &raquo;</li>
<li>1.3.0 升级 2.0.0指导</li>
<li class="wy-breadcrumbs-aside">
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div class="section" itemprop="articleBody">
<h1 id="130-200">1.3.0 升级 2.0.0指导</h1>
<p>2.0.0 版本实现了 <a href="../features/weak-type-contrast.html">弱类型契约</a>
总体而言,对于 <code>REST</code> 通信模式, 弱类型契约不仅增强了写代码的灵活性, 还完整保留了强类型契约的写代码方式,几乎不
存在用户需要感知的变更。 对于 <code>HIGHWAY</code> 通信模式, 由于底层采用 ProtoBuffer 编码, 而 ProtoBuffer 天然就是一种
强类型契约的编解码过程, java-chassis 为了支持弱类型契约, 做了大量努力, 在一些边界条件处理上与弱类型契约存在
变更,两个版本的编解码是不兼容的,需要同时升级提供者和消费者。 在编码方式上,差异主要体现在对于缺省值的处理,对于
<code>null</code> 的处理等问题上。</p>
<h2 id="highway">Highway通信协议的变更</h2>
<p>Highway通信协议是2.0.0最大的变更点。如果业务采用了Highway通信协议,需要确保所有相关的consumer
和provider都必须升级,低版本的consumer和高版本的provider之间无法直接通信。此外,从代码风格的层面,
还有如下一些变更。</p>
<ol>
<li>空字符串和null的传输:protoBuffer 协议对空字符串和null都序列化为空,反序列化的结果都是null。
应用程序的业务逻辑不应该使用空字符串和null表达不同语义。尽管对于REST,程序底层支持这样的区分,
仍然不建议将业务逻辑构筑在这个假设之上,避免后期升级和兼容陷阱。 </li>
<li>如果请求参数或者返回值是一个POJO,假设Person,REST可以返回null,但是HIGHWAY始终会创建一个
Person 对象返回。业务逻辑尽可能不要依赖于null对象提供语义。</li>
<li>在contrast first编程模式情况下,用户先写契约,然后通过契约生成代码,并将契约文件放
<code>microservices/{microservice name}/{schema id}.yaml</code> 文件中,这种情况下不会通过代码生成
契约。通常通过工具生成代码,工具生成的数据类型和契约的数据类型匹配,但是如果这种场景的代码经过
修改,并且yaml中的数据类型是number,而代码中的类型是Integer,在HIGHWAY通信模式下会报告错误。
HIGHWAY 会将 number 类型解析为 protoBuffer 的 double 类型, 对应的 JAVA 类型为 double。
protoBuffer 不支持将Integer类型采用Double的方式序列化。在contract first编程模式下,建议通过
生成工具生成代码,这样用户就不用了解swagger数据类型和JAVA数据类型映射的细节,避免一些陷阱。</li>
<li>HIGHWAY 的数据类型定义不支持一些特殊字符串,比如 <code>H.264</code><code>MPEG-2</code> 在OPEN API里面是合法的
参数名称,但是在 protoBuffer 里面是不合法的参数名称。带有"."和"-"的参数名字不能用于 HIGHWAY。
如果存在,第一次访问这个接口的时候,会报告:
<code>io.protostuff.compiler.parser.ParserException: Could not parse syntax</code> 异常。 </li>
<li>对于 ENUM 有一个需要特别注意的地方,protoBuffer 采用int来序列化 ENUM ,int的默认值(即0)不会序列化,那么反
序列化的时候,ENUM 的缺省值必须为第一个值。应用程序需要将null和第一个缺省值当成一样的语义对待。比
较好的做法是在程序里面显示的给 ENUM 字段赋缺省值。</li>
<li>HIGHWAY 不支持数组参数存在 null 值的情况。如果一个接口的参数是String[],那么里面的元素不能
为 null,否则序列化和反序列化会失败。</li>
<li>对于 primitive 类型,并且接口声明为 @Required,由于 HIGHWAY 并不会序列化缺省值,比如 0 等,
在Consumer端传递的参数值为 0 的时候,Provider 端并不能区分这个值是传递了0,还是没有传递。因
此 HIGHWAY 会忽略 @Required 声明,使用缺省值0。</li>
<li>
<p>如果一个属性的名称采用一个小写字母开头,并且只有一个小写字母,即使生成的getter/setter是合法
的, swagger 生成的属性名称还是会出现错误。应该尽可能避免使用这样的属性名称。必须使用的场景,需要
显示的使用 @JsonProperty 声明。</p>
<pre><code> ```java
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;
}
}
```
</code></pre>
</li>
<li>
<p>返回多种类型或者通过 ContextUtils 设置状态码 HIGHWAY 不再支持。 尽管 1.3.0 之前用户也不会在 HIGHWAY 模式下
使用类似下面的代码, 但是在 1.3.0 之前的版本, 这些代码部分确实能够工作。</p>
<pre><code>```java
@PUT
public String sayHi(@PathParam("name") String name) {
ContextUtils.getInvocationContext().setStatus(202);
return name + " sayhi";
}
```
</code></pre>
</li>
</ol>
<p><strong><em>优秀实践</em></strong>:</p>
<p>如果项目中需要同时使用 REST 和 HIGHWAY 对外提供服务, 并且会使用到一些 HIGHWAY 协议有差异的用法,
可以将这些接口定义到不同的类中, 使用不一样的 Schema ID 进行区分,比如 <code>MySchemaHighwayOnly</code> ,
<code>MySchemaRestOnly</code> , <code>MySchema</code></p>
<h2 id="edge-service-model">使用 Edge Service 场景下 Model 的缺省值</h2>
<p>假设业务应用采用 Edge Service 转发请求。 并且定义了一个接口, 有如下 Model 作为参数:</p>
<pre><code class="language-java">public class Person {
private Integer age = 30;
private List&lt;String&gt; items;
}
</code></pre>
<p>用户从浏览器调用这个接口, JSON 内容为 <code>{}</code> , 不传递任何内容, 1.3.0 版本得到的 age = null, items = null 。
2.0.0 版本 age = 30, items 为空表, 不为 null 。 这个行为是由于 1.3.0 版本 Edge Service 会自动生成一个 Person
类, 这个类没有缺省值, Edge Service 重新序列化, 造成服务端取到了 null。 弱类型契约没有中间类型, 序列化的结果
和用户从浏览器传递过来的值一样。 </p>
<h2 id="resttemplate">RestTemplate的使用</h2>
<p>对于下面的 consumer 和 provider 代码:</p>
<pre><code>// provider
@PostMapping(path = &quot;/object&quot;)
public Object testObject(@RequestBody Object input)
// consumer
Object result = restTemplate.postForObject(prefix + &quot;/object&quot;,
new EmptyObject(), EmptyObject.class);
</code></pre>
<p>1.3.0 版本返回的 result 类型为 Map。 2.0.0 版本返回的类型和 postForObject 指定的类型一致,上面的示例
中,result 类型为 EmptyObject。</p>
<p>下面的代码,1.3.0 和 2.0.0 版本运行的结果是一样的:</p>
<pre><code>List&lt;GenericObjectParam&lt;List&lt;RecursiveObjectParam&gt;&gt;&gt; response = consumers.getSCBRestTemplate()
postForObject(&quot;/testListObjectParam&quot;, request, List.class);
</code></pre>
<p>前提条件是 GenericObjectParam 和 RecursiveObjectParam 在 consumer 的 classpath 中存在对应的
类,并且 package 和服务端定义的类一样。如果不一样, 则 response 类型为 List<Map>,上面的代码会
抛出类型转换异常。2.0.0 没有相同 package 的约束,并且在保持兼容的情况下,支持下面的用法:</p>
<pre><code>HttpEntity&lt;SpringmvcBasicRequestModel&gt; requestEntity = new HttpEntity&lt;&gt;(requestModel, null);
List&lt;SpringmvcBasicResponseModel&gt; responseModelList =
template.exchange(&quot;/postListObject&quot;, HttpMethod.POST, requestEntity,
new ParameterizedTypeReference&lt;List&lt;SpringmvcBasicResponseModel&gt;&gt;() {
}).getBody();
</code></pre>
<p>这种方式的语义根据清晰,在使用泛型的时候,建议采用这种用法。</p>
<p>在1.3.0版本支持如下用法:</p>
<pre><code class="language-java">template.postForEntity(url,
&quot;{\&quot;time\&quot;:3073113710456,\&quot;date\&quot;:3073113710456,\&quot;holder\&quot;:\&quot;test\&quot;}&quot;,
DateTimeModel.class)
</code></pre>
<p>即通过 JSON String 的方式传递参数给后台的 DateTimeModel 对象。 由于这种用法在解析的时候存在二义性, 2.0.0
不再支持这种用法。 可以使用 Map 或者 JsonObject 来传递。 </p>
<h2 id="asyncresttemplate">AsyncRestTemplate的使用</h2>
<p>1.3.0 和 2.0.0 中 AsyncRestTemplate 的使用方式一样,没有变化。但是由于 2.0.0 只支持spring 5版
本,而 spring 5 将 AsyncRestTemplate 标记为废弃状态,开发者在后续开发过程中尽可能不要使
用 AsyncRestTemplate 。可以使用 CompletableFuture 来替代,可以参考这
<a href="https://github.com/apache/servicecomb-samples/pull/41/files">例子</a></p>
<h2 id="spring-boot">Spring Boot 集成的变化</h2>
<p>2.0.0 不再支持 spring 4 和 spring boot 1, 缺省使用 spring 5 和 spring boot 2, 并修改了相
关 starters 的名称。 可以通过阅
<a href="../../using-java-chassis-in-spring-boot/using-java-chassis-in-spring-boot.html">在Spring Boot中使用java chassis</a> 了解
相关变化。</p>
<h2 id="jdk-11">支持 JDK 11</h2>
<p>2.0.0 版本可以在 JDK 11 下运行,并进行了简单的集成测试。 2.0.0 支持的核心 JDK 版本仍然是 8, 并没有采用 JDK 11 编译。
JDK 11 的一个主要变化是后续可能不再支持通过反射改变类的封装性。 这个特性目前有很多地方使用, 2.0.0 版本为了适配 JDK 11,
某些特性的使用会发生变化。 具体有如下几个特性 :</p>
<ul>
<li>使用 EventManager 注册事件</li>
</ul>
<p>在 1.3.0 版本, 允许采用 private 类 或者 内部匿名类作为事件监听对象, 比如:</p>
<pre><code class="language-java">public void myMethod() {
Object receiveEvent = new Object() {
@Subscribe
public void onEvent(AlarmEvent circutBreakerEvent) {
taskList.add(circutBreakerEvent);
}
};
EventManager.getEventBus().register(receiveEvent);
}
</code></pre>
<p>在 2.0.0 版本不允许,启动的时候会报告异常。 2.0.0 版本注册的事件监听器,必须保证对于 EventManager 类具有可访问性。 通常
定义的类和 EventManager 不属于同一个 package , 因此这个类必须是 public 的, 事件处理方法也必须是 public 的。 </p>
<ul>
<li>定义接口的 Model 使用匿名内部类</li>
</ul>
<p>在 1.3.0 版本, 使用匿名内部类作为 REST 接口的 Model 是允许的, 但是 2.0.0 版本不允许。 如果采用这样的类型作为接口参数,
启动的时候会报告异常。</p>
<ul>
<li>其他方面的影响</li>
</ul>
<p>由于 JDK 11 不允许通过反射破坏封装, 早期通过反射修改 private 字段的值,来规避一些三方软件的 bug, 以及做一些额外
定制变得不可行, 使用这些特性 JDK 11 暂时只是打印警告, 在 JDK 13 等更高版本会彻底禁止。 因此业务开发的时候, 尽可能
不要使用破坏封装的特性。 </p>
<h2 id="_1">常见问题</h2>
<ul>
<li>java-chassis运行时依赖于接口定义里面的名字</li>
</ul>
<p>为了更好的基于swagger对服务进行治理,以及提高客户端代码书写的灵活性,java-chassis要求书写的接口定义代码在编译的时候,带上参数名称信息,否则会报告如下错误:</p>
<pre><code>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:
&lt;plugin&gt;
&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
&lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
&lt;configuration&gt;
&lt;compilerArgument&gt;-parameters&lt;/compilerArgument&gt;
&lt;/configuration&gt;
&lt;/plugin&gt;
</code></pre>
<p>解决该问题可以通过配置maven compiler plugin, 加上-parameters参数。如果在IDE下面运行,需要设置 build -&gt; java compilers 在编译参数里面增加-parameters。</p>
<ul>
<li>spring 5变更</li>
</ul>
<p>cse.bean.xml文件如果采用了classpath查找定义文件</p>
<pre><code>&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:p=&quot;http://www.springframework.org/schema/p&quot;
xmlns:util=&quot;http://www.springframework.org/schema/util&quot;
xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
xmlns:tx=&quot;http://www.springframework.org/schema/tx&quot;
xsi:schemaLocation=&quot;
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&quot;&gt;
</code></pre>
<p>会报告下面的错误:</p>
<pre><code>[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) 文档的根元素不是 &lt;xsd:schema&gt;。
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]
</code></pre>
<p>修改为:</p>
<pre><code>&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
xsi:schemaLocation=&quot;
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&quot;&gt;
</code></pre>
<ul>
<li>SCBEngine使用时机</li>
</ul>
<p>代码</p>
<pre><code>@RestSchema(schemaId = &quot;inspector&quot;)
@Path(&quot;/inspector&quot;)
public class InspectorEndpoint {
private InspectorConfig inspectorConfig;
public InspectorEndpoint() {
this.inspectorConfig = SCBEngine.getInstance().getPriorityPropertyManager().createConfigObject(InspectorConfig.class);
}
</code></pre>
<pre><code>Caused by: java.lang.NullPointerException
at org.apache.servicecomb.core.SCBEngine.&lt;init&gt;(SCBEngine.java:126)
at org.apache.servicecomb.core.SCBEngine.getInstance(SCBEngine.java:159)
at org.apache.servicecomb.samples.porter.file.api.InspectorEndpoint.&lt;init&gt;(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)
</code></pre>
<p>不能够在bean的初始化里面使用SCBEngine的实例。这个实例业务需要在事件AFTER_REGISTRY等处理函数中使用。</p>
<h2 id="_2">编译错误</h2>
<p>2.0.0 相对于 1.0.0 升级了大量三方件,包括netty, vert.x, spring, spring boot等,直接引用这些组件的代码可能编译失败。同时还对代码进行了一定重构,有些代码使用了java-chassis未公开接口,使用这些接口可能编译失败。下面是一些常见的问题。下面一些PR的修改可以参考:</p>
<ul>
<li><a href="https://github.com/apache/servicecomb-java-chassis/pull/1394">升级netty&amp;vertx</a></li>
<li><a href="https://github.com/apache/servicecomb-java-chassis/pull/1381">升级jackson</a></li>
<li><a href="https://github.com/apache/servicecomb-java-chassis/pull/1415">删除spring 4和spring boot 1的支持</a></li>
<li><a href="https://github.com/apache/servicecomb-java-chassis/pull/1439">调整2.x版本spring boot starter名字</a></li>
</ul>
<p>下面是一些场景的问题:</p>
<ul>
<li><code>router.routeWithRegex(regex).handler(CookieHandler.create())</code> 提示 CookieHandler deprecated,删除这行代码
即可,新版本的vert.x已经默认提供了cookie处理。</li>
<li>io.vertx.ext.web中的 <code>io.vertx.ext.web.Cookie已过时</code> , 修改
<code>io.vertx.core.http.Cookie</code></li>
</ul>
<p>2.0.0 一些可能被外部使用的内部接口调整:</p>
<ul>
<li><code>Invocation</code> 类删除了 <code>getArgs</code> 接口, 替换为 <code>getSwaggerArguments</code> , 同时新增了 <code>getInvocationArguments</code>
关于这个变更的说明,请参考新特性介绍文章<a href="../features/weak-type-contrast.html">弱类型契约</a></li>
<li>删除 <code>DynamicSchemaLoader</code> , 这个类早期版本提供出来是方便注册契约, 最新版本客户端契约发现可以通过服务中心
完成,不再需要这样的功能。</li>
<li><code>CseContext.getInstance().getTransportManager().findTransport(Const.RESTFUL)</code> 修改
<code>SCBEngine.getInstance().getTransportManager().findTransport(Const.RESTFUL)</code></li>
<li>测试代码可能使用 <code>CseContext.getInstance().getConsumerProviderManager().setTransport(microserviceName, transport)</code> , 修改
<code>ArchaiusUtils.setProperty("servicecomb.references.transport." + microserviceName, transport);</code></li>
</ul>
<h2 id="_3">已知缺陷</h2>
<ul>
<li>2.0.0 版本将 <code>servicecomb.service.registry.registerUrlPrefix</code> 弄丢了。 这个配置项是为一个特殊场景服务的的,
默认值为 false。 在使用 WEB 容器(比如 tomcat) java-chassis的场景下, 如果设置了 context-path, 使用 java-chassis
提供的 RestTemplate 访问服务的时候, 不需要指定 context-path,以保证用户不用关注微服务的部署方式,提供了很大的便利。
但是有些用户的代码是历史遗留代码改造过来的,期望 URL 包含完整的 context-path。 使用 2.0.0 版本如果存在这个特殊要
求, 程序会运行错误,访问接口提示 NOT FOUND。这个问题在 2.0.1 修复。 </li>
</ul>
</div>
</div><footer>
<hr/>
<div role="contentinfo">
<!-- Copyright etc -->
</div>
Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<div class="rst-versions" role="note" aria-label="Versions">
<span class="rst-current-version" data-toggle="rst-current-version">
</span>
</div>
<script>var base_url = '../..';</script>
<script src="../../js/theme_extra.js" defer></script>
<script src="../../js/theme.js" defer></script>
<script src="../../search/main.js" defer></script>
<script defer>
window.onload = function () {
SphinxRtdTheme.Navigation.enable(true);
};
</script>
</body>
</html>