Skip to content

开发第一个微服务应用

准备工作

在开发第一个Java-Chassis微服务之前,请先确保本地开发环境已经准备就绪,参考安装本地开发环境

运行这些例子之前,需要先安装注册中心配置中心 。华为云提供一个出色的本地轻量化微服务引擎 , 可以直接下载安装使用,它包含了注册中心和配置中心。

Java Chassis依赖于Spring Boot,如果对于Spring Boot比较陌生,可以先通过 Spring Boot入门 了解。

例子介绍

Basic示例 包含了3个微服务: gateway, provider, consumer。 这3个服务完成了一个最简单的微服务架构。 其中 provider 提供一个 REST 接口, consumer 调用 provider 的 REST 接口完成同样的功能。 gateway 作为微服务的接入端, 负责所有外部请求的接入。

如果已经了解 JAVA + MAVEN 应用程序开发, 可以直接下载并运行这个示例。 下面介绍该示例的关键开发步骤。

开发一个带 REST 接口的微服务

配置pom文件

创建一个空的maven工程。建议先配置dependencyManagement来管理依赖项


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

依赖项需要引入solution-basic, 并且引入注册中心、配置中心和Logger系统的依赖


<dependencies>
  <dependency>
    <groupId>org.apache.servicecomb</groupId>
    <artifactId>solution-basic</artifactId>
  </dependency>
  <!-- using log4j2 -->
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
  </dependency>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
  </dependency>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
  </dependency>
  <!-- using service-center & kie -->
  <dependency>
    <groupId>org.apache.servicecomb</groupId>
    <artifactId>registry-service-center</artifactId>
  </dependency>
  <dependency>
    <groupId>org.apache.servicecomb</groupId>
    <artifactId>config-kie</artifactId>
  </dependency>
  <!-- using java chassis http transport -->
  <dependency>
    <groupId>org.apache.servicecomb</groupId>
    <artifactId>java-chassis-spring-boot-starter-standalone</artifactId>
  </dependency>
</dependencies>

solution-basic中已经包含了常见场景下开发Java-Chassis微服务所需的全部依赖项。

引入maven-compiler-plugin插件,使项目打包时保留方法参数名:


<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>${maven-compiler-plugin.version}</version>
  <configuration>
    <compilerArgument>-parameters</compilerArgument>
    <source>17</source>
    <target>17</target>
  </configuration>
</plugin>

添加配置文件

按照Spring Boot应用程序要求,增加 application.yaml 文件 ,存放在resources目录中。

文件内容如下,这份文件表示当前开发的是basic-application应用下的名为provider的微服务,版本为0.0.1。该微服务连接的注册中心地址为http://localhost:30100 ,配置中心地址为http://localhost:30110。 该微服务监听HTTP协议的9093端口。

servicecomb:
  service:
    application: basic-application
    name: provider
    version: 0.0.1
  rest:
    address: 0.0.0.0:9093
  # 注册发现
  registry:
    sc:
      address: http://localhost:30100
  # 动态配置
  kie:
    serverUri: http://localhost:30110

编写启动类

Java Chassis应用是一个标准的Spring Boot应用。本示例中,设置 WebApplicationType.NONE, 这样会使用 Java Chassis自带的高性能 HTTP 容器,而不使用 Spring Boot自带的WEB容器。


@SpringBootApplication
public class ProviderApplication {
  public static void main(String[] args) throws Exception {
    try {
      new SpringApplicationBuilder()
          .web(WebApplicationType.NONE)
          .sources(ProviderApplication.class)
          .run(args);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

编写服务

本例子采用契约优先的开发方法。

首先定义服务接口:

@RequestMapping(path = "/provider")
public interface ProviderService {
  @GetMapping("/sayHello")
  String sayHello(@RequestParam("name") String name);

  @GetMapping("/exampleConfig")
  String exampleConfig();
}

在工程中添加一个REST接口类用于接收请求:

@RestSchema(schemaId = "ProviderController", schemaInterface = ProviderService.class)
public class ProviderController implements ProviderService {
  private DynamicProperties dynamicProperties;

  private String example;

  @Autowired
  public ProviderController(DynamicProperties dynamicProperties) {
    this.dynamicProperties = dynamicProperties;
    this.example = this.dynamicProperties.getStringProperty("basic.example",
        value -> this.example = value, "not set");
  }

  @Override
  public String sayHello(String name) {
    return "Hello " + name;
  }

  @Override
  public String exampleConfig() {
    return example;
  }
}

该类实现了两个REST接口,其中sayHello实现了一个简单的echo程序;exampleConfig演示了如何通过配置中心下发配置项,并动态监听配置项的变化。

添加日志配置文件

本例子引入了log4j2组件。如果想要看到运行日志,还需要手动添加一份日志配置文件,文件存放位置为resources\log4j2.xml,内容如下:


<Configuration status="INFO">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="[%d][%t][%p]%m [%c:%L]%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="INFO">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>

调用服务

在 Consumer 里面,演示了如何调用 Provider 的服务。 首先声明一个 PRC 接口的 Bean。

@Configuration
public class ProviderServiceConfiguration {
  @Bean
  public ProviderService providerService() {
    return Invoker.createProxy("provider", "ProviderController", ProviderService.class);
  }
}

使用 @Autowired 声明 RPC 接口的远程引用, 然后可以像调用本地方法一样,访问 Provider 的服务。

@RestSchema(schemaId = "ConsumerController", schemaInterface = ConsumerService.class)
public class ConsumerController implements ConsumerService {
  private ProviderService providerService;

  @Autowired
  public void setProviderService(ProviderService providerService) {
    this.providerService = providerService;
  }

  @Override
  public String sayHello(String name) {
    return providerService.sayHello(name);
  }

  @Override
  public String exampleConfig() {
    return providerService.exampleConfig();
  }
}

微服务网关

微服务网关是一个普通的微服务,需要额外引入 edge-core


<dependency>
  <groupId>org.apache.servicecomb</groupId>
  <artifactId>edge-core</artifactId>
</dependency>

启动服务

依次启动 ProviderApplicationConsumerApplicationGatewayApplication, 访问 http://localhost:9090/sayHello?name=World ,可以得到响应"Hello World!"

打开注册中心、配置中心控制台,还可以看到微服务的实例列表。通过配置中心给 ProviderApplication 添加配置, 访问 http://localhost:9090/exampleConfig , 可以得到响应,响应包含了最新的配置项的值。

使用Nacos注册中心和配置中心

本例子还可以使用 Nacos 作为注册中心和配置中心。

编译:

mvn clean install -Pnacos

运行:

java -Dspring.profiles.active=nacos -jar basic-provider-2.0-SNAPSHOT.jar

也可以在IDE里面选择 MAVEN 的 nacos PROFILE,并修改 application.yml 的 spring.profiles.active 为 nacos.