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 you 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 Implement service registration and discovery.

Service registration and discovery

This topic provides a simple example on how to develop RESTful applications and implement service registration and discovery in a local environment.

Source code of the demo:
  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 that is named sc-vip-server.
    2. Add the 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 set the parent of the project to spring-boot-starter-parent, you can add dependencyManagement and set scope=import 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 @EnableDiscoveryClient annotation 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 EchoController to provide a simple echo service.
      @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 by using RestTemplate, AsyncRestTemplate, and FeignClient.
    1. Create a RESTful application project that is named sc-vip-client.
    2. Add the 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>

      FeignClient is used in this example for demonstration. Compared with the service provider sc-vip-server, the pom.xml file contains the spring-cloud-starter-feign dependency.

    3. Enable service registration and discovery for sc-vip-client. This is the same as sc-vip-server. Compared with sc-vip-server, you must also add the following two annotations to use RestTemplate, AsyncRestTemplate, and FeignClient:
      • Add the @LoadBalanced annotation to combine RestTemplate and AsyncRestTemplate with the service discovery.
      • Use the @EnableFeignClients annotation 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 you use 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 testing.
      @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);
         }
      }
      Code description:
      • /echo-rest/ calls the service from the service provider by using RestTemplate.
      • /echo-async-rest/ calls the service from the service provider by using AsyncRestTemplate.
      • /echo-feign/ calls the service from the service provider by using 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 center.
      The light-weight configuration center 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 center, 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 an IDE, set the -Dvipserver.server.port=8080 startup parameter in VM options and start the application by calling the main method. This parameter is added only when the application is deployed in a local environment and the light-weight configuration center is used. When the application is deployed in EDAS, remove this parameter. Otherwise, the application cannot be released or subscribed to as expected.

        The light-weight configuration center and the application are deployed on different instances and their configurations must be added to 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 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 you add the plug-in, in the home directory of the project, run the Maven command mvn clean package for packaging. Then, you can view the 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 in -Dpandora.location must be a full path that is placed before sc-vip-server-0.0.1-SNAPSHOT.jar.
      Start the service consumer and call the service provider. The calls are successful. Develop RESTful applications in HSF and deploy them in EDAS
  4. Troubleshoot FAQ.
    • Why am I unable to enable service discovery by using AsyncRestTemplate?

      You can enable service discovery by using AsyncRestTemplate only in Spring Cloud Dalston and later versions. For more information, see Pull requests.

    • What can I do when FatJar packaging plug-ins conflict with other plug-ins?

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

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

      Yes, you can add taobao-hsf.sar to a package. However, we recommend that you do not add it to a package.

      You can modify pandora-boot-maven-plugin by setting excludeSar to false so that taobao-hsf.sar is automatically added to the package during packaging.
      <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>
      This way, the package can be started without configuring the address of pandora-boot-maven-plugin.
      java -jar  -Dvipserver.server.port=8080 sc-vip-server-0.0.1-SNAPSHOT.jar

      Restore the configuration to exclude taobao-hsf.sar before you deploy the application in EDAS.

Distributed tracing

You can modify your RESTful application in a local environment and connect the application to EagleEye of EDAS to enable distributed tracing.

To reduce development costs and make development efficient, EDAS provides the EagleEye component for distributed tracing. After the EagleEye tracking point is configured in the code, you can use the distributed tracing feature of EDAS without considering log collection, analysis, and storage.

Source code of the demo: service1 and service2.

Connect to EagleEye

  1. Configure the internal repository path of EDAS in Maven.
    The packages related to Pandora Boot Starter are published in the internal repository of EDAS. Therefore, you must configure the internal repository path in the settings.xml configuration file of Maven V3.x or later. For more information, see Configure the internal repository path and the light-weight configuration center of EDAS.
  2. Modify the code.
    You can connect RESTful applications to EagleEye of EDAS by performing 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 following code shows the original content of the main function:
      public static void main(String[] args) {
          SpringApplication.run(ServerApplication.class, args);
      }
      The following code shows the main function after modification:
      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 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 you complete the preceding three steps, you do not need to set up a collection and analysis system and can directly use the EDAS distributed tracing feature.

Examples of distributed tracing

To demonstrate how to use the distributed tracing feature, two application demos are used in this example: service1 and service2.

The demo application service1 works as an entrance and provides services for the following three demonstration scenarios:

  • /rest/ok for normal callsDistributed tracing example rest_ok
  • /rest/delay for calls that have a long delayDistributed tracing example rest_delay
  • /rest/error for calls that have exceptionsDistributed tracing example rest_error
  1. Deploys an application.
    The collection and analytics features of EagleEye are built on top of EDAS. To demonstrate how to perform trace queries, deploy service1 and service2 in EDAS first. For more information, see the following topics:
  2. View the trace information.
    To view the trace information after the applications are deployed, familiarize yourself with the corresponding methods for calling service1 in 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 mode multiple times. Then, perform the following steps to view the trace information:
    • Log on to the EDAS console and find the application that you have deployed.
    • In the left-side navigation pane, choose Application Monitoring > Interface Call.
    • On the Interface Call page, view the trace information.
  3. Perform demonstration on other clients.
    EagleEye implements automatic 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 you call them.

More information

  • Automatic tracking

    EagleEye of EDAS automatically tracks the requests of the RestTemplate, AsyncRestTemplate, and FeignClient calls. In the future, more components will support automatic tracking.

  • AsyncRestTemplate

    AsyncRestTemplate must modify the automatic tracking configuration during the class instantiation phase. Therefore, the eagleEyeAsyncRestTemplate object must be injected to enable the distributed tracing feature. By default, this object supports service discovery.

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

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