This is an automated email from the ASF dual-hosted git repository. ningjiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/servicecomb-website.git
commit 8618ac227746f3cfa78a33f13792f105e56a904e Author: chinx <[email protected]> AuthorDate: Mon Nov 18 10:15:52 2019 +0800 Add the Getting Started for servicecenter, tookit, syncer to the website --- _config.yml | 28 ++ _data/navigation.yml | 28 +- _docs/cn/getting-started.md | 27 ++ _docs/cn/quick-start.md | 2 +- _pages/cn/home.md | 2 +- _service-center/cn/install.md | 136 +++++++ _service-center/cn/registration-discovery.md | 112 ++++++ _syncer/cn/multi-servicecenters.md | 259 ++++++++++++ _syncer/cn/quick-start.md | 82 ++++ _toolkit/cn/oas-validator.md | 437 +++++++++++++++++++++ _toolkit/cn/quick-start.md | 242 ++++++++++++ .../images/docs/service-center/config-host-ip.jpg | Bin 0 -> 160416 bytes .../docs/service-center/registration&discovery.png | Bin 0 -> 17293 bytes .../docs/service-center/service-center-why.png | Bin 0 -> 32672 bytes .../images/docs/service-center/service-center.jpg | Bin 0 -> 66059 bytes assets/images/docs/syncer/account-server-reply.jpg | Bin 0 -> 198944 bytes .../docs/syncer/eureka-account-server-success.jpg | Bin 0 -> 90866 bytes .../images/docs/syncer/eureka-server-has-all.jpg | Bin 0 -> 75367 bytes .../images/docs/syncer/eureka-server-success.jpg | Bin 0 -> 63247 bytes .../docs/syncer/hello-server-discovery-success.jpg | Bin 0 -> 126329 bytes assets/images/docs/syncer/hello-server-result.jpg | Bin 0 -> 44530 bytes assets/images/docs/syncer/multi-servicecenters.png | Bin 0 -> 40141 bytes .../syncer/service-center-hello-server-success.jpg | Bin 0 -> 72537 bytes .../docs/syncer/service-center-server-has-all.jpg | Bin 0 -> 63431 bytes .../docs/syncer/service-center-server-success.jpg | Bin 0 -> 66059 bytes 25 files changed, 1348 insertions(+), 7 deletions(-) diff --git a/_config.yml b/_config.yml index 76b26f3..74fe3f3 100644 --- a/_config.yml +++ b/_config.yml @@ -120,6 +120,9 @@ include: - _users - _faqs - _release + - _service-center + - _toolkit + - _syncer exclude: - "*.sublime-project" - "*.sublime-workspace" @@ -264,6 +267,31 @@ defaults: comments: false sidebar: nav: "faqs" + - scope: + path: "_service-center" + type: pages + values: + layout: single + author_profile: false + sidebar: + nav: "docs" + - scope: + path: "_toolkit" + type: pages + values: + layout: single + author_profile: false + sidebar: + nav: "docs" + + - scope: + path: "_syncer" + type: pages + values: + layout: single + author_profile: false + sidebar: + nav: "docs" # Sass/SCSS sass: diff --git a/_data/navigation.yml b/_data/navigation.yml index 5d6e8a9..2bdf117 100755 --- a/_data/navigation.yml +++ b/_data/navigation.yml @@ -184,7 +184,7 @@ t: group: "users" children: - title: "入门指南" - url: /cn/docs/quick-start/ + url: /cn/docs/getting-started/ group: "users" - title: "用户手册" url: /cn/docs/users/ @@ -206,8 +206,15 @@ t: group: "release" docs: - - title: "基于java微服务SDK开发微服务应用" - url: /cn/docs/quick-start/ + - title: "入门指南" + url: /cn/docs/getting-started/ + - title: "服务中心 Service-Center" + children: + - title: "环境安装" + url: /cn/docs/service-center/install/ + - title: "服务注册发现" + url: /cn/docs/service-center/registration-discovery/ + - title: "基于java微服务SDK开发微服务应用" children: - title: "入门指南" url: /cn/docs/quick-start/ @@ -223,8 +230,7 @@ t: url: /cn/docs/quick-start-advance/service-management/ - title: "分布式调用链追踪" url: /cn/docs/quick-start-advance/distributed-tracing/ - - title: "使用mersher接入servicecomb微服务体系" - url: /cn/docs/mersher-quick-start/ + - title: "使用mersher接入servicecomb微服务体系" children: - title: "入门指南" url: /cn/docs/mersher-quick-start/ @@ -238,6 +244,18 @@ t: url: /cn/docs/mersher-quick-start-advance/mersher-service-management/ - title: "mersher分布式调用链追踪" url: /cn/docs/mersher-quick-start-advance/mersher-distributed-tracing/ + - title: "一键微服务开发工具 Toolkit" + children: + - title: "入门指南" + url: /cn/docs/toolkit/quick-start/ + - title: "OpenAPI V3 Spec校验工具" + url: /cn/docs/toolkit/oas-validator/ + - title: "异构、多服务中心通讯 Syncer" + children: + - title: "入门指南" + url: /cn/docs/syncer/quick-start/ + - title: "异构服务中心通讯" + url: /cn/docs/syncer/multi-servicecenters/ users: - title: Java-chassis用户手册 diff --git a/_docs/cn/getting-started.md b/_docs/cn/getting-started.md new file mode 100644 index 0000000..b1d398f --- /dev/null +++ b/_docs/cn/getting-started.md @@ -0,0 +1,27 @@ +--- +title: "入门指南" +lang: cn +ref: getting-started +permalink: /cn/docs/getting-started/ +excerpt: "ServiceComb入门指南" +last_modified_at: 2019-11-12T00:50:43-55:00 +--- + +{% include toc %} +## 入门 +Apache ServiceComb 是一个微服务的开源解决方案。其包含多个组件,通过组件之间的搭配,可以灵活的应对不同的场景。本指南可以帮助你快速的使用 Apache ServiceComb,针对初次使用的用户,这是开始尝试的最佳入口。 +1. 下载 [ServiceComb 发布版本](/cn/release/)组件 +2. [服务中心环境安装](/cn/docs/service-center/install/) +3. [服务注册与发现](/cn/docs/service-center/registration-discovery/) +4. 相应开发语言的快速入门说明进行使用 +- [Java微服务开发框架 Java-Chassis](/cn/docs/quick-start/) +- [多语言运行环境 Mersher](/cn/docs/mersher-quick-start/) +5. 如果项目涉及多方协作、或遗留系统希望进行微服务化转型 +[一键微服务开发工具 Toolkit](/cn/docs/toolkit/quick-start/) + +## 进阶 +1. [异构、多服务中心通讯 Syncer](/cn/docs/syncer/quick-start/) + +## 更多 +完成上面的内容后,可以通过各个服务用户手册进行深入学习: +[ServiceComb 用户手册](/cn/docs/users/) diff --git a/_docs/cn/quick-start.md b/_docs/cn/quick-start.md index f0e515b..b80b49f 100755 --- a/_docs/cn/quick-start.md +++ b/_docs/cn/quick-start.md @@ -1,5 +1,5 @@ --- -title: "入门指南" +title: "Java-Chassis 入门指南" lang: cn ref: quick-start permalink: /cn/docs/quick-start/ diff --git a/_pages/cn/home.md b/_pages/cn/home.md index 17fe195..5f22f88 100755 --- a/_pages/cn/home.md +++ b/_pages/cn/home.md @@ -12,7 +12,7 @@ excerpt: '开箱即用、高性能、兼容流行生态、支持多语言的一 <a href="/cn/release" class="home-button btn--info">下载</a> </div> <div class="button-group def-inline-block"> - <a href="/cn/docs/quick-start/" class="home-button btn--info">开始</a> + <a href="/cn/docs/getting-started/" class="home-button btn--info">开始</a> </div>' intro: diff --git a/_service-center/cn/install.md b/_service-center/cn/install.md new file mode 100644 index 0000000..3ec2440 --- /dev/null +++ b/_service-center/cn/install.md @@ -0,0 +1,136 @@ +--- +title: "ServiceCenter 安装" +lang: cn +ref: install +permalink: /cn/docs/service-center/install/ +excerpt: "了解如何运行ServiceComb的服务中心" +last_modified_at: 2019-11-12T00:50:43-55:00 +--- + +{% include toc %} +## 服务中心 ServiceCenter +ServiceCenter是一个服务注册中心。 服务提供者可以将自身的实例信息注册到 ServiceCenter,以供服务消费者发现并使用它。 + +## 版本发布包启动 +1. 下载 [最新版本的Service-Center](/cn/release/service-center-downloads/) + 此处使用了 apache-servicecomb-service-center-1.3.0-linux-amd64.tar.gz 包做介绍,实际操作时请根据系统环境从下载页面选取最新版本 +2. 启动服务 + ```bash + # 解压tar包 + $ tar -zxvf apache-servicecomb-service-center-1.3.0-linux-amd64.tar.gz + + # 启动servicecenter服务 + $ cd apache-servicecomb-service-center-1.3.0-linux-amd64/ + $ ./start-service-center.sh + ``` +3. 查看服务状态 + ```bash + # 查看进程状态 + $ ps -ef | grep service-center + root 27048 1 2 14:38 pts/2 00:00:00 ./service-center + root 27164 22742 0 14:38 pts/2 00:00:00 grep --color=auto service-center + + # 查看端口监听 + $ netstat -apn | grep :30100 + tcp 0 0 127.0.0.1:30100 0.0.0.0:* LISTEN 27048/service-cente + + # curl命令调用接口 + $ curl http://127.0.0.1:30100 + {"_links":{"pb:latest-pact-versions":{"href":"http://127.0.0.1:30100/pacts/latest","title":"Latest pact versions"},"pb:latest-provider-pacts":{"href":"http://127.0.0.1:30100/pacts/provider/{provider}/latest","title":"Latest pacts by provider","templated":true},"pb:latest-provider-pacts-with-tag":{"href":"http://127.0.0.1:30100/pacts/provider/{provider}/latest/{tag}","title":"Latest pacts by provider with a specified tag","templated":true},"pb:pacticipants":{"href":"http://127.0.0.1:30 [...] + + # 返回如上json串即为启动成功 + ``` +4. 启动前端页面并查看状态 + ```bash + $ ./start-frontend.sh + $ ps -ef | grep frontend + root 1875 32096 0 17:43 pts/6 00:00:00 grep --color=auto frontend + root 3020 1 0 Nov05 ? 00:00:23 ./frontend + + # 查看端口监听 + $ netstat -apn | grep :30103 + tcp 0 0 127.0.0.1:30103 0.0.0.0:* LISTEN 3020/frontend + ``` +5. 浏览器访问前端页面 http://127.0.0.1:30103,查看服务中心实例(出现以下页面即为成功) +  + **_注:_** + - 若 frontend 服务不是本地启动,则无法通过 http://127.0.0.1:30103 访问;需要修改配置文件中"frontend_host_ip"为主机IP,并使用 http://{ip}:30103 的形式进行访问 + - 若 Service-Center 需要对外提供服务,需要修改"httpaddr",外部应用使用 http://{ip}:30100 进行访问 + 如图: +  + +## Docker镜像启动 +1. 下载并运行镜像 + ```bash + # 下载镜像 + $ docker pull servicecomb/service-center + # 启动容器 + $ docker run -d -p 30100:30100 servicecomb/service-center + ``` +2. 查看镜像状态和监听端口 + ```bash + # 查看端口监听 + $ docker ps | grep service-center + 0733021cd96d servicecomb/service-center "/opt/service-cent..." 3 minutes ago Up 3 minutes 0.0.0.0:30100->30100/tcp gallant_varahamihira + ``` + +## Kubernetes 部署 +1. 配置部署脚本 + ```bash + $ cat <<EOF >> ./service-center.yaml + apiVersion: v1 + kind: Service + metadata: + name: servicecenter + labels: + app: servicecenter + spec: + ports: + - port: 30100 + name: http + selector: + app: servicecenter + --- + apiVersion: extensions/v1beta1 + kind: Deployment + metadata: + name: servicecenter + spec: + replicas: 1 + template: + metadata: + labels: + app: servicecenter + version: v1 + spec: + containers: + - name: servicecenter + image: servicecomb/service-center:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 30100 + EOF + ``` +2. Kubernetes中部署 + ```bash + # 创建 namespace "servicecomb" + $ kubectl create namespace servicecomb + + # 部署 service-center + $ kubectl -n servicecomb create -f service-center.yaml + ``` +3. 查看Pod状态和service端口 + ```bash + # 查看 pod 启动状态 + $ kubectl -n servicecomb get pod + NAME READY STATUS RESTARTS AGE + servicecenter-7d964b7644-h6f4s 1/1 Running 0 72s + + # 获取 service 监听 + $ kubectl -n servicecomb get service + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + servicecenter ClusterIP 10.104.241.163 <none> 30100/TCP 118s + + $ curl http://10.104.241.163:30100 + ... + ``` diff --git a/_service-center/cn/registration-discovery.md b/_service-center/cn/registration-discovery.md new file mode 100644 index 0000000..a231892 --- /dev/null +++ b/_service-center/cn/registration-discovery.md @@ -0,0 +1,112 @@ +--- +title: "服务注册发现" +lang: cn +ref: registration-discovery +permalink: /cn/docs/service-center/registration-discovery/ +excerpt: "服务中心注册发现" +last_modified_at: 2019-11-12T00:50:43-55:00 +--- + +{% include toc %} +## 服务注册发现 + 在微服务架构中,一个应用由一组职责单一化的服务组成,各个服务被动态的部署到不同的节点。面对这样一组服务,应该如何去管理服务之间的依赖关系呢? +  + 服务注册中心的出现正是为了解决这样的问题,它提供的注册机制,允许服务提供者将自己的信息登记到中心;提供的发现机制,供服务消费者从中心查找服务提供者信息。 + 服务注册中心有以下几个优点: + - 1 解耦服务提供者与服务消费者,服务消费者不需要硬编码服务提供者地址; + - 2 服务动态发现及可伸缩能力,服务提供者实例的动态增减能通过注册中心动态推送到服务消费者端; + - 3 通过注册中心可以动态的监控服务运行质量及服务依赖,为服务提供服务治理能力。 + +## 注册发现流程 +  + 如上图,Service-Center中服务发现流程大致有以下几个步骤: + - 1 服务提供者向Service-Center注册服务信息 + - 2 服务提供者发送心跳,维持在Service-Center中的“UP”状态 + - 3 服务消费者向Service-Center注册服务信息 + - 4 服务消费者从Service-Center发现服务提供者信息 + - 5 服务消费者向服务提供者发送请求,并获取通讯结果 + +Service-Center注册发现接口基于RESTful标准实现,不受开发语言限制,接口定义请参考[官方API文档](https://rawcdn.githack.com/ServiceComb/service-center/master/docs/api-docs.html) + +## 注册发现初窥 +以下将通过 curl 命令模拟 Service-center 中的服务注册与发现,以便于了解其流程。 +1. provider 服务注册 + ```bash + $ curl -X POST \ + http://127.0.0.1:30100/registry/v3/microservices \ + -H 'content-type: application/json' \ + -H 'x-domain-name: default' \ + -d '{ + "service": + { + "appId": "default", + "serviceName": "ProviderDemoService", + "version":"1.0.0" + } + }' + {"serviceId":"fa82132706a6b75a13393d8cf48800f9689b2603"} + ``` +2. provider 实例注册 +根据上一步返回的的 serviceId,注册微服务实例 + ```bash + $ curl -X POST \ + http://127.0.0.1:30100/registry/v3/microservices/fa82132706a6b75a13393d8cf48800f9689b2603/instances \ + -H 'content-type: application/json' \ + -H 'x-domain-name: default' \ + -d '{ + "instance": + { + "hostName":"provider-demo", + "endpoints": [ + "rest://127.0.0.1:8080" + ] + } + }' + {"instanceId":"6e160fb0196e11e9b8b50242ac110005"} + ``` +3. consumer 服务注册 + ```bash + $ curl -X POST \ + http://127.0.0.1:30100/registry/v3/microservices \ + -H 'content-type: application/json' \ + -H 'x-domain-name: default' \ + -d '{ + "service": + { + "appId": "default", + "serviceName": "ConsumerDemoService", + "version":"1.0.0" + } + }' + {"serviceId":"d08d29edbeaa372c5be88407aa9adb00b4cb6099"} + ``` +4. 服务发现 +根据 provider 服务名称和版本规则、以及 consumer 服务 ID 进行 provider 服务实例发现 + ```bash + $ curl -X GET \ + 'http://127.0.0.1:30100/registry/v3/instances?appId=default&serviceName=ProviderDemoService&version=latest' \ + -H 'content-type: application/json' \ + -H 'x-consumerid: d08d29edbeaa372c5be88407aa9adb00b4cb6099' \ + -H 'x-domain-name: default' + { + "instances": [ + { + "instanceId": "c23da577197111e9b8b50242ac110005", + "serviceId": "fa82132706a6b75a13393d8cf48800f9689b2603", + "endpoints": [ + "rest://127.0.0.1:8080" + ], + "hostName": "provider-demo", + "status": "UP", + "healthCheck": { + "mode": "push", + "interval": 30, + "times": 3 + }, + "timestamp": "1547631199", + "modTimestamp": "1547631199", + "version": "1.0.0" + } + ] + } + ``` diff --git a/_syncer/cn/multi-servicecenters.md b/_syncer/cn/multi-servicecenters.md new file mode 100644 index 0000000..244540e --- /dev/null +++ b/_syncer/cn/multi-servicecenters.md @@ -0,0 +1,259 @@ +--- +title: "异构服务中心通讯" +lang: cn +ref: install +permalink: /cn/docs/syncer/multi-servicecenters/ +excerpt: "了解如何使用异构、多服务中心通讯工具" +last_modified_at: 2019-11-12T00:50:43-55:00 +--- + +{% include toc %} +## ServiceCenter和Eureka异构服务中心通讯 + +本案例模拟了异构服务中心之间的通讯场景,包括以下四个部分: +- EurekaServer: Eureka服务中心 +- AccountServer:注册到Eureka的账号服务 +- Servicecomb-ServiceCenter:Servicecomb-ServiceCenter服务中心 +- HelloServer:注册到Servicecomb-ServiceCenter,需要使用AccountServer的服务 + +在传统的环境中,不同服务中心之间的实例是不能互相发现并访问的。当我们使用Syncer后,这将很容易实现。如下图: + + +### 运行环境 + 1. 2台linux机器: (假设为:10.0.0.10 和 10.0.0.11) + 2. [JDK 1.8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) + 3. [Maven 3.x](https://maven.apache.org/install.html) + 4. [Go 1.11.4](https://golang.google.cn/dl/) + 5. [ServiceComb Service-Center 1.3.0](/cn/release/service-center-downloads/) + +### 步骤1:启动Eureka环境和服务 +机器: 10.0.0.10 +#### 1. 编译项目 +```bash +# 记录当前目录 +$ project_dir=`pwd` + +# 下载源码 +$ git clone https://github.com/apache/servicecomb-service-center.git + +# 编译 Syncer +$ cd servicecomb-service-center/syncer +$ GO111MODULE=on go build + +# 编译 EurekaServer 和 AccountServer +$ cd samples/multi-servicecenters/eureka +$ mvn clean install +``` +#### 2. 启动EurekaServer: +- 修改启动配置 + 文件位置:${project_dir}/servicecomb-service-center/syncer/samples/multi-servicecenters/eureka/eureka-server/src/main/resources/application.yaml +```yml +spring: + application: + name: eureka-server +server: + port : 8761 +# servlet: +# context-path: /eureka +eureka: + instance: + hostname : 10.0.0.10 + client: + registerWithEureka : false + fetchRegistry : false + serviceUrl: + defaultZone : http://${eureka.instance.hostname}:${server.port}/eureka/ +management: + endpoints: + web: + exposure: + include: "*" +``` + +- 启动服务 +```bash +# 启动 EurekaServer +$ cd ${project_dir}/servicecomb-service-center/syncer/samples/multi-servicecenters/eureka/eureka-server/ +$ nohup mvn spring-boot:run & >> eureka-server.log 2>&1 & +``` +浏览器打开http://10.0.0.10:8761,若出现如下页面,则启动成功 + + +#### 3. 启动AccountServer +- 修改启动配置 + 文件位置:${project_dir}/servicecomb-service-center/syncer/samples/multi-servicecenters/eureka/account-server/src/main/resources/application.yaml +```yml +spring: + application: + name: account-server +server: + port: 8090 +eureka: + instance: + hostname: 10.0.0.10 + client: + service-url: + defaultZone: http://${eureka.instance.hostname}:8761/eureka/ +management: + endpoints: + web: + exposure: + include: "*" +``` +- 启动服务 +```bash +#启动 AccountServer +$ cd ${project_dir}/servicecomb-service-center/syncer/samples/multi-servicecenters/eureka/account-server +$ mvn spring-boot:run + +# 出现如下字样则为成功 +2019-09-19 17:20:35.534 INFO 20890 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8090 (http) with context path '' +2019-09-19 17:20:35.548 INFO 20890 --- [ main] .s.c.n.e.s.EurekaAutoServiceRegistration : Updating port to 8090 +2019-09-19 17:20:35.551 INFO 20890 --- [ main] o.a.s.s.account.AccountApplication : Started AccountApplication in 3.92 seconds (JVM running for 6.754) +2019-09-19 17:20:35.617 INFO 20890 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_ACCOUNT-SERVER/10.0.0.10:account-server:8090 - registration status: 204 +``` +此时打开http://10.0.0.10:8761,可以看到AccountServer已经注册成功 + + +#### 4. 启动Syncer +```bash +$ cd ${project_dir}/servicecomb-service-center/syncer +$ ./syncer daemon --sc-addr http://10.0.0.10:8761/eureka --bind-addr 10.0.0.10:30190 --rpc-addr 10.0.0.10:30191 --sc-plugin=eureka + +# 出现如下字样则为成功 +2019-09-19T17:28:28.809+0800 INFO etcd/agent.go:55 start etcd success +2019-09-19T17:28:28.809+0800 INFO grpc/server.go:94 start grpc success +2019-09-19T17:28:28.809+0800 DEBUG server/handler.go:39 is leader: true +2019-09-19T17:28:28.809+0800 DEBUG server/handler.go:43 Handle Tick +``` + +### 步骤2:启动Servicecenter环境和服务 +机器: 10.0.0.11 +#### 1. 编译项目 +```bash +# 记录当前目录 +$ project_dir=`pwd` + +# 下载源码 +$ git clone https://github.com/apache/servicecomb-service-center.git + +# 编译 Syncer +$ cd servicecomb-service-center/syncer +$ GO111MODULE=on go build + +# 编译 HelloServer +$ cd samples/multi-servicecenters/servicecenter/hello-server/ +$ GO111MODULE=on go build +``` +#### 2. 启动Servicecenter +- 下载ServiceCenter项目 +```bash +$ cd ${project_dir} + +# 下载 ServiceCenter 1.2.0版本包 +$ curl -O https://mirrors.tuna.tsinghua.edu.cn/apache/servicecomb/servicecomb-service-center/1.2.0/apache-servicecomb-service-center-1.2.0-linux-amd64.tar.gz +$ tar -zxvf apache-servicecomb-service-center-1.2.0-linux-amd64.tar.gz +``` + +- 修改启动配置: + 文件位置:${project_dir}/apache-servicecomb-service-center-1.2.0-linux-amd64/conf/app.conf +```conf +frontend_host_ip = 10.0.0.11 +frontend_host_port = 30103 + +################################################################### +# sever options +################################################################### +# if you want to listen at ipv6 address, then set the httpaddr value like: +# httpaddr = 2400:A480:AAAA:200::159 (global scope) +# httpaddr = fe80::f816:3eff:fe17:c38b%eth0 (link-local scope) +httpaddr = 10.0.0.11 +httpport = 30100 +# ...以下省略... +``` + +- 启动 ServiceCenter 和 Frontend +```bash +$ cd ${project_dir}/apache-servicecomb-service-center-1.2.0-linux-amd64 + +# 启动 ServiceCenter +$ ./start-service-center.sh + +# 启动 前端页面 Frontend +$ ./start-frontend.sh +``` +浏览器打开http://10.0.0.11:30103,若出现如下页面,则启动成功 + + +#### 3. 启动HelloServer +- 修改启动配置: + 文件位置:${project_dir}/servicecomb-service-center/syncer/samples/multi-servicecenters/servicecenter/hello-server/conf/microservice.yaml +```yml +service: # 微服务配置 + appId: eureka # eureka 中同步的实例appID均为:eureka + name: hello-server + version: 0.0.1 + instance: # 实例信息 + protocol: rest + listenAddress: 10.0.0.11:8091 #实例监听地址 +provider: # 服务端信息 + appId: eureka + name: account-server + version: 0.0.1 +registry: + address: http://10.0.0.11:30100 +``` + +- 启动服务 +```bash +$ cd ${project_dir}/servicecomb-service-center/syncer/samples/multi-servicecenters/servicecenter/hello-server +$ ./hello-server +2019-09-19T18:37:50.645+0800 DEBUG servicecenter/servicecenter.go:163 send heartbeat success +2019-09-19T18:37:50.645+0800 WARN servicecenter/servicecenter.go:85 discovery provider failed, appID = eureka, name = account-server, version = 0.0.1 +2019-09-19T18:37:50.645+0800 INFO servicecenter/servicecenter.go:87 waiting for retry +``` +此时打开http://10.0.0.11:30103,可以看到HelloServer已经注册成功 + +但由于无法发现属于Eureka服务中心的AccountServer实例,HelloServer处于重试状态 +(==注:重试次数为3次,每次间隔30秒,所以我们需要在90秒内完成后面的操作==) + +#### 4.启动Syncer +```bash +$ cd ${project_dir}/servicecomb-service-center/syncer +$ ./syncer daemon --sc-addr http://10.0.0.11:30100 --bind-addr 10.0.0.11:30190 --rpc-addr 10.0.0.11:30191 --sc-plugin=servicecenter --join-addr 10.0.0.10:30190 + +# 出现以下内容则为Syncer成功启动,并同步了对方的实例 +2019-09-19T18:44:35.536+0800 DEBUG server/handler.go:62 is leader: true +2019-09-19T18:44:35.536+0800 DEBUG server/handler.go:79 Receive serf user event +2019-09-19T18:44:35.536+0800 DEBUG serf/agent.go:130 member = xxxxxa, groupName = 0204d59328090c2f4449a088d4e0f1d8 +2019-09-19T18:44:35.536+0800 DEBUG serf/agent.go:130 member = xxxxxb, groupName = 34f53a9520a11c01f02f58f733e856b3 +2019-09-19T18:44:35.536+0800 DEBUG server/handler.go:97 Going to pull data from xxxxxb 10.0.0.10:30191 +2019-09-19T18:44:35.536+0800 INFO grpc/client.go:76 Create new grpc connection to 10.0.0.10:30191 +2019-09-19T18:44:35.538+0800 DEBUG servicecenter/servicecenter.go:87 create service success orgServiceID= account-server, curServiceID = 80784229255ec96d90353e3c041bdf3586fdbbae +2019-09-19T18:44:35.538+0800 DEBUG servicecenter/servicecenter.go:90 trying to do registration of instance, instanceID = 10.0.0.10:account-server:8090 +2019-09-19T18:44:35.540+0800 DEBUG servicecenter/sync.go:63 Registered instance successful, instanceID = 78bca3e2daca11e99638fa163eca30e0 +``` + +### 步骤3:结果验证 +1. 此时的HelloServer获取实例成功,并调用了AccountServer的CheckHealth接口 + + +2. 分别打开Euraka和ServiceCenter的网页,两个服务中心里均包含了所有的实例信息 + + +3. curl命令调用HelloServer的Login接口 +```bash +$ curl -X POST \ +http://192.168.88.75:8091/login \ +-H 'Content-Type: application/json' \ +-d '{ + "user":"Jack", + "password":"123456" +}' +welcome Jack +``` +HelloServer与AccountServer分别会打印如下的信息 +AccountServer + +HelloServer + diff --git a/_syncer/cn/quick-start.md b/_syncer/cn/quick-start.md new file mode 100644 index 0000000..3297091 --- /dev/null +++ b/_syncer/cn/quick-start.md @@ -0,0 +1,82 @@ +--- +title: "Syncer 快速入门" +lang: cn +ref: install +permalink: /cn/docs/syncer/quick-start/ +excerpt: "了解如何使用异构、多服务中心通讯工具" +last_modified_at: 2019-11-12T00:50:43-55:00 +--- + +{% include toc %} +## 异构、多服务中心通讯 Syncer +Syncer是一个多服务中心的同步工具,专为大型微服务架构设计,用于在网络互通的情况下,不同技术栈服务中心、跨区域的实例同步,未来将对跨网络、跨云等场景提供支持。 + +## 快速入门 +1. 获取并启动服务中心 + +以Service-center为例,详细参见:[ServiceCenter 环境安装](/cn/docs/service-center/install/) + +2. 下载并解压[ServiceCenter发布包(>=1.3.0)](/cn/release/service-center-downloads/) +```bash +# 解压tar包 +$ tar -zxvf apache-servicecomb-service-center-1.3.0-linux-amd64.tar.gz +$ cd apache-servicecomb-service-center-1.3.0-linux-amd64/ +``` + +3. 启动ServiceCenter Syncer +### 命令行参数说明: +- node: syncer名称,集群内成员名必须唯一。 +- sc-addr: 服务注册中心地址。支持集群模式,多个地址间使用英文半角","隔开。 +- bind-addr: Gossip协议通讯地址,用于Syncer间的消息传递、集群管理 +- rpc-addr: RPC数据传输地址,用于Syncer间的数据同步 +- join-addr: 指向目标Syncer的BindAddr,当前Syncer将通过该地址加入网络 +- mode: 运行模式配置,当前支持两种模式,单实例模式“single”和集群模式“cluster”, cluster模式下每个syncer拥有三个实例 +- cluster-name: 当mode为”cluster“时,Syncer集群的名字 +- cluster-port: 当mode为“cluster”时,Syncer三个实例之间一致性协商的端口 + + +假设有2个服务中心,每个服务中心都有一个用于微服务发现和注册的服务中心集群,如下所示: + +| Service center | Local address | +| :--------------------: | :-----------: | +| http://10.0.0.10:30100 | 10.0.0.10 | +| http://10.0.0.11:30100 | 10.0.0.11 | + +### 单例模式(Single Mode) + +分别在两个机器上启动两个syncer来完成这两个服务中心之间的微服务数据同步 + +- 在10.0.0.10的机器上执行以下命令启动Syncer + +```bash +$ ./syncer daemon --sc-addr http://10.0.0.10:30100 --bind-addr 10.0.0.10:30190 --rpc-addr 10.0.0.10:30191 +``` + +- 在10.0.0.11的机器上执行以下命令启动Syncer,并加入10.0.0.10的gossip池 + +```bash +$ ./syncer daemon --sc-addr http://10.0.0.11:30100 --bind-addr 10.0.0.11:30190 --rpc-addr 10.0.0.11:30191 --join-addr 10.0.0.10:30191 +``` + +### 集群模式(Cluster Mode) + +分别在两个机器上启动两个syncer集群来完成这两个服务中心之间的微服务数据同步 + +- 在10.0.0.10的机器上启动syncer集群 + +```bash +$ ./syncer daemon --sc-addr http://10.0.0.10:30100 --bind-addr 10.0.0.10:30190 --rpc-addr 10.0.0.10:30191 --mode cluster --node syncer011 --cluster-port 30201 --join-addr 10.0.0.10:30190 +$ ./syncer daemon --sc-addr http://10.0.0.10:30100 --bind-addr 10.0.0.10:30290 --rpc-addr 10.0.0.10:30291 --mode cluster --node syncer012 --cluster-port 30202 --join-addr 10.0.0.10:30190 +$ ./syncer daemon --sc-addr http://10.0.0.10:30100 --bind-addr 10.0.0.10:30390 --rpc-addr 10.0.0.10:30391 --mode cluster --node syncer013 --cluster-port 30203 --join-addr 10.0.0.10:30190 +``` + +- 在10.0.0.11机器上启动syncer集群 + +```bash +$ ./syncer daemon --sc-addr http://10.0.0.11:30100 --bind-addr 10.0.0.11:30190 --rpc-addr 10.0.0.11:30191 --mode cluster --node syncer021 --cluster-port 30201 --join-addr 10.0.0.10:30190 +$ ./syncer daemon --sc-addr http://10.0.0.11:30100 --bind-addr 10.0.0.11:30290 --rpc-addr 10.0.0.11:30291 --mode cluster --node syncer022 --cluster-port 30202 --join-addr 10.0.0.10:30190 +$ ./syncer daemon --sc-addr http://10.0.0.11:30100 --bind-addr 10.0.0.11:30390 --rpc-addr 10.0.0.11:30391 --mode cluster --node syncer023 --cluster-port 30203 --join-addr 10.0.0.10:30190 +``` + +### 结果验证 +将微服务实例注册到其中一个ServiceCener后30秒,可以从每个ServiceCenter获取有关该实例的信息。 diff --git a/_toolkit/cn/oas-validator.md b/_toolkit/cn/oas-validator.md new file mode 100644 index 0000000..1e40621 --- /dev/null +++ b/_toolkit/cn/oas-validator.md @@ -0,0 +1,437 @@ +--- +title: "OpenAPI V3 Spec校验工具" +lang: cn +ref: install +permalink: /cn/docs/toolkit/oas-validator/ +excerpt: "了解如何使用OpenAPI V3 Spec校验工具" +last_modified_at: 2019-11-12T00:50:43-55:00 +--- + +{% include toc %} +## 项目结构 + +* oas-validator-core,核心API及骨架实现 +* oas-validator-core-spring,骨架的Spring Boot Starter +* oas-validator-test,核心API的测试帮助类 +* oas-validator-compliance,合规性校验实现 +* oas-validator-compliance-spring,合规性校验的Spring Boot Starter +* oas-validator-compatibility,兼容性校验实现 +* oas-validator-compatibility-spring,兼容性校验实现的Spring Boot Starter +* oas-validator-web,校验工具的操作UI + +## 合规性校验 + +OAS必须符合[OAS 3.0.2规范][openapi-3.0.2](比如属性的名称、REQUIED要求)。除此之外则是我们自己的定义的合规性检查。 + +### 一些字符串匹配规则 + +* <a name="lower-camel-case"></a>Lower Camel Case:首字母小写的驼峰,对应的正则`^[a-z]+((\d)|([A-Z0-9][a-z0-9]+))*([A-Z])?$` +* <a name="upper-camel-case"></a>Upper Camel Case:首字母大写的驼峰,对应的正则`^[A-Z]([a-z0-9]+[A-Z]?)*$` +* <a name="upper-hyphen-case"></a>Upper Hyphen Case:单词首字母大写,多个单词用`-`连接,比如`Content-Type`、`Accept`、`X-Rate-Limit-Limit`。对应的正则:`^([A-Z][a-z0-9]*-)*([A-Z][a-z0-9]*)$` + +### OpenAPI Object [doc][spec-openapi] + +<a name="openapi-compliance"></a> + +* `openapi`属性必须为3.0.x且>=3.0.2 +* `info`属性见[Info Object合规性检查](#info-compliance) +* `paths`属性,必须提供见[Paths Object合规性检查](#paths-compliance) +* `components`属性见[Components Object合规性检查](#components-compliance) +* `tags`属性,至少提供一个[Tag Object][spec-tag] + * 见[Tag Object合规性检查](#tag-compliance) +* `security`属性,不允许提供 + +### Info Object [doc][spec-info] + +<a name="info-compliance"></a> + +* `description`属性,必须填写 + +### Tag Object [doc][spec-tag] + +<a name="tag-compliance"></a> + +- `name`属性,必须是[Upper Camel Case](#upper-camel-case) +- `description`属性,必须填写 +- 不得存在[Operation Object][spec-operation]没有引用过的tag + +### Paths Object [doc][spec-paths] + +<a name="paths-compliance"></a> + +* path必须是[Lower Camel Case](#lower-camel-case),包括[Path Templating][spec-path-templating]中的变量 + * 见[Path Item Object合规性检查](#path-item-compliance) + +### Path Item Object [doc][spec-path-item] + +<a name="path-item-compliance"></a> + +* `get/post/put/delete/...`属性,见[Operation Object合规性检查](operation-compliance) +* `parameters`属性,见[Parameter Object合规性检查](#parameter-compliance) + +### Operation Object [doc][spec-operation] + +<a name="operation-compliance"></a> + +* `summary`属性、必须填写 +* `operationId`属性,且[Lower Camel Case](#lower-camel-case) +* `parameters`属性,见[Parameter Object合规性检查](#parameter-compliance) +* `requestBody`属性,见[Request Body Object合规性检查](#request-body-compliance) +* `responses`属性,见[Responses Object合规性检查](#responses-compliance) +* `tags`属性,且只能写一个tag,且必须在[OpenAPI Object][spec-openapi] 的 `tags`属性里所定义的范围内 + +* `servers`属性,不允许提供 + +### Parameter Object [doc][spec-parameter] + +<a name="parameter-compliance"></a> + +* `description`属性,必须填写 +* `name`属性 + * 如果`in`为path、query、cookie,则那么必须是[Lower Camel Case](#lower-camel-case) + * 如果`in`为header,则那么必须是[Upper Hyphen Case](#upper-hyphen-case) +* `schema`属性,见[Schema Object合规性检查](#schema-compliance) +* `content`属性,见[Media Type Object合规性检查](#media-type-compliance) + +### Request Body Object [doc][spec-request-body] + +<a name="request-body-compliance"></a> + +* `description`属性,必须填写 +* `content`属性,见[Media Type Object合规性检查](#media-type-compliance) + +### Media Type Object [doc][spec-media-type] + +<a name="media-type-compliance"></a> + +* `schema`属性,必须填写。见[Schema Object合规性检查](#schema-compliance) +* `encoding`属性,见[Encoding Object合规性检查](#encoding-compliance) + +### Responses Object [doc][spec-responses] + +<a name="responses-compliance"></a> + +* 见[Response Object合规性检查](#response-compliance) + +### Response Object [doc][spec-response] + +<a name="response-compliance"></a> + +* `description`属性,必须填写 +* `headers`属性,name(`headers`的key)必须是[Upper Hyphen Case](#upper-hyphen-case) + * 见[Header Object合规性检查](#header-compliance) +* `content`属性,见[Media Type Object合规性检查](#media-type-compliance) + +### Schema Object [doc][spec-schema] + +<a name="schema-compliance"></a> + +* `title`属性,如果上级是[Schema Object][spec-schema]或[Components Object][spec-components],那么必须填写 +* `properties`属性,name(`properties`的key)必须是[Lower Camel Case](#lower-camel-case) + * Sub Schema见[Schema Object合规性检查](#schema-compliance) + +### Encoding Object [doc][spec-encoding] + +<a name="encoding-compliance"></a> + +* `headers`属性,name(`headers`的key)必须是[Upper Hyphen Case](#upper-hyphen-case) + * 见[Header Object合规性检查](#header-compliance) + +### Header Object [doc][spec-header] + +<a name="header-compliance"></a> + +* `description`属性,必须填写 +* `schema`属性,见[Schema Object合规性检查](#schema-compliance) +* `content`属性,见[Media Type Object合规性检查](#media-type-compliance) + +### Components Object [doc][spec-components] + +<a name="components-compliance"></a> + +* `schemas`属性,name必须是[Upper Camel Case](#upper-camel-case) + * 见[Schema Object合规性检查](#schema-compliance) +* `responses`属性,name必须是[Upper Camel Case](#upper-camel-case) + * 见[Response Object合规性检查](#response-compliance) +* `parameters`属性,name必须是[Upper Camel Case](#upper-camel-case) + * 见[Parameter Object合规性检查](#parameter-compliance) +* `examples`属性,name必须是[Upper Camel Case](#upper-camel-case) +* `requestBodies`属性,name必须是[Upper Camel Case](#upper-camel-case) + * 见[Request Body合规性检查](#request-body-compliance) +* `headers`属性,name必须是[Upper Hyphen Case](#upper-hyphen-case) + * 见[Header合规性检查](#header-compliance) +* `links`属性,name必须是[Upper Camel Case](#upper-camel-case) +* `callbacks`属性,name必须是[Upper Camel Case](#upper-camel-case) + +## 兼容性检查 + +对新旧两个版本的OAS做兼容性检查。 + +OAS可以使用[Reference Object][spec-reference]来描述Spec,两个不同的OAS会出现描述不同但语义相同的情况。比如下面的旧OAS没有使用[Reference Object][spec-reference],而新OAS则使用了的情况: + +旧OAS + +```yaml +openapi: "3.0.0" +info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT +servers: + - url: http://petstore.swagger.io/v1 +paths: + /pets: + post: + summary: List all pets + operationId: listPets + requestBody: + content: + application/json: + schema: + type: array + items: + type: object + properties: + Foo: + type: string + responses: + '200': + description: A paged array of pets +``` + +新OAS + +```yaml +paths: + /pets: + post: + operationId: listPets + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Foo' + responses: + '200': + description: A paged array of pets +components: + schemas: + Foo: + type: array + items: + type: object + properties: + Foo: + type: string +``` + +因此在检查兼容性的时候会将新旧OAS的[Reference Object][spec-reference]做解析,然后再检查,下面是一段[swagger-parser][swagger-parser]的例子: + +```java +OpenAPIV3Parser parser = new OpenAPIV3Parser(); + +ParseOptions parseOptions = new ParseOptions(); +parseOptions.setResolve(true); +parseOptions.setResolveCombinators(true); +parseOptions.setResolveFully(true); +parseOptions.setFlatten(false); + +SwaggerParseResult parseResult = parser.readContents(content, null, parseOptions); +``` + +因此,检查下来如果发现不兼容,那么所报告的位置会和原文档有所不同。 + +### Paths Object [doc][spec-paths] + +<a name="paths-compatibility"></a> + +* 新OAS必须包含旧OAS的所有的`path`,如果`path`使用了[Path Templating][spec-path-templating],只要变量名发生了变化,那么即使语义上相同也会被认为不同,比如`/pets/{foo}`和`/pets/{bar}`会被认定为不同。 + * 见[Path Item Object兼容性检查](#path-item-compatibility) + +### Path Item Object [doc][spec-path-item] + +<a name="path-item-compatibility"></a> + +* 新OAS必须包含旧OAS的所有的get/put/post/delete/...[Operation Object][spec-operation] + +### Operation Object [doc][spec-operation] + +<a name="operation-compatibility"></a> + +* `operationId`属性,新旧OAS必须完全一致。 +* `parameters`属性,对它检查须在考虑到[Path Item Object parameters属性][spec-path-item-parameters]的情况下进行: + * 新OAS可以新增[Parameter Object][spec-parameter],但是新增的[Parameter Object][spec-parameter]的`required`属性必须为`false` + * 新OAS可以删除[Parameter Object][spec-parameter] + * 针对单个[Parameter Object][spec-parameter]的修改的检查见[Parameter Object兼容性检查](#parameter-compatibility)(在同一个[Operation Object][spec-operation]下[Parameter Object][spec-parameter]依靠`name`和`in`两个属性作为ID)。 +* `requestBody`属性,见[Request Body Object兼容性检查](#request-body-compatibility) +* `responses`属性,见[Responses Object兼容性检查](#responses-compatibility) + +### Parameter Object [doc][spec-parameter] + +<a name="parameter-compatibility"></a> + +* `required`属性,只允许`true(旧) -> false(新)` +* `allowEmptyValue`属性,只允许`false(旧) -> true(新)`的变化 +* `style`属性,新旧OAS必须保持一致 +* `explode`属性,新旧OAS必须保持一致 +* `allowReserved`属性,只允许`false(旧) -> true(新)`的变化 +* `schema`属性,见[Schema Object兼容性检查](#schema-compatibility) +* `content`属性,新OAS必须包含旧OAS的所有media type(`content`的key),且不能新增media type + * 见[Media Type Object兼容性检查](#media-type-compatibility) + +### Request Body Object [doc][spec-request-body] + +<a name="request-body-compatibility"></a> + +* `content`属性,新OAS必须包含旧OAS的所有media type(`content`的key) + * 见[Media Type Object兼容性检查](#media-type-compatibility) +* `required`属性,只允许`true(旧) -> false(新)`的变化 + +### Media Type Object [doc][spec-media-type] + +<a name="media-type-compatibility"></a> + +* `schema`属性,见[Schema Object兼容性检查](#schema-compatibility) +* `encoding`属性,该属性仅适用于`requestBody`,因此新旧OAS的property name(`encoding`的key)必须完全一致 + * 见[Encoding Object兼容性检查](#encoding-compatibility) + +### Responses Object [doc][spec-responses] + +<a name="responses-compatibility"></a> + +* `default`属性,如果旧OAS没有定义`default`,那么新OAS也不能定义`default`。 +* `{Http Status Code}`属性,新OAS不允许新增。 +* 见[Response Object兼容性检查](#response-compatibility) + +### Response Object [doc][spec-response] + +<a name="response-compatibility"></a> + +* `headers`属性,新OAS必须包含旧OAS的所有header name(`headers`的key),可以新增header name + * [Header Object][spec-header]见[Header Object兼容性检查](#header-compatibility) +* `content`属性,新OAS必须包含旧OAS的所有media type(`content`的key),可以新增media type + - [Media Type Object][spec-media-type]见[Media Type Object兼容性检查](#media-type-compatibility) + +### Schema Object [doc][spec-schema] + +<a name="schema-compatibility"></a> + +OAS中定义,Schema Object可以直接或间接用在: + +* 请求类:[Parameter Object][spec-parameter]、[Request Body Object][spec-request-body]、[Header Object][spec-header] +* 响应类:[Header Object][spec-header]、[Response Object][spec-response] + +不同用途的兼容性检查规则有所不同。 + +### 用做请求时 + +原则上,当Schema Object用在请求时,只允许从紧到松的变化。 + +* `type, format`组合所允许的变化范围 + +| 旧(type,format) | 新(type,format) | +| ---------------- | ------------------------------------------------------------ | +| integer, null | integer, int64<br />number, double<br />number, null | +| integer, int32 | integer, int64<br />integer, null<br />number, float<br />number, double<br />number, null | +| integer, int64 | integer, null<br />number, double<br />number, null | +| number, null | number, double | +| number, float | number, null<br />number, double | +| number, double | number, null | +| string, null | string, password | +| string, password | string, null | + +* `allOf`、`oneOf`、`anyOf`属性,在combine之后再做检查 +* `multipleOf`属性,如果旧OAS为null。新OAS必须==旧OAS或者新OAS是旧OAS的因子,比如6(旧)->3(新) +* `maximum`、`maxLength`、`maxItems`、`maxProperties`,如果旧OAS为null,那么新OAS也必须是null。其他情况,新OAS必须>=旧OAS。 +* `minimum`、`minLenght`、`minItems`、`minProperties`,如果旧OAS为null,那么新OAS也必须是null。其他情况,新OAS必须<=旧OAS。 +* `exclusiveMaximum`、`exclusiveMinimum`属性,仅允许`true(旧)->false(新)`的变化 +* `uniqueItems`属性,只允许`true(旧)->false(新)`的变化。 +* `required`属性,新OAS必须==旧OAS,或者新OAS是旧OAS的子集。 +* `enum`属性,新OAS必须==旧OAS,或者新OAS是旧OAS的超集。 +* `properties`属性,新OAS可以新增property name(`properties`的key)或者减少property name。 +* `nullable`属性,只允许`false(旧)->true(新)`的变化。 +* `discriminator`属性,新旧OAS必须完全一致。 +* `xml`属性,新旧OAS必须完全一致。 +* `readOnly`、`writeOnly`,新旧OAS必须完全一致。 + +### 用做响应时 + +原则上,当Schema Object用在响应时,只允许从松到紧的变化。 + +* `type, format`组合所允许的变化范围 + +| 旧(type,format) | 新(type,format) | +| ---------------- | ---------------------------------- | +| integer, null | integer, int64<br />integer, int32 | +| integer, int64 | integer, null<br />interger, int32 | +| number, null | number, double<br />number, float | +| number, double | number, null<br />number, float | +| string, null | string, password | +| string, password | string, null | + +* `allOf`、`oneOf`、`anyOf`属性,在combine之后再做检查 +* `multipleOf`属性,如果旧OAS为null。新OAS必须==旧OAS或者新OAS是旧OAS的倍数,比如3(旧)->6(新) +* `maximum`、`maxLength`、`maxItems`、`maxProperties`,如果旧OAS为null,那么新OAS也必须是null。其他情况,新OAS必须<=旧OAS。 +* `minimum`、`minLenght`、`minItems`、`minProperties`,如果旧OAS为null,那么新OAS也必须是null。其他情况,新OAS必须>=旧OAS。 +* `exclusiveMaximum`、`exclusiveMinimum`属性,仅允许`false(旧)->true(新)`的变化 +* `uniqueItems`属性,只允许`false(旧)->true(新)`的变化。 +* `required`属性,新OAS必须==旧OAS或者,新OAS是旧OAS的超集。 +* `enum`属性,新OAS必须==旧OAS,或者新OAS是旧OAS的子集。 +* `properties`属性,新OAS可以新增property name(`properties`的key)或者减少property name。 +* `nullable`属性,只允许`true(旧)->false(新)`的变化。 +* `discriminator`属性,新旧OAS必须完全一致。 +* `xml`属性,新旧OAS必须完全一致。 +* `readOnly`、`writeOnly`,新旧OAS必须完全一致。 + +### Encoding Object [doc][spec-encoding] + +<a name="encoding-compatibility"></a> + +PS. Encoding Object仅针对Request Body Object有用 + +* `contentType`属性,新旧OAS必须保持一致 +* `headers`属性,新OAS不能新增旧OAS的header name(`headers`的key),但是可以删除header name + * [Header Object][spec-header]见[Header Object兼容性检查](#header-compatibility) +* `style`属性,新旧OAS必须保持一致 +* `explode`属性,新旧OAS必须保持一致 +* `allowReserved`属性,只允许`false(旧) -> true(新)`的变化 + +### Header Object [doc][spec-header] + +<a name="header-compatibility"></a> + +- `schema`属性,见[Schema Object兼容性检查](#schema-compatibility) + +### Components Object [doc][spec-components] + +<a name="components-compatibility"></a> + +[Components Object][spec-components]定义的都是可复用OAS Object,而在检查兼容性的时候所有`$ref`都已被解析了,因此不需要对[Components Object][spec-components]的属性做兼容性检查。 + + +[spec-operation]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#operationObject +[openapi-3.0.2]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md +[spec-openapi]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#openapi-object +[spec-server]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#serverObject +[spec-info]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#infoObject +[spec-paths]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#paths-object +[spec-path-item]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#pathItemObject +[spec-parameter]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#parameterObject +[spec-request-body]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#requestBodyObject +[spec-security-scheme]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#securitySchemeObject +[spec-components]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#components-object +[spec-tag]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#tagObject +[spec-schema]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#schemaObject + +[spec-media-type]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#media-type-object +[spec-response]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#response-object +[spec-path-templating]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#path-templating +[spec-parameterIn]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#parameterIn +[spec-encoding]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#encodingObject +[spec-header]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#header-object +[spec-info]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#infoObject +[spec-reference]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#reference-object +[swagger-parser]: https://github.com/swagger-api/swagger-parser +[spec-path-item-parameters]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#user-content-pathitemparameters +[spec-responses]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#responsesObject diff --git a/_toolkit/cn/quick-start.md b/_toolkit/cn/quick-start.md new file mode 100644 index 0000000..3fad7df --- /dev/null +++ b/_toolkit/cn/quick-start.md @@ -0,0 +1,242 @@ +--- +title: "Toolkit 快速入门" +lang: cn +ref: install +permalink: /cn/docs/toolkit/quick-start/ +excerpt: "了解如何使用一键式微服务开发工具" +last_modified_at: 2019-11-12T00:50:43-55:00 +--- + +{% include toc %} +## 一键式微服务开发工具 Toolkit +Apache ServiceComb Toolkit 是基于契约的微服务开发工具套件。提供契约、代码、文档相互转换及校验的能力,帮助用户一键式快速构建基于流行微服务框架和流行编程模型的微服务工程,降低微服务入门成本,使用户聚焦业务开发,提升遗留系统重构、开发效率。 + +## 3 快速入门 +### 3.1 从源码构建工具和插件 +构建环境要求: + +* [Java 8](http://java.oracle.com) + +* [Apache maven 3.5.0 or greater](http://maven.apache.org/) + +```shell +# 从github获取toolkit最新源码 +$ git clone https://github.com/apache/servicecomb-toolkit.git +$ cd toolkit + +# 构建打包 +$ mvn clean install +``` + + +### 使用toolkit-maven-plugin插件 +#### 1 配置 +在maven项目的pom文件中配置 +```xml +<plugin> + <groupId>org.apache.servicecomb.toolkit</groupId> + <artifactId>toolkit-maven-plugin</artifactId> + <version>0.2.0-SNAPSHOT</version> + <configuration> + <!-- 输入源。设置为 code,表示解析当前代码;设置为 contract,表示解析指定目录的契约文件。不设置则默认为 code --> + <sourceType>code</sourceType> + <!-- 生成契约文件的类型,不设置则默认为 yaml --> + <contractFileType>yaml</contractFileType> + <!-- 生成文档的类型,不设置则默认为 html --> + <documentType>html</documentType> + <!-- 生成契约文件、文档的根目录,不设置则默认为运行命令所在目录下的 target 目录,生成的微服务工程在 project 目录,契约文件在 contract 目录,文档在 document 目录 --> + <outputDirectory>./target</outputDirectory> + <!-- 被解析的契约文件路径,在 sourceType 设置为 contract 时有效,且必须设置 --> + <contractLocation>./contract</contractLocation> + <!-- 被校验的契约文件目录,在 sourceType 设置为 contract 时有效,且必须设置 --> + <sourceContractPath>./target/contract</sourceContractPath> + <!-- 样本契约文件目录,必须设置 --> + <destinationContractPath>./contract</destinationContractPath> + <!-- 生成的微服务代码工程配置 --> + <service> + <!-- 微服务的类型,可生成 provider/consumer/all,默认值为 all --> + <serviceType>all</serviceType> + <!-- 微服务的 groupid,用户可选,默认值为 domain.orgnization.project --> + <groupId>domain.orgnization.project</groupId> + <!-- 微服务的 artifactId,用户可选,默认值为 sample --> + <artifactId>sample</artifactId> + <!-- 微服务的 artifactVersion,用户可选,默认值为 0.1.0-SNAPSHOT --> + <artifactVersion>0.1.0-SNAPSHOT</artifactVersion> + <!-- 微服务的 packageName,用户可选,默认值为 domain.orgnization.project.sample --> + <packageName>domain.orgnization.project.sample</packageName> + <!-- 微服务框架,用户可选。设置为 ServiceComb,生成ServiceComb风格的微服务项目;设置为 SpringCloud,生成SpringCloud风格的微服务项目。默认值为 ServiceComb --> + <microServiceFramework>ServiceComb</microServiceFramework> + <!-- 服务提供者的服务id。仅包含服务消费者的场景(serviceType=consumer)必须设置该值 --> + <providerServiceId>servicecomb-provider</providerServiceId> + <!-- 服务id,默认值为artifactId的值 --> + <serviceId>servicecomb-consumer</serviceId> + </service> + </configuration> +</plugin> +``` + +#### 2 命令 +```shell +# 生成契约,文档和微服务工程 +mvn toolkit:generate + +# 校验代码和契约一致性 +mvn toolkit:verify +``` + +#### 2.1 解析代码,生成微服务代码工程、OpenAPI规范契约、文档 + +配置项(不显式设置 `<configuration>` 则使用默认配置) +例: +```xml +<plugin> + <groupId>org.apache.servicecomb.toolkit</groupId> + <artifactId>toolkit-maven-plugin</artifactId> + <version>0.2.0-SNAPSHOT</version> + <configuration> + <!-- 输入源。设置为 code,表示解析当前代码;设置为 contract,表示解析指定目录的契约文件。不设置则默认为 code --> + <sourceType>code</sourceType> + <!-- 生成契约文件、文档的根目录,不设置则默认为运行命令所在目录下的 target 目录,生成的微服务工程在 project 目录,契约文件在 contract 目录,文档在 document 目录 --> + <outputDirectory>./target</outputDirectory> + <!-- 生成的微服务代码工程配置 --> + <service> + <!-- 微服务的类型,可生成 provider/consumer/all,默认值为 all --> + <serviceType>all</serviceType> + </service> + </configuration> +</plugin> +``` + +运行命令 +```shell +mvn toolkit:generate +``` + +代码生成契约现已支持以下注解(类级别)编写的restful接口 +>RestController, RestSchema, RpcSchema, RequestMapping + +代码生成契约时,restful接口方法修饰符必须指定为public + + +#### 2.2 解析契约,生成微服务工程、文档 + +配置项(不显式设置 `<configuration>` 则使用默认配置) +例: +```xml +<plugin> + <groupId>org.apache.servicecomb.toolkit</groupId> + <artifactId>toolkit-maven-plugin</artifactId> + <version>0.2.0-SNAPSHOT</version> + <configuration> + <!-- 输入源。设置为 code,表示解析当前代码;设置为 contract,表示解析指定目录的契约文件。不设置则默认为 code --> + <sourceType>contract</sourceType> + <!-- 被解析的契约文件路径,在 sourceType 设置为 contract 时有效,且必须设置 --> + <contractLocation>./contract</contractLocation> + <!-- 生成契约文件、文档的根目录,不设置则默认为运行命令所在目录下的 target 目录,生成的微服务工程在 project 目录,契约文件在 contract 目录,文档在 document 目录 --> + <outputDirectory>./target</outputDirectory> + <!-- 生成的微服务代码工程配置 --> + <service> + <!-- 微服务的类型,可生成 provider/consumer/all,默认值为 all --> + <serviceType>provider</serviceType> + </service> + </configuration> +</plugin> +``` + +运行命令 +```shell +mvn toolkit:generate +``` + +#### 2.3 代码和契约一致性校验 + +配置项 +例: +```xml +<plugin> + <groupId>org.apache.servicecomb.toolkit</groupId> + <artifactId>toolkit-maven-plugin</artifactId> + <version>0.2.0-SNAPSHOT</version> + <configuration> + <!-- 输入源。设置为 code,表示解析当前代码;设置为 contract,表示解析指定目录的契约文件。不设置则默认为 code --> + <sourceType>code</sourceType> + <!-- 样本契约文件目录,必须设置 --> + <destinationContractPath>./contract</destinationContractPath> + </configuration> +</plugin> +``` + +运行命令 +```shell +mvn toolkit:verify +``` + + +### 3 使用toolkit cli工具 +可执行jar包位于toolkit/cli/target/bin目录下 +```shell +$ java -jar toolkit-cli-{version}.jar help +``` +#### 3.1 契约生成微服务工程 +```shell +$ java -jar toolkit-cli-{version}.jar codegenerate -m ServiceComb -i swagger.yaml -o ./project -p SpringMVC +``` +> **codegenerate** 命令选项说明: +* -m, --microservice-framework : 指定微服务框架,现支持ServiceComb +例:-m ServiceComb +* -p, --programming-model : 指定编程模型,可选JAX-RS,POJO,SpringMVC,SpringBoot +例:-p SpringMvc +* -i, --input : 指定遵循OpenAPI规范的契约文件,支持yaml和json格式,支持指定本地和网络文件 +例:-i http://petstore.swagger.io/v2/swagger.json +* -o, --output : 生成的项目代码输出路径 +例:-o ./project +* --group-id : 指定生成的项目的group id +例:--group-id com.demo +* --artifact-id : 指定生成的项目的artifact id +例:--artifact-id springmvc-example +* --artifact-version : 指定生成的项目的artifact version +例:--artifact-version 1.0.0 +* --api-package : 指定生成项目的api package +例:--api-package com.demo.api +* --model-package : 指定生成项目的model package +例:--model-package com.demo.model +* -t, --service-type : 指定生成的微服务项目的微服务类型。可选值为provider,consumer,all +例:--service-type provider + +#### 3.2 契约生成文档 +```shell +$ java -jar toolkit-cli-{version}.jar docgenerate -i swagger.yaml -o ./document +``` +> **docgenerate** 命令选项说明: +* -i, --input : 指定遵循OpenAPI规范的契约文件,支持yaml和json格式,支持指定本地和网络文件 +例:-i http://petstore.swagger.io/v2/swagger.json +* -o, --output : 文档输出路径 +例:-o ./document +* -f, --format : 指定输出文档风格,现支持swagger-ui +例:-f swagger-ui + +#### 3.3 契约风格检查 + +```shell +$ java -jar toolkit-cli-{version}.jar checkstyle oas.yaml +或者 +$ java -jar toolkit-cli-{version}.jar cs oas.yaml +``` + +> **checkstyle** Command argument +* <file> OpenAPI v3 spec yaml文件 + +见[风格检查规则](/cn/docs/toolkit/oas-validator/#合规性校验) + +#### 3.4 契约兼容性检查 + +```shell +$ java -jar toolkit-cli-{version}.jar checkcompatibility left-oas.yaml right-oas.yaml +或者 +$ java -jar toolkit-cli-{version}.jar cc left-oas.yaml right-oas.yaml +``` + +> **checkcompatibility** Command argument +* <files> Two OpenAPI v3 spec yaml file + +见[兼容性检查规则](/cn/docs/toolkit/oas-validator/#兼容性检查) diff --git a/assets/images/docs/service-center/config-host-ip.jpg b/assets/images/docs/service-center/config-host-ip.jpg new file mode 100644 index 0000000..9378186 Binary files /dev/null and b/assets/images/docs/service-center/config-host-ip.jpg differ diff --git a/assets/images/docs/service-center/registration&discovery.png b/assets/images/docs/service-center/registration&discovery.png new file mode 100644 index 0000000..d02449c Binary files /dev/null and b/assets/images/docs/service-center/registration&discovery.png differ diff --git a/assets/images/docs/service-center/service-center-why.png b/assets/images/docs/service-center/service-center-why.png new file mode 100644 index 0000000..f0031d9 Binary files /dev/null and b/assets/images/docs/service-center/service-center-why.png differ diff --git a/assets/images/docs/service-center/service-center.jpg b/assets/images/docs/service-center/service-center.jpg new file mode 100644 index 0000000..7d0774c Binary files /dev/null and b/assets/images/docs/service-center/service-center.jpg differ diff --git a/assets/images/docs/syncer/account-server-reply.jpg b/assets/images/docs/syncer/account-server-reply.jpg new file mode 100644 index 0000000..c05ab8c Binary files /dev/null and b/assets/images/docs/syncer/account-server-reply.jpg differ diff --git a/assets/images/docs/syncer/eureka-account-server-success.jpg b/assets/images/docs/syncer/eureka-account-server-success.jpg new file mode 100644 index 0000000..50b0a98 Binary files /dev/null and b/assets/images/docs/syncer/eureka-account-server-success.jpg differ diff --git a/assets/images/docs/syncer/eureka-server-has-all.jpg b/assets/images/docs/syncer/eureka-server-has-all.jpg new file mode 100644 index 0000000..339c70b Binary files /dev/null and b/assets/images/docs/syncer/eureka-server-has-all.jpg differ diff --git a/assets/images/docs/syncer/eureka-server-success.jpg b/assets/images/docs/syncer/eureka-server-success.jpg new file mode 100644 index 0000000..5672b56 Binary files /dev/null and b/assets/images/docs/syncer/eureka-server-success.jpg differ diff --git a/assets/images/docs/syncer/hello-server-discovery-success.jpg b/assets/images/docs/syncer/hello-server-discovery-success.jpg new file mode 100644 index 0000000..3e51c2a Binary files /dev/null and b/assets/images/docs/syncer/hello-server-discovery-success.jpg differ diff --git a/assets/images/docs/syncer/hello-server-result.jpg b/assets/images/docs/syncer/hello-server-result.jpg new file mode 100644 index 0000000..61ef0a2 Binary files /dev/null and b/assets/images/docs/syncer/hello-server-result.jpg differ diff --git a/assets/images/docs/syncer/multi-servicecenters.png b/assets/images/docs/syncer/multi-servicecenters.png new file mode 100644 index 0000000..dbf9731 Binary files /dev/null and b/assets/images/docs/syncer/multi-servicecenters.png differ diff --git a/assets/images/docs/syncer/service-center-hello-server-success.jpg b/assets/images/docs/syncer/service-center-hello-server-success.jpg new file mode 100644 index 0000000..5a0ee93 Binary files /dev/null and b/assets/images/docs/syncer/service-center-hello-server-success.jpg differ diff --git a/assets/images/docs/syncer/service-center-server-has-all.jpg b/assets/images/docs/syncer/service-center-server-has-all.jpg new file mode 100644 index 0000000..2596cb7 Binary files /dev/null and b/assets/images/docs/syncer/service-center-server-has-all.jpg differ diff --git a/assets/images/docs/syncer/service-center-server-success.jpg b/assets/images/docs/syncer/service-center-server-success.jpg new file mode 100644 index 0000000..7d0774c Binary files /dev/null and b/assets/images/docs/syncer/service-center-server-success.jpg differ
