All Products
Search
Document Center

Enterprise Distributed Application Service:Use Pandora Boot to develop HSF applications

Last Updated:Feb 22, 2024

You can use Pandora Boot to develop High-speed Service Framework (HSF) applications and implement service registration and discovery, asynchronous calls, and unit testing. A WAR package is required when you deploy an HSF application in Ali-Tomcat, whereas a JAR package is required when Pandora Boot is used. You can build the HSF application into a FatJar package, which is more consistent with the microservices architecture. This method does not depend on Ali-Tomcat and makes application deployment more flexible. Pandora Boot is an enhancement of Spring Boot.

Prerequisites

Before you develop an application, make sure that the following operations are complete:

Service registration and discovery

This section describes how to develop applications by using Pandora Boot and implement service registration and discovery. The applications include a service provider and a service consumer.

Important

Do not call HSF remote services when you start an application. Otherwise, the application fails to be started.

Download the demo source code. For more information, see Demo source code.

Clone the whole project from GitHub and find the demo project that is used in this topic in the microservice-doc-demo/hsf-pandora-boot directory.

  1. Create a service provider.

    1. Create a Maven project named hsf-pandora-boot-provider.

    2. Add the required dependencies to the pom.xml file.

      <properties>
            <java.version>1.8</java.version>
            <spring-boot.version>2.1.6.RELEASE</spring-boot.version>
            <pandora-boot.version>2019-06-stable</pandora-boot.version>
        </properties>
      
        <dependencies>
            <dependency>
                <groupId>com.alibaba.boot</groupId>
                <artifactId>pandora-hsf-spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
        </dependencies>
      
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>${spring-boot.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>com.taobao.pandora</groupId>
                    <artifactId>pandora-boot-starter-bom</artifactId>
                    <version>${pandora-boot.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
      
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.7.0</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>com.taobao.pandora</groupId>
                    <artifactId>pandora-boot-maven-plugin</artifactId>
                    <version>2.1.11.8</version>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>

      HSF is independent of the web environment. However, you must add the spring-boot-starter-web dependency because web-related features are required in the application lifecycle.

      pandora-hsf-spring-boot-starter implements automatic installation and configuration of HSF. pandora-boot-maven-plugin is a Maven packaging plug-in that is provided by Pandora Boot. This plug-in can compile a Pandora Boot HSF project as an executable FatJar package and then deploy and run the package in Enterprise Distributed Application Service (EDAS) Container.

      dependencyManagement consists of the spring-boot-dependencies and pandora-boot-starter-bom dependencies. You can use the dependencies to separately manage the versions of related Spring Boot and Pandora Boot dependencies without the need to set parent to spring-boot-starter-parent for your project.

    3. Define a service interface, and create an interface class named com.alibaba.edas.HelloService.

      HSF implements service communication based on interfaces. After an interface is defined, it is used by producers to implement and publish services and by consumers to subscribe to and consume services.

        public interface HelloService {
            String echo(String string);
        }

      The com.alibaba.edas.HelloService interface provides the echo method.

    4. Add the EchoServiceImpl implementation class of the service provider, and publish the service by using annotations.

        @HSFProvider(serviceInterface = HelloService.class, serviceVersion = "1.0.0")
        public class HelloServiceImpl implements HelloService {
            @Override
            public String echo(String string) {
                return string;
            }
        }

      In HSF applications, a service is uniquely identified by the interface name and service version. Therefore, you must add the com.alibaba.edas.HelloService interface name and the 1.0.0 service version to the HSFProvider annotation.

      Note
      • The configurations in the HSFProvider annotation have a higher priority.

      • If properties are not configured in the HSFProvider annotation, the global configurations of these properties in the resources/application.properties file are searched first when the service is published.

      • If properties are not configured in the HSFProvider annotation or the resources/application.properties file, the default values in the annotation are used.

    5. Configure the application name and the listener port number in the application.properties file in the resources directory.

        spring.application.name=hsf-pandora-boot-provider
        server.port=8081
      
        spring.hsf.version=1.0.0
        spring.hsf.timeout=3000
      Note

      We recommend that you configure both the service version (spring.hsf.version) and service timeout period (spring.hsf.timeout) in the application.properties file.

    6. Add the main function handler for starting the service.

       @SpringBootApplication
        public class HSFProviderApplication {
      
            public static void main(String[] args) {
                // Start Pandora Boot to load the Pandora container. 
                PandoraBootstrap.run(args);
                SpringApplication.run(HSFProviderApplication.class, args);
                // Mark the service as started and specify the thread wait time. This prevents the container from exiting after you run the service code and exit. 
                PandoraBootstrap.markStartupAndWait();
            }
        }
      Table 1: Properties of the service provider

      Property

      Required

      Description

      Type

      Default value

      serviceInterface

      Yes

      The interface that provides services.

      Class

      java.lang.Object

      serviceVersion

      No

      The version of the service.

      String

      1.0.0.DAILY

      serviceGroup

      No

      The group name of the service.

      String

      HSF

      clientTimeout

      No

      This property applies to all methods in the interface. However, if a timeout period is configured for a method of the consumer by using the methodSpecials property, the configured timeout period takes precedence over this property value for this method. Other methods still use the timeout period configured for the provider. Unit: milliseconds.

      int

      -1

      corePoolSize

      No

      The minimum number of active threads that are allocated from the public thread pool for the service.

      int

      0

      maxPoolSize

      No

      The maximum number of active threads that are allocated from the public thread pool for the service.

      int

      0

      delayedPublish

      No

      Specifies whether to delay the service publishing.

      boolean

      false

      includeFilters

      No

      The custom filters that you can use.

      String[]

      Null

      enableTXC

      No

      Specifies whether to enable Global Transaction Service (GTS) for distributed transactions.

      boolean

      false

      serializeType

      No

      The serialization type of the service interface. Valid values: hessian and java.

      String

      hessian

      supportAsynCall

      No

      Specifies whether to support asynchronous calls.

      String

      false

      Table 2: Limits on service creation and publishing

      Item

      Example

      Upper limit

      Adjustable

      {Service name}:{Version number}

      com.alibaba.edas.testcase.api.TestCase:1.0.0

      192 bytes

      No

      Group name

      aliware

      32 bytes

      No

      Number of services published for a Pandora application instance

      N/A

      800

      Yes. In the left-side navigation pane of the application details page, click Basic Information. In the Application Settings section of the Basic Information tab, click Edit on the right side of JVM Parameters. In the Application Settings dialog box, click Custom and enter -DCC.pubCountMax=1200 in the Custom Parameters field. You can change the value of DCC.pubCountMax based on the number of services published for the application.

  2. Create a service consumer.

    In this example, a service consumer is created to call the service provider by using the interfaces provided by HSFConsumer.

    1. Create a Maven project named hsf-pandora-boot-consumer.

    2. Add the required dependencies to the pom.xml file.

      Note

      The Maven dependencies for the consumer and provider are the same.

        <properties>
            <java.version>1.8</java.version>
            <spring-boot.version>2.1.6.RELEASE</spring-boot.version>
            <pandora-boot.version>2019-06-stable</pandora-boot.version>
        </properties>
      
        <dependencies>
            <dependency>
                <groupId>com.alibaba.boot</groupId>
                <artifactId>pandora-hsf-spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
        </dependencies>
      
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>${spring-boot.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>com.taobao.pandora</groupId>
                    <artifactId>pandora-boot-starter-bom</artifactId>
                    <version>${pandora-boot.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
      
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.7.0</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>com.taobao.pandora</groupId>
                    <artifactId>pandora-boot-maven-plugin</artifactId>
                    <version>2.1.11.8</version>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    3. Copy the service interface that is published by the service provider, such as the com.alibaba.edas.HelloService interface, to the local environment. The package name is also copied.

        public interface HelloService {
            String echo(String string);
        }
    4. Use annotations to inject the service consumer instance to the Spring context.

       @Configuration
        public class HsfConfig {
      
            @HSFConsumer(clientTimeout = 3000, serviceVersion = "1.0.0")
            private HelloService helloService;
      
        }
      Note

      Configure an @HSFConsumer annotation once in the HsfConfig class, and then inject and use the annotation in multiple places by using @Autowired. In most cases, an @HSFConsumer annotation is used in multiple places, but you do not need to use @HSFConsumer to mark each place where the annotation is used. You need to only write an HsfConfig class and inject it by using @Autowired.

    5. To facilitate testing, you can use SimpleController to expose an /hsf-echo/* HTTP interface. The /hsf-echo/* interface provides built-in capabilities to call the HSF service provider.

        @RestController
        public class SimpleController {
      
            @Autowired
            private HelloService helloService;
      
            @RequestMapping(value = "/hsf-echo/{str}", method = RequestMethod.GET)
            public String echo(@PathVariable String str) {
                return helloService.echo(str);
            }
        }
    6. Configure the application name and the listener port number in the application.properties file in the resources directory.

        spring.application.name=hsf-pandora-boot-consumer
        server.port=8080
      
        spring.hsf.version=1.0.0
        spring.hsf.timeout=1000
      Note

      We recommend that you specify the service version and timeout period in the application.properties file.

    7. Add the main function handler for starting the service.

        @SpringBootApplication
        public class HSFConsumerApplication {
      
            public static void main(String[] args) {
                PandoraBootstrap.run(args);
                SpringApplication.run(HSFConsumerApplication.class, args);
                PandoraBootstrap.markStartupAndWait();
            }
        }
      Table 3: Properties of the service consumer

      Property

      Required

      Description

      Type

      Default value

      serviceGroup

      No

      The group name of the service.

      String

      HSF

      serviceVersion

      No

      The version of the service.

      String

      1.0.0.DAILY

      clientTimeout

      No

      The timeout period for all methods in the interface of the consumer. Unit: milliseconds.

      int

      -1

      generic

      No

      Specifies whether to support generic calls.

      boolean

      false

      addressWaitTime

      No

      The time used to wait for the service registry (ConfigServer) to push the service provider address. Unit: milliseconds.

      int

      3000

      proxyStyle

      No

      The proxy style. Valid values: JDK and Javassist.

      String

      jdk

      futureMethods

      No

      The names of methods in asynchronous call mode on the service. Default value: Null. A value of Null specifies that all methods are called in synchronous mode.

      String[]

      Null

      consistent

      No

      Specifies whether to use consistent hashing.

      String

      Null (Consistent hashing is not used.)

      methodSpecials

      No

      The method-level timeout period and number of retries, and the method name.

      com.alibaba.boot.hsf.annotation.HSFConsumer.ConsumerMethodSpecial[]

      Null

      Table 4: Global properties for the service provider and the service consumer

      Property

      Required

      Description

      Type

      Default value

      spring.hsf.version

      No

      The global version of the service. If you want to use this property as a local property of the service, specify this property in the following format: spring.hsf.versions.<Complete service interface name>=<Version number separately specified for the service interface, in String format>. Example: spring.hsf.versions.com.aliware.edas.EchoService="1.0.0".

      String

      1.0.0.DAILY

      spring.hsf.group

      No

      The global group name of the service. If you want to use this property as a local property of the service, specify this property in the following format: spring.hsf.groups.<Complete service interface name>=<Group name separately specified for the service interface, in String format>.

      String

      HSF

      spring.hsf.timeout

      No

      The global timeout period of the service. If you want to use this property as a local property of the service, specify this property in the following format: spring.hsf.timeouts.<Complete service interface name>=<Timeout period, in String format>.

      Integer

      None

      spring.hsf.max-wait-address-time

      No

      The global time used to wait for the service registry (ConfigServer) to push the service provider address. Unit: milliseconds. If you want to use this property as a local property of the service, specify this property in the following format: spring.hsf.max-wait-address-times.<Complete service interface name>=<Wait time, in String format>.

      Integer

      3000

      spring.hsf.delay-publish

      No

      The global switch for service publishing delay. Valid values: true and false. If you want to use this property as a local property of the service, specify this property in the following format: spring.hsf.delay-publishes.<Complete service interface name>=<Whether to delay the service publishing, in String format>.

      String

      None

      spring.hsf.core-pool-size

      No

      The minimum number of globally active threads for the service. If you want to use this property as a local property of the service, specify this property in the following format: spring.hsf.core-pool-sizes.<Complete service interface name>=<Minimum number of active threads, in String format>.

      int

      None

      spring.hsf.max-pool-size

      No

      The maximum number of globally active threads for the service. If you want to use this property as a local property of the service, specify this property in the following format: spring.hsf.max-pool-sizes.<Complete service interface name>=<Maximum number of active threads, in String format>.

      int

      None

      spring.hsf.serialize-type

      No

      The global serialization type of the service. Valid values: Hessian and Java. If you want to use this property as a local property of the service, specify this property in the following format: spring.hsf.serialize-types.<Complete service interface name>=<Serialization type>.

      String

      None

      Note

      You can configure global properties in the application.properties file of Pandora Boot applications.

Local code development and debugging

  1. Configure the lightweight configuration and registry center.

    You must use the lightweight configuration and registry center for local code development and debugging, which includes a lightweight service registry. For more information, see Start the lightweight configuration center.

  2. Start the application by using one of the following methods:

    • Start the application in an integrated development environment (IDE).

      To start the application in an IDE, configure the startup parameter -Djmenv.tbsite.net={$IP} by using VM options and start the application by calling the main method. In the startup parameter, {$IP} specifies the IP address of the lightweight configuration center. For example, the value of {$IP} is 127.0.0.1 for the lightweight configuration center that is locally started.

      You can also set jmenv.tbsite.net to the IP address of the lightweight configuration center in the hosts file, without setting JVM parameters. For more information, see Start the lightweight configuration center.

    • Start the application by using FatJar.

      1. Add the taobao-hsf.sar dependency to your code to download the ${USER_HOME}/.m2/com/taobao/pandora/taobao-hsf.sar/2019-06-stable/taobao-hsf.sar-2019-06-stable.jar dependency on which the startup parameters in later steps depend.

           <dependency>
                <groupId>com.taobao.pandora</groupId>
                <artifactId>taobao-hsf.sar</artifactId>
                <version>2019-06-stable</version>
            </dependency>
      2. Add the following plug-in to the pom.xml file to build the Pandora Boot project into a FatJar package by using Maven. To prevent conflicts with other packaging plug-ins, do not add configurations of other FatJar plug-ins to the plugin field in build.

            <plugin>
                <groupId>com.taobao.pandora</groupId>
                <artifactId>pandora-boot-maven-plugin</artifactId>
                <version>2.1.11.8</version>
                <executions>
                    <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                    </execution>
                </executions>
            </plugin>
      3. After you add the plug-in, run the mvn clean package command in the home directory of the project to build a package. Then, you can find the packaged FatJar file in the Target directory.

      4. Start the application by running the following Java command:

        java -Djmenv.tbsite.net=127.0.0.1 -Dpandora.location=${USER_HOME}/.m2/repository/com/taobao/pandora/taobao-hsf.sar/2019-06-stable/taobao-hsf.sar-2019-06-stable.jar -jar hsf-pandora-boot-provider-1.0.jar
        Note
        • The path specified by -Dpandora.location must be a full path. When you start the application in the command line, you must explicitly specify the location of taobao-hsf.sar.

        • The value format of ${USER_HOME} varies based on the type of your OS:

          • macOS/Linux: /Users/<Current user>.

          • Windows: C:\Users\<Current user>.

    Access the address of the instance where the consumer is located for the consumer to remotely call services of the provider.

    curl localhost:8080/hsf-echo/helloworld
    helloworld

Unit testing

The Pandora Boot unit testing can be started by PandoraBootRunner and is seamlessly integrated with SpringJUnit4ClassRunner.

The following example demonstrates how to perform unit testing for a service provider.

  1. Add the dependencies required for the Pandora Boot and Spring Boot unit testing in Maven.

      <dependency>
          <groupId>com.taobao.pandora</groupId>
          <artifactId>pandora-boot-test</artifactId>
          <scope>test</scope>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
      </dependency>
  2. Compile the test code.

    @RunWith(PandoraBootRunner.class)
      @DelegateTo(SpringJUnit4ClassRunner.class)
      // Add both the Spring Boot startup class and service test class required for unit testing. 
      @SpringBootTest(classes = {HSFProviderApplication.class, HelloServiceTest.class })
      @Component
      public class HelloServiceTest {
    
          /**
           * If you use @HSFConsumer, you must add the service class to @SpringBootTest and use the class to inject objects to prevent abnormal class conversion during generic calls. 
           */
          @HSFConsumer(generic = true)
          HelloService helloService;
    
          // Perform a common call. 
          @Test
          public void testInvoke() {
              TestCase.assertEquals("hello world", helloService.echo("hello world"));
          }
          // Perform a generic call. 
          @Test
          public void testGenericInvoke() {
              GenericService service = (GenericService) helloService;
              Object result = service.$invoke("echo", new String[] {"java.lang.String"}, new Object[] {"hello world"});
              TestCase.assertEquals("hello world", result);
          }
          // Return the value of Mock. 
          @Test
          public void testMock() {
              HelloService mock = Mockito.mock(HelloService.class, AdditionalAnswers.delegatesTo(helloService));
              Mockito.when(mock.echo("")).thenReturn("beta");
              TestCase.assertEquals("beta", mock.echo(""));
          }
      }