在 HSF 框架中开发 RESTful 应用,并实现服务注册与发现。由于 EDAS 已经支持原生 Spring Cloud 框架的应用,新用户不推荐使用该开发方式。

背景信息

原生 Spring Cloud 框架下的服务开发请参考将 Spring Cloud 应用托管到 EDAS

服务注册与发现

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

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

  1. 创建服务提供者。
    此服务提供者提供了一个简单的 echo 服务,并将自身注册到服务发现中心。
    1. 创建命名为 sc-vip-server的 RESTful 应用工程,。
    2. pom.xml 中添加需要的依赖。
          <parent>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-parent</artifactId>
              <version>1.5.8.RELEASE</version>
              <relativePath/>
          </parent>
      
          <dependencies>
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-vipclient</artifactId>
                  <version>1.3</version>
              </dependency>
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-pandora</artifactId>
                  <version>1.3</version>
              </dependency>
          </dependencies>
      
          <dependencyManagement>
              <dependencies>
                  <dependency>
                      <groupId>org.springframework.cloud</groupId>
                      <artifactId>spring-cloud-dependencies</artifactId>
                      <version>Dalston.SR4</version>
                      <type>pom</type>
                      <scope>import</scope>
                  </dependency>
              </dependencies>
          </dependencyManagement>

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

      <dependencyManagement>
                  <dependencies>
                      <dependency>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-dependencies</artifactId>
                          <version>1.5.8.RELEASE</version>
                          <type>pom</type>
                          <scope>import</scope>
                      </dependency>
                  </dependencies>
      </dependencyManagement>
    3. 创建服务提供者应用,其中 @EnableDiscoveryClient 注解表明此应用需开启服务注册与发现功能。
      @SpringBootApplication
          @EnableDiscoveryClient
          public class ServerApplication {
      
              public static void main(String[] args) {
                  PandoraBootstrap.run(args);
                  SpringApplication.run(ServerApplication.class, args);
                  PandoraBootstrap.markStartupAndWait();
              }
          }
    4. 创建 EchoController,提供简单的 echo 服务。
      @RestController
          public class EchoController {
              @RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)
              public String echo(@PathVariable String string) {
                  return string;
              }
          }
    5. resources下的 application.properties 文件中配置应用名与监听端口号。
      spring.application.name=service-provider
      server.port=18081
  2. 创建服务消费者。
    本示例中将创建一个服务消费者,通过 RestTemplate、AsyncRestTemplate、FeignClient 这三个客户端去调用服务提供者。
    1. 创建名为 sc-vip-client 的 RESTful 应用工程。
    2. pom.xml 中引入需要的依赖。
      <parent>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-parent</artifactId>
              <version>1.5.8.RELEASE</version>
              <relativePath/>
          </parent>
      
          <dependencies>
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-vipclient</artifactId>
                  <version>1.3</version>
              </dependency>
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-pandora</artifactId>
                  <version>1.3</version>
              </dependency>
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-feign</artifactId>
              </dependency>
          </dependencies>
      
          <dependencyManagement>
              <dependencies>
                  <dependency>
                      <groupId>org.springframework.cloud</groupId>
                      <artifactId>spring-cloud-dependencies</artifactId>
                      <version>Dalston.SR4</version>
                      <type>pom</type>
                      <scope>import</scope>
                  </dependency>
              </dependencies>
          </dependencyManagement>

      本示例需要通过 FeignClient 进行演示,与 sc-vip-server(服务提供者)相比,pom.xml 文件中的依赖增加了 spring-cloud-starter-feign

    3. 与 sc-vip-server 相比,除了开启服务与注册外,还需要添加下面两项配置才能使用 RestTemplate、AsyncRestTemplate、FeignClient 这三个客户端。
      • 添加 @LoadBalanced 注解将 RestTemplate 和 AsyncRestTemplate 与服务发现结合。
      • 使用 @EnableFeignClients 注解激活 FeignClients。
        @SpringBootApplication
            @EnableDiscoveryClient
            @EnableFeignClients
            public class ConsumerApplication {
        
                @LoadBalanced
                @Bean
                public RestTemplate restTemplate() {
                    return new RestTemplate();
                }
        
                @LoadBalanced
                @Bean
                public AsyncRestTemplate asyncRestTemplate(){
                    return new AsyncRestTemplate();
                }
        
                public static void main(String[] args) {
                    PandoraBootstrap.run(args);
                    SpringApplication.run(ConsumerApplication.class, args);
                    PandoraBootstrap.markStartupAndWait();
                }
        
            }
    4. 在使用 EchoService 的 FeignClient 之前,还需要配置服务名以及方法对应的 HTTP 请求。在 sc-vip-server 工程中配置服务名 service-provider。
      @FeignClient(name = "service-provider")
          public interface EchoService {
              @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
              String echo(@PathVariable("str") String str);
          }
    5. 创建一个 Controller 用于调用测试。
      @RestController
      public class Controller {
         @Autowired
         private RestTemplate restTemplate;
         @Autowired
         private AsyncRestTemplate asyncRestTemplate;
         @Autowired
         private  EchoService echoService;
         @RequestMapping(value = "/echo-rest/{str}", method = RequestMethod.GET)
         public String rest(@PathVariable String str) {
             return restTemplate.getForObject("http://service-provider/echo/" + str, String.class);
         }
         @RequestMapping(value = "/echo-async-rest/{str}", method = RequestMethod.GET)
         public String asyncRest(@PathVariable String str) throws Exception{
             ListenableFuture<ResponseEntity<String>> future = asyncRestTemplate.
                     getForEntity("http://service-provider/echo/"+str, String.class);
             return future.get().getBody();
         }
         @RequestMapping(value = "/echo-feign/{str}", method = RequestMethod.GET)
         public String feign(@PathVariable String str) {
             return echoService.echo(str);
         }
      }
      代码说明如下:
      • /echo-rest/ 验证通过 RestTemplate 去调用服务提供者。
      • /echo-async-rest/ 验证通过 AsyncRestTemplate 去调用服务提供者。
      • /echo-feign/ 验证通过 FeignClient 去调用服务提供者。
    6. 配置应用名以及监听端口号。
      spring.application.name=service-consumer
      server.port=18082
  3. 本地开发调试。
    1. 启动轻量级配置中心。
      本地开发调试时,需要使用轻量级配置中心,轻量级配置中心包含了 EDAS 服务注册发现服务端的轻量版,详情请参见启动轻量级配置及注册中心
    2. 启动应用。
      • IDE 中启动

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

        轻量级配置中心与应用部署在不同的机器上,需要绑定 hosts,详情请参见启动轻量级配置及注册中心

      • FatJar 启动
        1. 添加 FatJar 打包插件。

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

          <build>
              <plugin>
                  <groupId>com.taobao.pandora</groupId>
                      <artifactId>pandora-boot-maven-plugin</artifactId>
                      <version>2.1.9.1</version>
                      <executions>
                         <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                         </execution>
                       </executions>
              </plugin>
          </build>
        2. 添加完插件后,在工程的主目录下,使用 maven 命令 mvn clean package 进行打包,即可在 target 目录下找到打包好的 FatJar 文件。
        3. 通过 Java 命令启动应用。
          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 之前。
      启动服务,分别进行调用,可以看到调用都成功了。EDAS应用开发HSF开发RESTful
  4. 常见问题处理。
    • AsyncRestTemplate 无法接入服务发现。

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

    • FatJar 打包插件冲突。

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

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

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

      通过修改 pandora-boot-maven-plugin 插件,把 excludeSar 设置为 false,打包时就会自动包含 taobao-hsf.sar。
      <plugin>
          <groupId>com.taobao.pandora</groupId>
          <artifactId>pandora-boot-maven-plugin</artifactId>
          <version>2.1.9.1</version>
          <configuration>
          <excludeSar>false</excludeSar>
          </configuration>
             <executions>
                 <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                  </execution>
          </executions>
      </plugin>
      这样打包后可以在不配置 Pandora 地址的情况下启动。
      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

  1. 在 Maven 中配置 EDAS 的私服地址。
    目前 Pandora Boot Starter 相关的包只发布在 EDAS 的私服中,所以需要在 Maven(要求 3.x 及后续版本)配置文件settings.xml中配置 EDAS 的私服地址,详情请参见配置私服地址和轻量级配置及注册中心
  2. 修改代码。
    RESTful 应用接入 EDAS 的 EagleEye 很简单,只需要完成以下三步。
    1. 在 pom.xml 文件中加入如下公共配置。
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-eagleeye</artifactId>
                  <version>1.3</version>
              </dependency>
      
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-pandora</artifactId>
                  <version>1.3</version>
              </dependency>
    2. 在 main 函数中添加修改配置。
      假设修改之前的 main 函数内容如下:
      public static void main(String[] args) {
          SpringApplication.run(ServerApplication.class, args);
      }
      则修改为:
      public static void main(String[] args) {
          PandoraBootstrap.run(args);
          SpringApplication.run(ServerApplication.class, args);
          PandoraBootstrap.markStartupAndWait();
      }
    3. 添加 FatJar 打包插件。
      使用 Maven 将 pandora-boot 工程打包成 FatJar, 需要在pom.xml中添加如下插件。

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

      <build>
          <plugins>
          <plugin>
              <groupId>com.taobao.pandora</groupId>
              <artifactId>pandora-boot-maven-plugin</artifactId>
              <version>2.1.9.1</version>
              <executions>
              <execution>
                  <phase>package</phase>
                  <goals>
                  <goal>repackage</goal>
                  </goals>
                  </execution>
              </executions>
          </plugin>
          </plugins>
      </build>

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

全链路跟踪示例

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

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

  • /rest/ok,对应正常的调用全链路跟踪示例rest_ok
  • /rest/delay,对应延迟较大的调用全链路跟踪示例rest_delay
  • /rest/error,对应异常出错的调用全链路跟踪示例rest_error
  1. 部署应用。
    EagleEye 的采集和分析功能都搭建在 EDAS 上,为了演示调用链查看功能,我们首先将 service1 和 service2 这两个应用部署到 EDAS 中,具体详情请参见如下文档。
  2. 查看服务调用链。
    部署完毕之后,为了能够查看调用链的信息,我们还需要调用 service1 三个场景演示的入口对应的方法。您可以通过执行 curl http://{$ip:$port}/rest/ok 这种简单的方式来调用。也可以使用 postman 等工具或者直接在浏览器中调用。为了便于观察,建议使用脚本等方式多调用几次。然后按以下步骤查看调用链。
    • 登录 EDAS 控制台,进入刚刚部署的应用中
    • 在应用详情页面左侧的导航栏中选择应用监控 > 接口调用
    • 接口调用页面进行查看。

    更详细的使用信息,请参考应用接口调用监控

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

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

    • AsyncRestTemplate

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

      @Autowired
      private AsyncRestTemplate eagleEyeAsyncRestTemplate;
    • FatJar 打包插件

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