全部产品
云市场

开发 RESTful 应用(不推荐)

更新时间:2019-09-16 16:04:26

你可以在 HSF 框架中开发 RESTful 应用,并实现服务注册与发现、全链路追踪。不过,EDAS 已经支持原生 Spring Cloud 框架的应用,新用户不推荐使用这种开发方式。

原生 Spring Cloud 框架下的服务开发请参考 快速开始

服务注册与发现

通过一个简单的示例详细介绍如何在本地开发 RESTful 应用并实现注册与发现。

Demo 源码下载: sc-vip-serversc-vip-client

创建服务提供者

此服务提供者提供了一个简单的 echo 服务,并将自身注册到服务发现中心。

  1. 创建一个 RESTful 应用工程,命名为sc-vip-server

  2. pom.xml中添加需要的依赖。

    1. <parent>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-parent</artifactId>
    4. <version>1.5.8.RELEASE</version>
    5. <relativePath/>
    6. </parent>
    7. <dependencies>
    8. <dependency>
    9. <groupId>org.springframework.cloud</groupId>
    10. <artifactId>spring-cloud-starter-vipclient</artifactId>
    11. <version>1.3</version>
    12. </dependency>
    13. <dependency>
    14. <groupId>org.springframework.cloud</groupId>
    15. <artifactId>spring-cloud-starter-pandora</artifactId>
    16. <version>1.3</version>
    17. </dependency>
    18. </dependencies>
    19. <dependencyManagement>
    20. <dependencies>
    21. <dependency>
    22. <groupId>org.springframework.cloud</groupId>
    23. <artifactId>spring-cloud-dependencies</artifactId>
    24. <version>Dalston.SR4</version>
    25. <type>pom</type>
    26. <scope>import</scope>
    27. </dependency>
    28. </dependencies>
    29. </dependencyManagement>

    如果您的工程不想将 parent 设置为spring-boot-starter-parent,也可以通过添加dependencyManagement并设置scope=import来达到依赖管理的效果。

    1. <dependencyManagement>
    2. <dependencies>
    3. <dependency>
    4. <groupId>org.springframework.boot</groupId>
    5. <artifactId>spring-boot-dependencies</artifactId>
    6. <version>1.5.8.RELEASE</version>
    7. <type>pom</type>
    8. <scope>import</scope>
    9. </dependency>
    10. </dependencies>
    11. </dependencyManagement>
  3. 创建服务提供者应用,其中@EnableDiscoveryClient注解表明此应用需开启服务注册与发现功能。

    1. @SpringBootApplication
    2. @EnableDiscoveryClient
    3. public class ServerApplication {
    4. public static void main(String[] args) {
    5. PandoraBootstrap.run(args);
    6. SpringApplication.run(ServerApplication.class, args);
    7. PandoraBootstrap.markStartupAndWait();
    8. }
    9. }
  4. 创建EchoController,提供简单的 echo 服务。

    1. @RestController
    2. public class EchoController {
    3. @RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)
    4. public String echo(@PathVariable String string) {
    5. return string;
    6. }
    7. }
  5. resources下的application.properties文件中配置应用名与监听端口号。

    1. spring.application.name=service-provider
    2. server.port=18081

创建服务消费者

本示例中将创建一个服务消费者,通过 RestTemplate、AsyncRestTemplate、FeignClient 这三个客户端去调用服务提供者。

  1. 创建一个 RESTful 应用工程,命名为sc-vip-client

  2. pom.xml中引入需要的依赖。

    1. <parent>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-parent</artifactId>
    4. <version>1.5.8.RELEASE</version>
    5. <relativePath/>
    6. </parent>
    7. <dependencies>
    8. <dependency>
    9. <groupId>org.springframework.cloud</groupId>
    10. <artifactId>spring-cloud-starter-vipclient</artifactId>
    11. <version>1.3</version>
    12. </dependency>
    13. <dependency>
    14. <groupId>org.springframework.cloud</groupId>
    15. <artifactId>spring-cloud-starter-pandora</artifactId>
    16. <version>1.3</version>
    17. </dependency>
    18. <dependency>
    19. <groupId>org.springframework.cloud</groupId>
    20. <artifactId>spring-cloud-starter-feign</artifactId>
    21. </dependency>
    22. </dependencies>
    23. <dependencyManagement>
    24. <dependencies>
    25. <dependency>
    26. <groupId>org.springframework.cloud</groupId>
    27. <artifactId>spring-cloud-dependencies</artifactId>
    28. <version>Dalston.SR4</version>
    29. <type>pom</type>
    30. <scope>import</scope>
    31. </dependency>
    32. </dependencies>
    33. </dependencyManagement>

    因为要演示 FeignClient 的使用,所以与sc-vip-server(服务提供者)相比,pom.xml文件中的依赖增加了一个spring-cloud-starter-feign

  3. sc-vip-server相比,除了开启服务与注册外,还需要添加下面两项配置才能使用 RestTemplate、AsyncRestTemplate、FeignClient 这三个客户端。

    • 添加@LoadBalanced注解将 RestTemplate 和 AsyncRestTemplate 与服务发现结合。
    • 使用@EnableFeignClients注解激活 FeignClients。

      1. @SpringBootApplication
      2. @EnableDiscoveryClient
      3. @EnableFeignClients
      4. public class ConsumerApplication {
      5. @LoadBalanced
      6. @Bean
      7. public RestTemplate restTemplate() {
      8. return new RestTemplate();
      9. }
      10. @LoadBalanced
      11. @Bean
      12. public AsyncRestTemplate asyncRestTemplate(){
      13. return new AsyncRestTemplate();
      14. }
      15. public static void main(String[] args) {
      16. PandoraBootstrap.run(args);
      17. SpringApplication.run(ConsumerApplication.class, args);
      18. PandoraBootstrap.markStartupAndWait();
      19. }
      20. }
  4. 在使用EchoService的 FeignClient 之前,还需要配置服务名以及方法对应的 HTTP 请求。在sc-vip-server工程中配置服务名service-provider

    1. @FeignClient(name = "service-provider")
    2. public interface EchoService {
    3. @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
    4. String echo(@PathVariable("str") String str);
    5. }
  5. 创建一个Controller用于调用测试。

    1. @RestController
    2. public class Controller {
    3. @Autowired
    4. private RestTemplate restTemplate;
    5. @Autowired
    6. private AsyncRestTemplate asyncRestTemplate;
    7. @Autowired
    8. private EchoService echoService;
    9. @RequestMapping(value = "/echo-rest/{str}", method = RequestMethod.GET)
    10. public String rest(@PathVariable String str) {
    11. return restTemplate.getForObject("http://service-provider/echo/" + str, String.class);
    12. }
    13. @RequestMapping(value = "/echo-async-rest/{str}", method = RequestMethod.GET)
    14. public String asyncRest(@PathVariable String str) throws Exception{
    15. ListenableFuture<ResponseEntity<String>> future = asyncRestTemplate.
    16. getForEntity("http://service-provider/echo/"+str, String.class);
    17. return future.get().getBody();
    18. }
    19. @RequestMapping(value = "/echo-feign/{str}", method = RequestMethod.GET)
    20. public String feign(@PathVariable String str) {
    21. return echoService.echo(str);
    22. }
    23. }

    代码说明如下:

    • /echo-rest/验证通过 RestTemplate 去调用服务提供者。
    • /echo-async-rest/ 验证通过 AsyncRestTemplate 去调用服务提供者。
    • /echo-feign/ 验证通过 FeignClient 去调用服务提供者。
  6. 配置应用名以及监听端口号。

    1. spring.application.name=service-consumer
    2. server.port=18082

本地开发调试

启动轻量级配置中心

本地开发调试时,需要使用轻量级配置中心,轻量级配置中心包含了 EDAS 服务注册发现服务端的轻量版,详情请参见配置轻量配置中心

启动应用

本地应用可以通过两种方式启动。

  • IDE 中启动

    在 IDE 中启动,通过 VM options 配置启动参数 -Dvipserver.server.port=8080(注意:该参数仅在本地开发且使用轻量级配置中心时需要添加,当应用部署到 EDAS 时,须移除此参数,否则会使应用无法正常发布或订阅),通过 main 方法直接启动。

    如果你的轻量级配置中心与应用部署在不同的机器上,还需进行 hosts 绑定,详情请参见轻量级配置中心

  • FatJar 启动

    1. 添加 FatJar 打包插件。

      使用 Maven 将 pandora-boot 工程打包成 FatJar, 需要在 pom.xml 中添加如下插件。为避免与其他打包插件发生冲突,请勿在 build 的 plugin 中添加其他 FatJar 插件。

      1. <build>
      2. <plugin>
      3. <groupId>com.taobao.pandora</groupId>
      4. <artifactId>pandora-boot-maven-plugin</artifactId>
      5. <version>2.1.9.1</version>
      6. <executions>
      7. <execution>
      8. <phase>package</phase>
      9. <goals>
      10. <goal>repackage</goal>
      11. </goals>
      12. </execution>
      13. </executions>
      14. </plugin>
      15. </build>
    2. 添加完插件后,在工程的主目录下,使用 maven 命令 mvn clean package 进行打包,即可在 target 目录下找到打包好的 FatJar 文件。

    3. 通过 Java 命令启动应用。

      1. java -Dvipserver.server.port=8080 -Dpandora.location=/Users/{$username}/.m2/repository/com/taobao/pandora/taobao-hsf.sar/dev-SNAPSHOT/taobao-hsf.sar-dev-SNAPSHOT.jar -jar sc-vip-server-0.0.1-SNAPSHOT.jar

      注意 : -Dpandora.location 指定的路径必须是全路径,且必须放在 sc-vip-server-0.0.1-SNAPSHOT.jar 之前。

演示

启动服务,分别进行调用,可以看到调用都成功了。

调用结果

常见问题

  1. AsyncRestTemplate 无法接入服务发现。

    AsyncRestTemplate 接入服务发现的时间比较晚,需要在 Dalston 之后的版本才能使用,具体详情参见此 pull request

  2. FatJar 打包插件冲突

    为避免与其他打包插件发生冲突,请勿在 build 的 plugin 中添加其他 FatJar 插件。

  3. 打包时可不可以不排除 taobao-hsf.sar?

    可以,但是不建议这么做。

    通过修改 pandora-boot-maven-plugin 插件,把 excludeSar 设置为 false,打包时就会自动包含 taobao-hsf.sar。

    1. <plugin>
    2. <groupId>com.taobao.pandora</groupId>
    3. <artifactId>pandora-boot-maven-plugin</artifactId>
    4. <version>2.1.9.1</version>
    5. <configuration>
    6. <excludeSar>false</excludeSar>
    7. </configuration>
    8. <executions>
    9. <execution>
    10. <phase>package</phase>
    11. <goals>
    12. <goal>repackage</goal>
    13. </goals>
    14. </execution>
    15. </executions>
    16. </plugin>

    这样打包后可以在不配置 Pandora 地址的情况下启动。

    1. java -jar -Dvipserver.server.port=8080 sc-vip-server-0.0.1-SNAPSHOT.jar

    请在将应用部署到 EDAS 前恢复到默认排除 SAR 包的配置。

全链路跟踪

您可以在本地对您的 RESTful 应用经过简单的修改接入到 EDAS 的 EagleEye,从而实现全链路跟踪。

为了节约您的开发成本和提升您的开发效率,EDAS 提供了全链路跟踪的组件 EagleEye。您只需在代码中配置 EagleEye 埋点,即可直接使用 EDAS 的全链路跟踪功能,无需关心日志采集、分析、存储等过程。

Demo 源码下载:service1service2

接入 EagleEye

在 Maven 中配置 EDAS 的私服地址

目前 Pandora Boot Starter 相关的包只发布在 EDAS 的私服中,所以需要在 Maven(要求 3.x 及后续版本)配置文件settings.xml中配置 EDAS 的私服地址,详情请参见- 在 Maven 中配置 EDAS 私服地址

修改代码

RESTful 应用接入 EDAS 的 EagleEye 很简单,只需要完成以下三步。

  1. pom.xml文件中加入如下公共配置。

    1. <dependency>
    2. <groupId>org.springframework.cloud</groupId>
    3. <artifactId>spring-cloud-starter-eagleeye</artifactId>
    4. <version>1.3</version>
    5. </dependency>
    6. <dependency>
    7. <groupId>org.springframework.cloud</groupId>
    8. <artifactId>spring-cloud-starter-pandora</artifactId>
    9. <version>1.3</version>
    10. </dependency>
  2. 在 main 函数中添加修改配置。

    假设修改之前的 main 函数内容如下:

    1. public static void main(String[] args) {
    2. SpringApplication.run(ServerApplication.class, args);
    3. }

    则修改为:

    1. public static void main(String[] args) {
    2. PandoraBootstrap.run(args);
    3. SpringApplication.run(ServerApplication.class, args);
    4. PandoraBootstrap.markStartupAndWait();
    5. }
  3. 添加 FatJar 打包插件。

    使用 Maven 将 pandora-boot 工程打包成 FatJar, 需要在pom.xml中添加如下插件。

    为避免与其他打包插件发生冲突,请勿在 build 的 plugin 中添加其它 FatJar 插件。

    1. <build>
    2. <plugins>
    3. <plugin>
    4. <groupId>com.taobao.pandora</groupId>
    5. <artifactId>pandora-boot-maven-plugin</artifactId>
    6. <version>2.1.9.1</version>
    7. <executions>
    8. <execution>
    9. <phase>package</phase>
    10. <goals>
    11. <goal>repackage</goal>
    12. </goals>
    13. </execution>
    14. </executions>
    15. </plugin>
    16. </plugins>
    17. </build>

完成上述三处修改后,您无需搭建任何采集分析系统,即可直接使用 EDAS 的全链路跟踪功能。

全链路跟踪示例

源码

为了演示如何使用全链路跟踪功能 ,这里提供两个应用 Demo:service1service2

service1 用作入口的服务,提供了三个场景演示的入口:

  • /rest/ok,对应正常的调用

    /rest/ok

  • /rest/delay,对应延迟较大的调用

    /rest/delay

  • /rest/error,对应异常出错的调用

    /rest/error

部署应用

EagleEye 的采集和分析功能都搭建在 EDAS 上,为了演示调用链查看功能,我们首先将 service1 和 service2 这两个应用部署到 EDAS 中。详情请参见应用部署概述

查看调用链

部署完毕之后,为了能够查看调用链的信息,我们还需要调用 service1 三个场景演示的入口对应的方法。您可以通过执行 curl http://{$ip:$port}/rest/ok 这种简单的方式来调用。也可以使用 postman 等工具或者直接在浏览器中调用。

为了便于观察,建议使用脚本等方式多调用几次。然后按以下步骤查看调用链。

  1. 登录 EDAS 控制台,进入刚刚部署的应用中。

  2. 在应用详情页面左侧的导航栏中选择应用监控 > 服务监控

  3. 在服务监控页面单击提供的 RPC 服务页签,然后单击查看调用链

更详细的使用信息,请参考服务监控

  • 正常的调用链详情

    rest.ok.png

    从图中可以看出服务经过了哪几次调用,并且可以看到 step1、step2、step3 的耗时分别是 2ms、1ms、0ms。

  • 延迟较大的调用链详情

    rest.delay.1.png

    从图中可以看到 delay1、delay2、delay3 的耗时分别是 453ms、353ms、151ms,

    rest.delay.2.png

    将鼠标停留在 delay3 这个调用段,还可以看到更多详细的调用链的信息。其中服务端处理请求花费了 150ms,客户端在服务端处理完请求后的 1ms 收到了响应。

  • 异常出错的调用链详情

    rest.error.png

    从图中我们可以很清晰地看到,出错的请求为 /rest/error3 ,极大地方便了我们对问题进行定位。

其他客户端的演示

同时,在 service1 的 /echo-rest/{str} 、 /echo-async-rest/{str} 、 /echo-feign/{str} 这三个 URI 中,分别演示了 EagleEye 对 RestTemplate、 AsyncRestTemplate 、 FeignClient 的自动埋点支持,您可以在调用后,通过同样的方式查看着这三者的调用链信息。

常见问题

埋点支持

目前 EDAS 的 EagleEye 已经支持自动对 RestTemplate、AsyncRestTemplate、FeignClient 调用的请求自动进行跟踪。后续我们将接入更多的组件的自动埋点

AsyncRestTemplate

由于 AsyncRestTemplate 需要在类实例化的阶段进行埋点支持的修改,所以如果需要使用全链路跟踪功能,需要按名称注入对象,eagleEyeAsyncRestTemplate,此对象默认添加了服务发现的支持。

  1. @Autowired
  2. private AsyncRestTemplate eagleEyeAsyncRestTemplate;

FatJar 打包插件

使用 Maven 将 pandora-boot 工程打包成 FatJar, 需要在 pom.xml 中添加 pandora-boot-maven-plugin 的打包插件。为避免与其他打包插件发生冲突,请勿在 build 的 plugin 中添加其他 FatJar 插件。

扩展

更多全链路跟踪以及 EagleEye 的信息,请参考 Spring Cloud 接入 EDAS 之全链路跟踪