全部产品
云市场

开发 HSF 应用(Pandora Boot)

更新时间:2019-09-29 11:47:52

您可以使用 Pandora Boot 开发 HSF 应用,实现服务注册发现、异步调用,并完成单元测试。相比使用 ali-tomcat 部署 HSF 的 war 包,Pandora Boot 部署的是 jar 包。直接将 HSF 应用打包成 FatJar,这更加符合微服务的风格,不需要依赖外置的 ali-tomcat 也使得应用的部署更加灵活。Pandora Boot 可以认为是 Spring Boot 的增强。

前提条件

在开发应用前,您已经完成以下工作:

服务注册与发现

介绍如何使用 Pandora Boot 开发应用(包括服务提供者和服务消费者)并实现服务注册与发现。

注意:严禁在应用启动时调用HSF远程服务,否则会导致启动失败。

Demo 源码下载:https://github.com/aliyun/alibabacloud-microservice-demo/tree/master/microservice-doc-demo/hsf-pandora-boot

使用 git 克隆整个项目,并在 microservice-doc-demo/hsf-pandora-boot 文件夹内可以找到本文使用的示例工程。

创建服务提供者

  1. 创建一个 Maven 工程,命名为hsf-pandora-boot-provider

  2. pom.xml 中引入需要的依赖。

    1. <properties>
    2. <java.version>1.8</java.version>
    3. <spring-boot.version>2.1.6.RELEASE</spring-boot.version>
    4. <pandora-boot.version>2019-06-stable</pandora-boot.version>
    5. </properties>
    6. <dependencies>
    7. <dependency>
    8. <groupId>com.alibaba.boot</groupId>
    9. <artifactId>pandora-hsf-spring-boot-starter</artifactId>
    10. </dependency>
    11. <dependency>
    12. <groupId>org.springframework.boot</groupId>
    13. <artifactId>spring-boot-starter-web</artifactId>
    14. </dependency>
    15. </dependencies>
    16. <dependencyManagement>
    17. <dependencies>
    18. <dependency>
    19. <groupId>org.springframework.boot</groupId>
    20. <artifactId>spring-boot-dependencies</artifactId>
    21. <version>${spring-boot.version}</version>
    22. <type>pom</type>
    23. <scope>import</scope>
    24. </dependency>
    25. <dependency>
    26. <groupId>com.taobao.pandora</groupId>
    27. <artifactId>pandora-boot-starter-bom</artifactId>
    28. <version>${pandora-boot.version}</version>
    29. <type>pom</type>
    30. <scope>import</scope>
    31. </dependency>
    32. </dependencies>
    33. </dependencyManagement>
    34. <build>
    35. <plugins>
    36. <plugin>
    37. <groupId>org.apache.maven.plugins</groupId>
    38. <artifactId>maven-compiler-plugin</artifactId>
    39. <version>3.7.0</version>
    40. <configuration>
    41. <source>1.8</source>
    42. <target>1.8</target>
    43. </configuration>
    44. </plugin>
    45. <plugin>
    46. <groupId>com.taobao.pandora</groupId>
    47. <artifactId>pandora-boot-maven-plugin</artifactId>
    48. <version>2.1.11.8</version>
    49. <executions>
    50. <execution>
    51. <phase>package</phase>
    52. <goals>
    53. <goal>repackage</goal>
    54. </goals>
    55. </execution>
    56. </executions>
    57. </plugin>
    58. </plugins>
    59. </build>

    虽然 HSF 服务框架并不依赖于 Web 环境,但是 EDAS 管理应用的生命周期过程中需要使用到 Web 相关的特性,所以需要添加 spring-boot-starter-web 的依赖。

    另外引入了 pandora-hsf-spring-boot-starter ,它会帮我们实现 HSF 配置的自动装配。

    pandora-boot-maven-plugin 是 Pandora Boot 提供的 maven 打包插件,它可以将 Pandora Boot HSF 工程打包成可执行的 FatJar,并在 EDAS Container 中部署运行。

    dependencyManagement 中包含了 spring-boot-dependenciespandora-boot-starter-bom 两个依赖,分别负责 Spring Boot 和 Pandora Boot 相关依赖的版本管理,设置之后,您的工程不再需要设置 parent 为 spring-boot-starter-parent

  3. 定义服务接口,创建一个接口类 com.alibaba.edas.HelloService

    HSF 服务框架基于接口进行服务通信,当接口定义好之后,生产者将通过该接口实现具体的服务并发布,消费者也是基于此接口去订阅和消费服务。

    1. public interface HelloService {
    2. String echo(String string);
    3. }

    接口com.alibaba.edas.HelloService提供了一个echo方法

  4. 添加服务提供者的具体实现类EchoServiceImpl,并通过注解方式发布服务。

    1. @HSFProvider(serviceInterface = HelloService.class, serviceVersion = "1.0.0")
    2. public class HelloServiceImpl implements HelloService {
    3. @Override
    4. public String echo(String string) {
    5. return string;
    6. }
    7. }

    在 HSF 应用中,接口名和服务版本才能唯一确定一个服务,所以在注解HSFProvider中的需要添加接口名com.alibaba.edas.HelloService和服务版本1.0.0

    说明

    • 注解中的配置拥有最高优先级。
    • 如果在注解中没有配置,服务发布时会优先在resources/application.properties文件中查找这些属性的全局配置。
    • 如果注解和resources/application.properties文件中都没有配置,则会使用注解中的默认值。
  5. resources目录下的application.properties文件中配置应用名和监听端口号。

    1. spring.application.name=hsf-pandora-boot-provider
    2. server.port=8081
    3. spring.hsf.version=1.0.0
    4. spring.hsf.timeout=3000

    最佳实践: 建议将服务版本服务超时都统一配置在application.properties中。

  6. 添加服务启动的 main 函数入口。

    1. @SpringBootApplication
    2. public class HSFProviderApplication {
    3. public static void main(String[] args) {
    4. // 启动 Pandora Boot 用于加载 Pandora 容器
    5. PandoraBootstrap.run(args);
    6. SpringApplication.run(HSFProviderApplication.class, args);
    7. // 标记服务启动完成,并设置线程 wait。防止业务代码运行完毕退出后,导致容器退出。
    8. PandoraBootstrap.markStartupAndWait();
    9. }
    10. }

创建服务消费者

本示例中,将创建一个服务消费者,通过HSFConsumer所提供的 API 接口去调用服务提供者。

  1. 创建一个 Maven 工程,命名为hsf-pandora-boot-consumer

  2. pom.xml中引入需要的依赖内容:

    说明:消费者和提供者的 Maven 依赖是完全一样的。

    1. <properties>
    2. <java.version>1.8</java.version>
    3. <spring-boot.version>2.1.6.RELEASE</spring-boot.version>
    4. <pandora-boot.version>2019-06-stable</pandora-boot.version>
    5. </properties>
    6. <dependencies>
    7. <dependency>
    8. <groupId>com.alibaba.boot</groupId>
    9. <artifactId>pandora-hsf-spring-boot-starter</artifactId>
    10. </dependency>
    11. <dependency>
    12. <groupId>org.springframework.boot</groupId>
    13. <artifactId>spring-boot-starter-web</artifactId>
    14. </dependency>
    15. </dependencies>
    16. <dependencyManagement>
    17. <dependencies>
    18. <dependency>
    19. <groupId>org.springframework.boot</groupId>
    20. <artifactId>spring-boot-dependencies</artifactId>
    21. <version>${spring-boot.version}</version>
    22. <type>pom</type>
    23. <scope>import</scope>
    24. </dependency>
    25. <dependency>
    26. <groupId>com.taobao.pandora</groupId>
    27. <artifactId>pandora-boot-starter-bom</artifactId>
    28. <version>${pandora-boot.version}</version>
    29. <type>pom</type>
    30. <scope>import</scope>
    31. </dependency>
    32. </dependencies>
    33. </dependencyManagement>
    34. <build>
    35. <plugins>
    36. <plugin>
    37. <groupId>org.apache.maven.plugins</groupId>
    38. <artifactId>maven-compiler-plugin</artifactId>
    39. <version>3.7.0</version>
    40. <configuration>
    41. <source>1.8</source>
    42. <target>1.8</target>
    43. </configuration>
    44. </plugin>
    45. <plugin>
    46. <groupId>com.taobao.pandora</groupId>
    47. <artifactId>pandora-boot-maven-plugin</artifactId>
    48. <version>2.1.11.8</version>
    49. <executions>
    50. <execution>
    51. <phase>package</phase>
    52. <goals>
    53. <goal>repackage</goal>
    54. </goals>
    55. </execution>
    56. </executions>
    57. </plugin>
    58. </plugins>
    59. </build>
  3. 将服务提供者所发布的 API 服务接口(包括包名)拷贝到本地,如com.alibaba.edas.HelloService

    1. public interface HelloService {
    2. String echo(String string);
    3. }
  4. 通过注解的方式将服务消费者的实例注入到 Spring 的 Context 中。

    1. @Configuration
    2. public class HsfConfig {
    3. @HSFConsumer(clientTimeout = 3000, serviceVersion = "1.0.0")
    4. private EchoService echoService;
    5. }

    最佳实践:在HsfConfig类里配置一次@HSFConsumer,然后在多处通过@Autowired注入使用。通常一个 HSF Consumer 需要在多个地方使用,但并不需要在每次使用的地方都用@HSFConsumer来标记。只需要写一个统一的HsfConfig类,然后在其它需要使用的地方,直接通过@Autowired注入即可。

  5. 为了便于测试,使用SimpleController来暴露一个/hsf-echo/*的 HTTP 接口,/hsf-echo/*接口内部实现调用了 HSF 服务提供者。

    1. @RestController
    2. public class SimpleController {
    3. @Autowired
    4. private HelloService helloService;
    5. @RequestMapping(value = "/hsf-echo/{str}", method = RequestMethod.GET)
    6. public String echo(@PathVariable String str) {
    7. return helloService.echo(str);
    8. }
    9. }
  6. resources目录下的application.properties文件中配置应用名与监听端口号。

    1. spring.application.name=hsf-pandora-boot-consumer
    2. server.port=8080
    3. spring.hsf.version=1.0.0
    4. spring.hsf.timeout=1000

    最佳实践: 建议将服务版本服务超时都统一配置在application.properties中。

  7. 添加服务启动的 main 函数入口。

    1. @SpringBootApplication
    2. public class HSFConsumerApplication {
    3. public static void main(String[] args) {
    4. PandoraBootstrap.run(args);
    5. SpringApplication.run(HSFConsumerApplication.class, args);
    6. PandoraBootstrap.markStartupAndWait();
    7. }
    8. }

本地开发调试

配置轻量配置中心

本地开发调试时,需要使用轻量级配置中心,轻量级配置中心包含了 EDAS 服务注册发现服务端的轻量版,详情请参见配置轻量配置中心

启动应用

应用可以通过以下两种方式启动。

  • 在 IDE 中启动

    通过 VM options 配置启动参数 -Djmenv.tbsite.net={$IP},通过 main 方法直接启动。其中 {$IP} 为轻量配置中心的 IP 地址。比如本机启动轻量配置中心,则{$IP}127.0.0.1

    您也可以不配置 JVM 的参数,而是直接通过修改 hosts 文件将 jmenv.tbsite.net 绑定为轻量配置中心的 IP。详情请参见配置轻量级配置中心

  • 通过 FatJar 启动

    1. 增加 taobao-hsf.sar 依赖,这样会下载到我们需要的依赖:/.m2/com/taobao/pandora/taobao-hsf.sar/2019-06-stable/taobao-hsf.sar-2019-06-stable.jar,在后面的启动参数中依赖它。

      1. <dependency>
      2. <groupId>com.taobao.pandora</groupId>
      3. <artifactId>taobao-hsf.sar</artifactId>
      4. <version>2019-06-stable</version>
      5. </dependency>
    2. 使用 Maven 将 Pandora Boot 工程打包成 FatJar, 需要在pom.xml 中添加如下插件。为避免与其他打包插件发生冲突,请勿在 build 的 plugin 中添加其他 FatJar 插件。

      1. <plugin>
      2. <groupId>com.taobao.pandora</groupId>
      3. <artifactId>pandora-boot-maven-plugin</artifactId>
      4. <version>2.1.11.8</version>
      5. <executions>
      6. <execution>
      7. <phase>package</phase>
      8. <goals>
      9. <goal>repackage</goal>
      10. </goals>
      11. </execution>
      12. </executions>
      13. </plugin>
    3. 添加完插件后,在工程的主目录下,执行 maven 命令 mvn clean package 进行打包,即可在Target目录下找到打包好的 FatJar 文件。

    4. 通过 Java 命令启动应用。

      1. java -Djmenv.tbsite.net=127.0.0.1 -Dpandora.location=${M2_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

    说明-Dpandora.location 指定的路径必须是全路径,使用命令行启动时,必须显示指定 taobao-hsf.sar 的位置。

结果验证

访问 consumer 所在机器的地址,可以触发 consumer 远程调用 provider

  1. curl localhost:8080/hsf-echo/helloworld
  2. helloworld

单元测试

Pandora Boot 的单元测试可以通过 PandoraBootRunner 启动,并与 SpringJUnit4ClassRunner 无缝集成。

我们将演示一下如何在服务提供者中进行单元测试,供大家参考。

  1. 在 Maven 中添加 Pandora Boot 和 Spring Boot 测试必要的依赖。

    1. <dependency>
    2. <groupId>com.taobao.pandora</groupId>
    3. <artifactId>pandora-boot-test</artifactId>
    4. <scope>test</scope>
    5. </dependency>
    6. <dependency>
    7. <groupId>org.springframework.boot</groupId>
    8. <artifactId>spring-boot-starter-test</artifactId>
    9. <scope>test</scope>
    10. </dependency>
  2. 编写测试类的代码。

    1. @RunWith(PandoraBootRunner.class)
    2. @DelegateTo(SpringJUnit4ClassRunner.class)
    3. // 加载测试需要的类,一定要加入 Spring Boot 的启动类,其次需要加入本类。
    4. @SpringBootTest(classes = {HSFProviderApplication.class, HelloServiceTest.class })
    5. @Component
    6. public class HelloServiceTest {
    7. /**
    8. * 当使用 @HSFConsumer 时,一定要在 @SpringBootTest 类加载中,加载本类,通过本类来注入对象,否则当做泛化时,会出现类转换异常。
    9. */
    10. @HSFConsumer(generic = true)
    11. HelloService helloService;
    12. //普通的调用
    13. @Test
    14. public void testInvoke() {
    15. TestCase.assertEquals("hello world", helloService.echo("hello world"));
    16. }
    17. //泛化调用
    18. @Test
    19. public void testGenericInvoke() {
    20. GenericService service = (GenericService) helloService;
    21. Object result = service.$invoke("echo", new String[] {"java.lang.String"}, new Object[] {"hello world"});
    22. TestCase.assertEquals("hello world", result);
    23. }
    24. //返回值 Mock
    25. @Test
    26. public void testMock() {
    27. HelloService mock = Mockito.mock(HelloService.class, AdditionalAnswers.delegatesTo(helloService));
    28. Mockito.when(mock.echo("")).thenReturn("beta");
    29. TestCase.assertEquals("beta", mock.echo(""));
    30. }
    31. }