Develop HSF applications (Pandora Boot)

更新时间:
复制 MD 格式

Use Pandora Boot to develop High-speed Service Framework (HSF) applications. You can implement service registration and discovery, perform asynchronous calls, and run unit tests. Unlike deploying HSF WAR packages with Ali-Tomcat, Pandora Boot deploys JAR packages. You can directly package an HSF application as a FatJar. This approach aligns better with the microservice style and makes application deployment more flexible because it does not require an external Ali-Tomcat. Pandora Boot can be considered an enhancement of Spring Boot.

Prerequisites

Service registration and discovery

This topic describes how to use Pandora Boot to develop applications that include a service provider and a service consumer to implement service registration and discovery.

Important

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

Download the demo source code.

Clone the entire project using Git. You can find the sample project used in this topic in the microservice-doc-demo/hsf-pandora-boot folder.

  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>

      Although the HSF service framework does not depend on a web environment, web-related features are required during the application lifecycle. Therefore, you must add the spring-boot-starter-web dependency.

      pandora-hsf-spring-boot-starter implements automatic configuration for HSF. pandora-boot-maven-plugin is a Maven packaging plugin provided by Pandora Boot. This plugin compiles a Pandora Boot HSF project into an executable FatJar. You can then deploy and run the package in EDAS Container.

      dependencyManagement contains the spring-boot-dependencies and pandora-boot-starter-bom dependencies. These dependencies manage the versions of the Spring Boot and Pandora Boot dependencies. After you add them, you do not need to set the parent of your project to spring-boot-starter-parent.

    3. Define a service interface. Create an interface class com.alibaba.edas.HelloService.

      The HSF service framework uses interfaces for service communication. A producer implements and publishes a service through a defined interface, and a consumer subscribes to and consumes the service based on the same interface.

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

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

    4. Add the EchoServiceImpl implementation class for the service provider and publish the service using an annotation.

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

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

      Note
      • Configurations in the annotation have the highest priority.

      • If a property is not configured in the annotation, the system searches for the global configuration of the property in the resources/application.properties file when the service is published.

      • If the property is not configured in the annotation or the resources/application.properties file, the default value in the annotation is used.

    5. In the resources directory, configure the application name and listening port in the application.properties file.

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

      Configure both the service version (spring.hsf.version) and service timeout (spring.hsf.timeout) in the application.properties file.

    6. Add the main function entry point to start 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 that the service has started and set the thread to wait. This prevents the container from exiting after the business code finishes running.
                PandoraBootstrap.markStartupAndWait();
            }
        }
      Table 1. Service provider properties

      Property

      Required

      Description

      Type

      Default value

      serviceInterface

      Yes

      The interface that the service exposes.

      Class

      java.lang.Object

      serviceVersion

      No

      The version number of the service.

      String

      1.0.0.DAILY

      serviceGroup

      No

      The group name of the service.

      String

      HSF

      clientTimeout

      No

      This configuration applies to all methods in the interface. However, if the client configures a timeout for a specific method using the `methodSpecials` property, the client's configuration takes precedence for that method. Other methods are not affected and still use the server-side configuration. Unit: ms.

      int

      -1

      corePoolSize

      No

      The minimum number of active threads allocated from the shared thread pool specifically for this service.

      int

      0

      maxPoolSize

      No

      The maximum number of active threads allocated from the shared thread pool specifically for this service.

      int

      0

      delayedPublish

      No

      Specifies whether to delay publishing the service.

      boolean

      false

      includeFilters

      No

      Optional custom filters.

      String[]

      Empty

      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. Service creation and publishing limits

      Name

      Example

      Size limit

      Adjustable

      {Service name}:{Version number}

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

      Up to 192 bytes

      No

      Group name

      aliware

      Up to 32 bytes

      No

      Number of services published by a Pandora application instance

      N/A

      Up to 800

      Yes. In the navigation pane on the left, click Basic Information. On the Basic Information tab, in the Application Settings section, click Edit to the right of JVM Parameters. In the Application Settings dialog box that appears, select Custom > Custom Parameters. In the input box, add the -DCC.pubCountMax=1200 property parameter. You can adjust this value based on the actual number of services your application publishes.

  2. Create a service consumer.

    In this example, you will create a service consumer that calls the service provider using the API operations 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 are the same as for the provider.

        <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 API service interface published by the service provider, including the package name, to the consumer project, such as com.alibaba.edas.HelloService.

        public interface HelloService {
            String echo(String string);
        }
    4. Inject the service consumer instance into the Spring context using an annotation.

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

      You can configure @HSFConsumer once in the HsfConfig class, and then inject it for use in multiple locations with @Autowired. Although the @HSFConsumer annotation is used in multiple locations, you do not need to mark each location with @HSFConsumer. Instead, you can create a unified HsfConfig class and inject it directly with @Autowired where needed.

    5. For testing purposes, use SimpleController to expose an /hsf-echo/* HTTP interface. The /hsf-echo/* interface internally calls 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. In the resources directory, configure the application name and listening port in the application.properties file.

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

      Configure both the service version and service timeout in the application.properties file.

    7. Add the main function entry point to start the service.

        @SpringBootApplication
        public class HSFConsumerApplication {
      
            public static void main(String[] args) {
                PandoraBootstrap.run(args);
                SpringApplication.run(HSFConsumerApplication.class, args);
                PandoraBootstrap.markStartupAndWait();
            }
        }
      Table 3. Service consumer properties

      Property

      Required

      Description

      Type

      Default value

      serviceGroup

      No

      The group name of the service.

      String

      HSF

      serviceVersion

      No

      The version number of the service.

      String

      1.0.0.DAILY

      clientTimeout

      No

      The timeout for all methods in the client interface. Unit: ms.

      int

      -1

      generic

      No

      Specifies whether to support generalized calls.

      boolean

      false

      addressWaitTime

      No

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

      int

      3000

      proxyStyle

      No

      The proxy style. Valid values: `JDK` and `Javassist`.

      String

      jdk

      futureMethods

      No

      A list of method names that must be called asynchronously when this service is invoked, and the asynchronous invocation method. The default value is empty, which means all methods are called synchronously.

      String[]

      Empty

      consistent

      No

      Specifies whether to use consistent hashing for load balancing.

      String

      Empty (An empty value indicates that consistent hashing is not used).

      methodSpecials

      No

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

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

      Empty

      Table 4. Global configuration parameters for the service provider and consumer

      Property

      Required

      Description

      Type

      Default value

      spring.hsf.version

      No

      The global version number for services. You can also use spring.hsf.versions.<full service interface name>=<version number for this specific interface, String type> to set a version number for a specific service. For example: spring.hsf.versions.com.aliware.edas.EchoService="1.0.0".

      String

      1.0.0.DAILY

      spring.hsf.group

      No

      The global group name for services. You can also use spring.hsf.groups.<full service interface name>=<group name for this specific interface, String type> to set a group name for a specific service.

      String

      HSF

      spring.hsf.timeout

      No

      The global timeout for services. You can also use spring.hsf.timeouts.<full service interface name>=<timeout, String type> to set a timeout for a specific service.

      Integer

      None

      spring.hsf.max-wait-address-time

      No

      The global time to wait for the service registry (ConfigServer) to push the service provider address. Unit: ms. You can also use spring.hsf.max-wait-address-times.<full service interface name>=<wait time, String type> to set the wait time for a specific service.

      Integer

      3000

      spring.hsf.delay-publish

      No

      The global switch for delayed service publishing. Valid values: `true` or `false`. You can also use spring.hsf.delay-publishes.<full service interface name>=<whether to delay publishing, String type> to set a delay for a specific service.

      String

      None

      spring.hsf.core-pool-size

      No

      The global minimum number of active threads for services. You can also use spring.hsf.core-pool-sizes.<full service interface name>=<minimum active threads, String type> to set the minimum number of active threads for a specific service.

      int

      None

      spring.hsf.max-pool-size

      No

      The global maximum number of active threads for services. You can also use spring.hsf.max-pool-sizes.<full service interface name>=<maximum active threads, String type> to set the maximum number of active threads for a specific service.

      int

      None

      spring.hsf.serialize-type

      No

      The global serialization type for services. Valid values: `Hessian` or `Java`. You can also use spring.hsf.serialize-types.<full service interface name>=<serialization type> to set the serialization type for a specific service.

      String

      None

      Note

      You can set global configuration parameters in the application.properties file of a Pandora Boot application.

Local development and debugging

  1. Configure the lightweight configuration and registry center.

    For local development and debugging, you must use the lightweight configuration and registry center. This center includes a lightweight version of the service registration and discovery server. For more information, see Start the lightweight configuration and registry center.

  2. Start the application.

    • Start in an IDE

      Configure the -Djmenv.tbsite.net={$IP} startup parameter in the VM options and start the application from the main method. {$IP} is the IP address of the lightweight configuration center. For example, if you start the lightweight configuration center on your local machine, {$IP} is 127.0.0.1.

      Alternatively, you can modify the hosts file to bind jmenv.tbsite.net to the IP address of the lightweight configuration center instead of configuring JVM parameters. For more information, see Start the lightweight configuration and registry center.

    • Start using a FatJar

      1. Add the `taobao-hsf.sar` dependency. This step downloads the required dependency to `${USER_HOME}/.m2/repository/com/taobao/pandora/taobao-hsf.sar/2019-06-stable/taobao-hsf.sar-2019-06-stable.jar`, which is required for the startup parameters.

           <dependency>
                <groupId>com.taobao.pandora</groupId>
                <artifactId>taobao-hsf.sar</artifactId>
                <version>2019-06-stable</version>
            </dependency>
      2. Use Maven to package the Pandora Boot project as a FatJar. You need to add the following plugin to the pom.xml file. To avoid conflicts with other packaging plugins, do not add other FatJar plugins to the `plugins` section of the 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 plugin, run the mvn clean package command in the project's home directory to package the project. You can find the packaged FatJar file in the Target directory.

      4. Start the application by running a 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 from the command line, you must explicitly specify the location of `taobao-hsf.sar`.

        • Replace the ${USER_HOME} parameter based on your operating system.

          • macOS/Linux: /Users/<current_user>.

          • Windows: C:\Users\<current_user>.

    Access the address of the machine where the consumer is located. This triggers the consumer to remotely call the provider.

    curl localhost:8080/hsf-echo/helloworld
    helloworld

Unit testing

You can run Pandora Boot unit tests using `PandoraBootRunner`, which is seamlessly integrated with `SpringJUnit4ClassRunner`.

The following example shows how to perform a unit test in the service provider.

  1. In Maven, add the necessary dependencies for Pandora Boot and Spring Boot testing.

      <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. You can write the code for the test class.

    @RunWith(PandoraBootRunner.class)
      @DelegateTo(SpringJUnit4ClassRunner.class)
      // Load the classes required for the test. Be sure to add the Spring Boot startup class and this test class.
      @SpringBootTest(classes = {HSFProviderApplication.class, HelloServiceTest.class })
      @Component
      public class HelloServiceTest {
    
          /**
           * When you use @HSFConsumer, you must load this class in the @SpringBootTest class loading process and use this class to inject the object. Otherwise, a class conversion exception occurs during generalization.
           */
          @HSFConsumer(generic = true)
          HelloService helloService;
    
          // A regular call.
          @Test
          public void testInvoke() {
              TestCase.assertEquals("hello world", helloService.echo("hello world"));
          }
          // A generalized 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);
          }
          // Mock the return value.
          @Test
          public void testMock() {
              HelloService mock = Mockito.mock(HelloService.class, AdditionalAnswers.delegatesTo(helloService));
              Mockito.when(mock.echo("")).thenReturn("beta");
              TestCase.assertEquals("beta", mock.echo(""));
          }
      }