This topic describes how to develop RESTful applications in High-speed Service Framework (HSF) and implement service registration and discovery. Enterprise Distributed Application Service (EDAS) supports native Spring Cloud applications. Therefore, we recommend that new users do not use HSF to develop RESTful applications.

Background information

For more information about how to develop applications in the native Spring Cloud framework, see Host Spring Cloud applications to EDAS.

Service registration and discovery

This topic uses a simple example to describe how to develop RESTful applications and implement service registration and discovery locally.

Download the demo source code: sc-vip-serversc-vip-client

  1. Create a service provider.
    The service provider provides a simple echo service and registers itself with the service registry.
    1. Create a RESTful application project named sc-vip-server.
    2. Add required dependencies to the pom.xml file.
          <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>

      If you do not want to configure the parent of the project as spring-boot-starter-parent, you can add dependencyManagement and set scope=import as follows to manage dependencies:

      <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. Create a service provider application, in which the annotation @EnableDiscoveryClient enables service registration and discovery for the application.
      @SpringBootApplication
          @EnableDiscoveryClient
          public class ServerApplication {
      
              public static void main(String[] args) {
                  PandoraBootstrap.run(args);
                  SpringApplication.run(ServerApplication.class, args);
                  PandoraBootstrap.markStartupAndWait();
              }
          }
    4. Create an EchoController to provide simple echo services.
      @RestController
          public class EchoController {
              @RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)
              public String echo(@PathVariable String string) {
                  return string;
              }
          }
    5. Configure the application name and the listener port number in the application.properties file in the resources directory.
      spring.application.name=service-provider
      server.port=18081
  2. Create a service consumer.
    In this example, a service consumer is created to call the service provider through RestTemplate, AsyncRestTemplate, and FeignClient.
    1. Create a RESTful application project named sc-vip-client.
    2. Add required dependencies to the pom.xml file.
      <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>

      This example uses FeignClient for demonstration. Compared with sc-vip-server (service provider), the pom.xml file contains the spring-cloud-starter-feign dependency.

    3. In addition to enabling service registration and discovery as in sc-vip-server, add the following two annotations to enable RestTemplate, AsyncRestTemplate, and FeignClient:
      • Add the annotation @LoadBalanced to combine RestTemplate, AsyncRestTemplate, and service registry.
      • Add the annotation @EnableFeignClients to activate FeignClient.
        @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. Configure the service name and the HTTP request of the HTTP method before using FeignClient of EchoService. In the sc-vip-server project, set the service name to service-provider.
      @FeignClient(name = "service-provider")
          public interface EchoService {
              @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
              String echo(@PathVariable("str") String str);
          }
    5. Create a Controller for call test.
      @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);
         }
      }
      The code is described as follows:
      • /echo-rest/ calls the service from the service provider through RestTemplate.
      • /echo-async-rest/ calls the service from the service provider through AsyncRestTemplate.
      • /echo-feign/ calls the service from the service provider through FeignClient.
    6. Configure the application name and the listener port number.
      spring.application.name=service-consumer
      server.port=18082
  3. Perform local code development and debugging.
    1. Start the light-weight configuration registry.
      The light-weight configuration registry must be started for local code development and debugging, which includes a light-weight EDAS service registry for service providers. For more information about the light-weight configuration registry, see Start the light-weight configuration registry.
    2. Start the application.
      • Start the application in an integrated development environment (IDE)

        To start the application in IDE, configure the startup parameter -Dvipserver.server.port=8080 in VM options and directly start the application by calling the main method. This parameter is added only when the application is locally deployed and the light-weight configuration registry is used. When the application is deployed in EDAS, remove this parameter because it disables application release or subscription.

        The light-weight configuration registry and the application are deployed on different instances and need to be bound in the hosts file. For more information, see Start the light-weight configuration registry.

      • Start the application by using FatJar
        1. Add a FatJar packaging plug-in.

          To package the pandora-boot project into a FatJar package by using Maven, add the following plug-in to pom.xml. To prevent conflicts with other packaging plug-ins, do not add configurations of any other FatJar plug-ins to the plugin field in build.

          <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. After adding the plug-in, run the mvn clean package command in the home directory of the project to create a FatJar package in the target directory.
        3. Start the application by running the following Java command:
          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
          Note The path specified by -Dpandora.location must be a full path placed before sc-vip-server-0.0.1-SNAPSHOT.jar.
      Start the service consumer and run the corresponding curl command to call the service provider. Calls based on RestTemplate, AsyncRestTemplate, FeignClient are all successful.
  4. Troubleshoot common issues.
    • What can I do if I cannot enable service registration and discovery for AsyncRestTemplate?

      AsyncRestTemplate provides service registration and discovery only in Spring Cloud Dalston and later versions. For more information, see pull request.

    • What can I do if a FatJar packaging plug-in conflict occurs?

      To prevent conflicts with other packaging plug-ins, do not add configurations of any other FatJar plug-ins to the plugin field in build.

    • Can taobao-hsf.sar be included during packaging?

      Yes, but this is not recommended.

      You can modify pandora-boot-maven-plugin and set excludeSar to false to automatically add taobao-hsf.sar to the package file.
      <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>
      In this way, the package can be started even if the Pandora address is not configured.
      java -jar  -Dvipserver.server.port=8080 sc-vip-server-0.0.1-SNAPSHOT.jar

      Restore the configuration to exclude the taobao-hsf.sar package before deploying an application in EDAS.

Distributed tracing

You can simply modify your RESTful application locally and connect it to EagleEye of EDAS to enable distributed tracing.

To reduce development costs and improve development efficiency, EDAS provides EagleEye, a component for distributed tracing. After EagleEye tracking is configured in the code, you can use the distributed tracing function of EDAS, without considering log collection, analysis, and storage.

Download the demo source code service1 and service2.

Access EagleEye

  1. Configure the local repository path of EDAS in Maven.
    Currently, Pandora Boot Starter-related packages are only published in the local repository of EDAS. Therefore, you must configure the local repository path in the settings.xml configuration file of Maven (V3.x or later). For more information, see Configure the local repository path and light-weight configuration registry of EDAS.
  2. Modify the code.
    You can connect RESTful applications to EDAS EagleEye in the following steps:
    1. Add the following public settings to the pom.xml file:
              <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. Modify the code in the main function.
      The original content of the main function is as follows:
      public static void main(String[] args) {
          SpringApplication.run(ServerApplication.class, args);
      }
      The main function is modified as follows:
      public static void main(String[] args) {
          PandoraBootstrap.run(args);
          SpringApplication.run(ServerApplication.class, args);
          PandoraBootstrap.markStartupAndWait();
      }
    3. Add a FatJar packaging plug-in.
      To package the pandora-boot project into a FatJar package by using Maven, add the following plug-in to pom.xml.

      To prevent conflicts with other packaging plug-ins, do not add configurations of any other FatJar plug-ins to the plugin field in build.

      <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>

      After finishing the preceding steps, you can use the EDAS distributed tracing function without setting up any collection and analysis systems.

Distributed tracing example

To demonstrate how to perform distributed tracing, two application demos service1 and service2 are used in this example.

service2 calls service1, resulting in three types of responses.

  • /rest/ok for normal calls
  • /rest/delay for calls with a large delay
  • /rest/error for calls with errors
  1. Deploy an application.
    The collection and analysis functions of EagleEye are set up in EDAS. To demonstrate the trace query function, deploy the two applications service1 and service2 in EDAS. For more information, see the following topics:
  2. View the trace information.
    To view the trace information after the application is deployed, you have to know the call methods for calling service1 in each of the three demonstration scenarios. You can run the curl http://{$ip:$port}/rest/ok command. You can also use tools such as Postman, or directly call the methods in your browser. To observe the response, we recommend that you call the methods in script or any other mode multiple times. Then follow these steps to view the trace information:
    • Log on to the EDAS console and access the application you deployed.
    • In the left-side navigation pane, choose Application Monitoring > Interface Call.
    • View the trace information on the Interface Call page.
  3. Perform demonstration on other clients.
    EagleEye implements auto tracking for RestTemplate, AsyncRestTemplate, and FeignClient in /echo-rest/{str}, /echo-async-rest/{str}, and /echo-feign/{str} of service1. You can view the trace information in the same way after calling them.
  4. Rectify common issues.
    • Auto tracking

      Currently, EagleEye of EDAS supports auto tracking for requests of RestTemplate, AsyncRestTemplate, and FeignClient. We will provide auto tracking of more components.

    • AsyncRestTemplate

      As AsyncRestTemplate must modify the auto tracking configuration during class instantiation, injection of the object eagleEyeAsyncRestTemplate, which supports service discovery by default, is required to enable distributed tracing.

      @Autowired
      private AsyncRestTemplate eagleEyeAsyncRestTemplate;
    • FatJar packaging plug-in

      To use Maven to package the pandora-boot project into a FatJar package, add pandora-boot-maven-plugin to pom.xml. To prevent conflicts with other packaging plug-ins, do not add configurations of any other FatJar plug-ins to the plugin field in build.