Apache ServiceComb java-chassis 3.3.0 构建并运行示例 REST 应用指南

Apache ServiceComb java-chassis 3.3.0 构建并运行示例 REST 应用指南:从零创建 Maven 工程、完整 pom.xml 与 @RestSchema 接口源码、microservice.yaml 配置、mvn package 打 fat jar、java -jar 启动日志与 curl 真实回显(HTTP 200 返回 JSON 字符串),含 local 注册中心与 service-center 注册实测,全程可复现。

Apache ServiceCombApache ServiceComb2026/10/12

Apache ServiceComb java-chassis 3.3.0 构建并运行示例 REST 应用指南

目标:从零构建并运行一个基于 Apache ServiceComb java-chassis 3.3.0 的最小 REST 微服务。给出完整 pom.xml、示例 Java 源码、microservice.yaml 配置、编译打包命令、启动日志与 curl 真实回显(GET /hello 返回 HTTP 200 与 "Hello, ServiceComb!"),并实测「内置 local 注册中心」与「外置 service-center 注册中心」两种运行形态。所有命令与输出均在 Ubuntu 22.04.5 + JDK 17 环境实测通过。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS
  • Java:OpenJDK 17.0.20.1
  • 构建工具:Apache Maven 3.6.3
  • java-chassis 版本:3.3.0(java-chassis-bom + java-chassis-spring-boot-starter-standalone)
  • Spring Boot 版本:3.2.12
  • 注册中心(可选小节):service-center 2.2.0(embedded_etcd 模式,监听 30100)
  • 示例工程目录:/root/servicecomb-hello/
  • 演示账号:root

二、前置条件

  • 已安装 JDK 17 与 Maven,并确认版本回显正确:
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH
java -version
  • 回显需为 openjdk version "17.0.20.1" 2026-08-18(java-chassis 3.x 必须 JDK 17+)。
  • 安装步骤见《Ubuntu 22.04 安装 Apache ServiceComb java-chassis 3.3.0 指南》篇。

三、工程结构

标准 Maven 布局,一个主类、一个 REST 生产者、两个配置文件:

servicecomb-hello/
├── pom.xml
└── src/main/
    ├── java/demo/
    │   ├── HelloApplication.java
    │   └── HelloEndpoint.java
    └── resources/
        ├── application.yml
        └── microservice.yaml
mkdir -p /root/servicecomb-hello/src/main/java/demo
mkdir -p /root/servicecomb-hello/src/main/resources

四、完整 pom.xml

pom 通过 <dependencyManagement> 同时导入 java-chassis-bom(3.3.0)与 spring-boot-dependencies(3.2.12),并用 spring-boot-maven-plugin 的 repackage 打可执行 fat jar:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>demo</groupId>
    <artifactId>servicecomb-hello</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java-chassis.version>3.3.0</java-chassis.version>
        <spring-boot.version>3.2.12</spring-boot.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.apache.servicecomb</groupId>
                <artifactId>java-chassis-bom</artifactId>
                <version>${java-chassis.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.apache.servicecomb</groupId>
            <artifactId>java-chassis-spring-boot-starter-standalone</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

    <build>
        <finalName>servicecomb-hello</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

五、示例源码

5.1 启动主类 HelloApplication.java

java-chassis 3.x 无需在主类上加任何 java-chassis 注解(2.x 的 @EnableServiceComb 已移除),框架经 Spring Boot 3 自动配置装配:

package demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HelloApplication {
    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class, args);
    }
}

5.2 REST 生产者 HelloEndpoint.java

@RestSchema 把类声明为 java-chassis REST 生产者 schema;JAX-RS(jakarta 命名空间)注解声明路径与方法。示例包含两个端点:/hello 直接返回,/hello/call 演示通过 RestTemplateBuilder 以 cse://服务名/路径 形式做服务间调用:

package demo;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;
import org.apache.servicecomb.provider.rest.common.RestSchema;
import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder;
import org.springframework.web.client.RestOperations;

@RestSchema(schemaId = "hello")
@Path("/hello")
public class HelloEndpoint {
    private final RestOperations restTemplate = RestTemplateBuilder.create();

    @GET
    public String sayHello(@QueryParam("name") String name) {
        String who = (name == null || name.isEmpty()) ? "ServiceComb" : name;
        return "Hello, " + who + "!";
    }

    @GET
    @Path("/call")
    public String callSelf(@QueryParam("name") String name) {
        return restTemplate.getForObject(
                "cse://hello/hello?name={name}", String.class, name);
    }
}

💡 说明:RestTemplateBuilder.create() 的返回类型是 RestOperations 接口,不能声明为 RestTemplate,否则编译报 incompatible types: org.springframework.web.client.RestOperations cannot be converted to org.springframework.web.client.RestTemplate(实测踩坑)。

5.3 微服务配置 microservice.yaml

声明服务名、版本、REST 监听地址。registry.enabled: false 为最小可运行形态(不依赖任何注册中心):

application:
  name: hello-app
servicecomb:
  service:
    name: hello
    version: 0.0.1
    registry:
      enabled: false
  rest:
    address: 0.0.0.0:8080

5.4 application.yml(standalone 形态必需)

spring:
  main:
    web-application-type: none

⚠️ 注意:缺少该文件时启动会报 Web application could not be started as there was no org.springframework.boot.web.servlet.server.ServletWebServerFactory bean defined in the context——standalone 形态 REST 由 Vert.x 提供,必须禁止 Spring Boot 再起 Servlet 容器。

六、编译与运行

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH
cd /root/servicecomb-hello

# 编译打包(生成可执行 fat jar)
mvn clean package -DskipTests

实测结果(节选):

[INFO] --- spring-boot-maven-plugin:3.2.12:repackage (repackage) @ servicecomb-hello ---
[INFO] Replacing main artifact /root/servicecomb-hello/target/servicecomb-hello.jar
[INFO] BUILD SUCCESS

限制 JVM 堆内存并后台启动(演示进程堆限制在 256–512MB):

nohup java -Xms256m -Xmx512m -jar target/servicecomb-hello.jar > /root/hello.log 2>&1 &

启动日志关键行(真实回显,节选):

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::               (v3.2.12)

Starting HelloApplication using Java 17.0.20.1 with PID 5549 (/root/servicecomb-hello/target/servicecomb-hello.jar started by root in /root/servicecomb-hello)
o.a.s.t.rest.vertx.RestServerVerticle    : rest listen success. address=0.0.0.0:8080
o.a.s.core.transport.TransportManager    : endpoint to publish: rest://172.17.0.9:8080
o.a.s.c.p.producer.ProducerBootListener  : export microservice swagger file to path /tmp/microservices/%s/%s.yaml
org.apache.servicecomb.core.SCBEngine    : ServiceComb is ready.

验证堆内存生效(另开终端):

jps -v

实测回显:

5549 servicecomb-hello.jar -Xms256m -Xmx512m

七、验证 REST 服务

7.1 直接调用

curl -s http://127.0.0.1:8080/hello
curl -s "http://127.0.0.1:8080/hello?name=Alice"
curl -s -i http://127.0.0.1:8080/hello

实测回显:

"Hello, ServiceComb!"
"Hello, Alice!"
HTTP/1.1 200 OK
X-B3-TraceId: 6accdcd8751366a7
Content-Type: application/json
Content-Length: 21

"Hello, ServiceComb!"

💡 响应头 X-B3-TraceId 为 java-chassis 自动注入的链路追踪标识;返回值带引号是因为 REST 契约默认按 JSON 字符串序列化。

7.2 服务间调用(cse:// 协议)

curl -s "http://127.0.0.1:8080/hello/call?name=Carol"

实测回显:

"Hello, Carol!"

/hello/call 内部经 cse://hello/hello 由 java-chassis 服务发现后转发到本服务的 /hello,证明消费端调用链可用。

7.3 查看 Swagger 契约

java-chassis 启动时自动把生产者契约导出到 /tmp/microservices/<应用>/<服务>/:

cat /tmp/microservices/hello/hello.yaml

实测回显(节选):

openapi: 3.0.1
info:
  title: swagger definition for demo.HelloEndpoint
  version: 1.0.0
servers:
- url: /hello
paths:
  /:
    get:
      operationId: sayHello
      parameters:
      - name: name
        in: query
        schema:
          type: string
      responses:
        "200":
          description: response of 200

八、接入服务注册中心(可选)

默认 registry.enabled: false 时服务独立运行。生产环境通常需要注册中心,以下两种形态均已实测。

8.1 形态一:内置 local 注册中心(零外部依赖)

在 pom.xml 追加 registry-local 依赖(版本由 bom 管理):

<dependency>
    <groupId>org.apache.servicecomb</groupId>
    <artifactId>registry-local</artifactId>
</dependency>

microservice.yaml 改为:

application:
  name: hello-app
servicecomb:
  service:
    name: hello
    version: 0.0.1
    registry:
      enabled: true
  registry:
    local:
      enabled: true
  rest:
    address: 0.0.0.0:8080

重新打包并启动后,日志关键行:

o.a.servicecomb.registry.RegistrationId  : initialized global registration id 8122c655-dc18-4b25-996a-d5f7691288e2
o.a.s.c.provider.LocalOpenAPIRegistry    : register swagger appId=default, name=hello, schemaId=hello.
rest listen success. address=0.0.0.0:8080
ServiceComb is ready.
  name:local-registry

local 注册中心把实例注册在进程内存中,适合单机演示与同进程消费端调用验证。

8.2 形态二:外置 service-center 注册中心(生产形态)

部署 service-center 2.2.0 并以 embedded_etcd 模式启动(默认 etcd 模式需要外置 etcd,本例改用内嵌):

wget https://dlcdn.apache.org/servicecomb/servicecomb-service-center/2.2.0/apache-servicecomb-service-center-2.2.0-linux-amd64.tar.gz
mkdir -p /opt/service-center
tar xzf apache-servicecomb-service-center-2.2.0-linux-amd64.tar.gz -C /opt/service-center
sed -i 's/^  kind: etcd/  kind: embedded_etcd/' /opt/service-center/apache-servicecomb-service-center-2.2.0-linux-amd64/conf/app.yaml
cd /opt/service-center/apache-servicecomb-service-center-2.2.0-linux-amd64
nohup ./service-center > /root/sc.log 2>&1 &
curl -s http://127.0.0.1:30100/v4/default/registry/microservices

service-center 就绪后(自身实例 UP,version 2.2.0),在示例工程 pom.xml 追加依赖:

<dependency>
    <groupId>org.apache.servicecomb</groupId>
    <artifactId>registry-service-center</artifactId>
</dependency>

microservice.yaml 指定 service-center 地址(3.x 配置键为 servicecomb.registry.sc.address):

application:
  name: hello-app
servicecomb:
  service:
    name: hello
    version: 0.0.1
    registry:
      enabled: true
  registry:
    sc:
      address: http://127.0.0.1:30100
  rest:
    address: 0.0.0.0:8080

⚠️ 注意:3.x 已不支持 2.x 的 servicecomb.service.registry.address 写法;若沿用旧键,启动直接失败并提示 Address is required in configuration. NOTICE: since 3.0.0, only support servicecomb.registry.sc.address to configure service center address。另外修改 src/main/resources 下任何配置后必须重新 mvn package,fat jar 内的配置是打包时快照。

重新打包、启动后,注册成功日志:

o.a.s.s.c.client.ServiceCenterClient     : Query serviceId fails, statusCode = 400; message = Bad Request; content = {"errorCode":"400012","errorMessage":"Micro-service does not exist","detail":"/default/hello/0.0.1 does not exist."}
o.a.s.s.c.c.ServiceCenterRegistration    : register microservice successfully, service id=bad03bda8b28269a31ccf8fade650edd7750bb86, instance id=b1050217-3fed-4bb3-aaff-63cb259e98ed

💡 首次启动时 Query serviceId fails, statusCode = 400(errorCode 400012,Micro-service does not exist)是正常现象:客户端先查询服务是否存在,不存在则自动完成注册。

到 service-center 侧查询,可见 hello 服务已注册:

curl -s http://127.0.0.1:30100/v4/default/registry/microservices

实测回显(节选):

"serviceName":"hello"

九、注意事项

⚠️ 注意:

  1. 必须使用 JDK 17 编译运行(java-chassis 3.x 基于 Spring Boot 3.x / jakarta 命名空间);JDK 8/11 请退用 java-chassis 2.x。
  2. java-chassis-bom 与 spring-boot-dependencies 两个 import 必须成对出现,且所有 org.apache.servicecomb 依赖不要单独写版本号,统一由 bom 管理。
  3. standalone 形态必须设置 spring.main.web-application-type: none,否则与 Vert.x REST 端口模型冲突。
  4. 进程堆内存建议显式限制(-Xms256m -Xmx512m),并用 jps -v 验证。

十、常见问题

Q1:启动报 no org.springframework.boot.web.servlet.server.ServletWebServerFactory bean defined in the context? 在 application.yml 增加 spring.main.web-application-type: none。原因与原理见 5.4 节。

Q2:编译报 package org.apache.servicecomb.springboot.starter does not exist? 主类使用了 2.x 的 @EnableServiceComb。3.x 主类只需 @SpringBootApplication。

Q3:编译报 RestOperations cannot be converted to RestTemplate? RestTemplateBuilder.create() 返回 RestOperations,字段类型要声明为 RestOperations。

Q4:连不上注册中心 / 报 Address is required in configuration? 3.x 的 service-center 地址键是 servicecomb.registry.sc.address,不是 2.x 的 servicecomb.service.registry.address;确认 microservice.yaml 层级为 servicecomb.registry.sc.address,且修改后已重新 mvn package。

Q5:修改了配置文件但不生效? fat jar 内的 microservice.yaml 是打包时快照,改 src/main/resources 后必须重新 mvn clean package 再启动。

十一、参考链接

  • java-chassis 官方文档:https://servicecomb.apache.org/references/java-chassis/zh_CN/
  • Spring Boot 集成说明:https://servicecomb.apache.org/references/java-chassis/zh_CN/using-java-chassis-in-spring-boot/
  • service-center 官方仓库:https://github.com/apache/servicecomb-service-center
  • 本示例依赖坐标查询:https://repo1.maven.org/maven2/org/apache/servicecomb/