简介:专有云传统HSF升级Pandora Boot开发

本次最佳实践,分析传统HSF应用的劣势及升级至Pandora Boot开发的优势。将结合HSF代码和Pandora Boot代码进行详解传统HSF应用如何升级至Pandora Boot开发。

背景信息

HSF开发应用的劣势在于HSF要使用指定的Ali-Tomcat容器,还需要在Ali-Tomcat等容器中加入sar包扩展,对用户运行环境的侵入性大。而HSF开发的应用程序最终以WAR包的形式运行,不符合微服务设计的轻量应用理念。并且开发过程注入Bean需要编写较多的xml文件配置。

而Pandora Boot开发应用的优势就在于依赖容器Pandora,不需要Ali-Tomcat。而且Pandora Boot开发也兼容了完整的HSF功能,同时与Spring Boot无缝集成。所以使用Pandora Boot的同时也可以引入Spring Boot提供开箱即用的依赖模板。快速、敏捷的开发Spring框架的应用程序,享受开发的便利。

Pandora Boot开发的应用最终以FatJar包的形式运行,并且Pandora环境也可以直接在IDE中启动,开发调试等效率将得到极大的提高。而Pandora Boot注入Bean通过注解的方式,也减少了繁杂的xml配置文件编写,提高开发效率。

因为在传统客户中有HSF应用升级至Pandora Boot开发的需求,所以针对客户的需要,本次最佳实践将详细描述传统HSF应用和PandoraBoot应用的开发,使单体微服务应用的敏捷开发及拓展性有所提高。

HSF环境介绍及准备

产品组件

  • Ali-Tomcat是EDAS中的服务运行依赖的一个容器,支持Servlet 3.0规范,支持WebSocket。包含服务的发布、订阅、调用链追踪等一系列的核心功能。
  • Pandora是一个轻量级的隔离容器-taobao-hsf.sar,它用来隔离Webapp和中间件的依赖,也用来隔离中间件之间的依赖,并实现部署与应用分离。
  • 轻量级配置中心(Diamond)是淘宝内部广泛使用的配置中心,提供持久化管理和动态配置推送服务。应用方发布的配置会通过持久化存储保存,与发布者的生命周期无关。
  • 动态配置推送是Diamond的核心功能,在淘宝内部有很多应用场景,如数据库动态切换和扩容,业务系统开关配置运行时变更等。
  • 轻量级注册中心(ConfigServer):主要用于非持久数据的发布和订阅、数据的生命周期和TCP连接生命周期绑定、产品架构基于发布订阅模型和去中心无master设计,保证了系统的可扩展性、高可用。在集团内部主要场景为分布式消息系统Notify、分布式RPC框架HSF提供地址发现服务。

基本结构

HSF结构分为6个部分,共同组合在一起可以提供全功能的分布式服务,分别是:

  • 服务消费方:消费服务提供方提供的服务,服务消费者通过地址注册中心订阅服务,根据订阅到的地址信息发起调用,地址注册中心作为旁路不参与调用。
  • 服务提供方: 在服务框架中真正提供服务功能实现的应用实例,为了保障服务提供的高可用性,一般均是集群部署,同时将地址信息发布到地址注册中心。
  • 地址注册中心:接受服务提供方发布的地址,当服务消费方根据服务进行订阅时,会将地址信息推送给服务消费方,注册中心就是服务信息的中介,提供服务发现的能力
  • 持久化配置中心:持久化的配置中心用于存储 HSF 服务的各种治理规则,HSF 客户端在启动的过程中会向持久化配置中心订阅各种服务治理规则,如路由规则、归组规则、权重规则等,从而根据规则对调用过程的选址逻辑进行干预。
  • 元数据存储中心:元数据是指 HSF 服务对应的方法列表以及参数结构等信息,元数据不会对 HSF 的调用过程产生影响,因此元数据存储中心也并不是必须的。但考虑到服务运维的便捷性,HSF客户端在启动时会将元数据上报到元数据存储中心,以便提供给服务运维使用
  • HSF运维平台(HSF控制台):HSF 控制台通过打通地址注册中心 ConfigServer、持久化配置中心 Diamond、元数据存储中心Redis,为用户提供了一些列服务运维功能,包括服务查询、服务治理规则管理、服务测试、服务 Mock、单机运维等,旨在提高 HSF 服务研发的效率、运维的便捷性。

环境准备流程步骤

在进行开发前,需要准备以下基本内容:

  1. JDK基础运行环境:正确安装JDK 7+,正确配置JAVA_HOME环境变量。
  2. MAVEN环境及构建HSF MAVEN工程:添加打war包与HSF开发编译依赖。
  3. 开发IDE:推荐Eclipse或IDEA。
  4. Eclipse配置:Tomcat4e插件+Pandora配置。
  5. IDEA:配置AliTomcat+Pandora。
  6. 轻量级配置中心:HSF服务的发布与订阅。

Pandora Boot环境介绍及准备

产品组件

  • Pandora:一个轻量级的隔离容器-taobao-hsf.sar,它用来隔离Webapp和中间件的依赖,也用来隔离中间件之间的依赖,也实现部署与应用分离。
  • 轻量级配置及注册中心:对于开发者可以在本地使用轻量级配置及注册中心实现应用的注册、发现与配置管理,完成应用的开发和测试。本地开发完应用托管到EDAS服务上,EDAS内置注册及配置中心,因此注册及配置功能仍然可以正常使用。

基本结构

HSF结构分为6个部分,共同组合在一起可以提供全功能的分布式服务,分别是:

  • 服务消费方:消费服务提供方提供的服务,服务消费者通过地址注册中心订阅服务,根据订阅到的地址信息发起调用,地址注册中心作为旁路不参与调用。
  • 服务提供方: 在服务框架中真正提供服务功能实现的应用实例,为了保障服务提供的高可用性,一般均是集群部署,同时将地址信息发布到地址注册中心。
  • 地址注册中心:接受服务提供方发布的地址,当服务消费方根据服务进行订阅时,会将地址信息推送给服务消费方,注册中心就是服务信息的中介,提供服务发现的能力
  • 持久化配置中心:持久化的配置中心用于存储 HSF 服务的各种治理规则,HSF 客户端在启动的过程中会向持久化配置中心订阅各种服务治理规则,如路由规则、归组规则、权重规则等,从而根据规则对调用过程的选址逻辑进行干预。
  • 元数据存储中心:元数据是指 HSF 服务对应的方法列表以及参数结构等信息,元数据不会对 HSF 的调用过程产生影响,因此元数据存储中心也并不是必须的。但考虑到服务运维的便捷性,HSF客户端在启动时会将元数据上报到元数据存储中心,以便提供给服务运维使用
  • HSF运维平台(HSF控制台):HSF 控制台通过打通地址注册中心 ConfigServer、持久化配置中心 Diamond、元数据存储中心Redis,为用户提供了一些列服务运维功能,包括服务查询、服务治理规则管理、服务测试、服务 Mock、单机运维等,旨在提高 HSF 服务研发的效率、运维的便捷性。

环境准备流程步骤

在进行开发前,需要准备一下基本内容:

  1. JDK基础运行环境:正确安装JDK 7+,正确配置JAVA_HOME环境变量。
  2. MAVEN环境及构建Pandora Boot MAVEN工程:添加打FatJar包与Pandora Boot开发编译依赖。
  3. 开发IDE:推荐Eclipse或IDEA。
  4. Eclipse配置:启动Pandora Boot应用主函数自动加载Pandora容器。
  5. IDEA配置:启动Pandora Boot应用主函数自动加载Pandora容器。
  6. 轻量级注册及配置中心:Pandora Boot应用的注册、发现及配置管理。

HSF开发流程及流程图

开发流程节点:

  1. 服务接口:HSF的服务基于接口实现,接口需在服务设计时预先定义设计好,生产者将实现该接口以提供具体的实现来提供服务,消费者也是基于此接口作为服务去订阅。
  2. 服务生产者:生产者将实现之前定义的服务接口以提供具体实现,除了代码实现的工作之外,由于HSF是基于Spring框架来实现的,所以还需要再定义服务发布的XML文件。
  3. 服务消费者:消费者基于接口使用服务,具体调用时需要做两个步骤
    1. Pandora Boot 的配置文件使用注解@HSFConsumer定义好一个 Bean。
    2. 在使用的时候从 Spring 的 context 中将 Bean 取出。

图 1. 流程图

开发HSF应用

背景信息

  1. 无缝兼容:HSF与Spring无缝兼容,标准用法使用Spring的xml配置。
  2. 标准schema:提供hsf:provider,hsf:consumer两个标准的xml格式。
  3. 代码无侵入:使用xml方式开发时,代码不需要感知HSF框架,而且POM中只需要引入edas-sdk。
  4. 框架与WAR包分离:最终输入的war,不需要包含HSF框架,HSF框架依赖AliTomcat+Pandora方式提供。

您需要按以下步骤构建HSF maven工程:

  1. 构建maven工程,创建完maven工程后,在pom.xml文件中定义添加edas-sdk和spring的依赖。
<dependencies><!-- 添加 servlet 的依赖 --><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring</artifactId><version>2.5.6</version><type>jar</type><scope>compile</scope></dependency><!-- 添加 edas-sdk 的依赖 --><dependency><groupId>com.alibaba.edas</groupId><artifactId>edas-sdk</artifactId><version>1.5.4</version></dependency></dependencies>

  1. 在pom.xml文件中添加HSF应用的maven打包插件。
<build><finalName>itemcenter</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><source>1.6</source><target>1.6</target></configuration></plugin></plugins></build>

定义服务接口

HSF服务基于接口实现调用,定义好接口Sayhello后,生产者将使用该接口实现具体的服务,消费者也基于此接口订阅服务,所以一般会将接口定义在一个工程中,它会打成一个jar包,发布到maven仓库中。下面是公共模块edasdemo-api接口定义代码:

package com.edas.demo;public interface Sayhello {public String sayHello();public String sayHello(String name);}

编写HSF服务提供者

  1. 编写HSF提供者服务除构建HSF maven工程外,服务提供者需要在pom.xml文件中引入公共模块工程的依赖。
<dependency><groupId>com.edas.demo</groupId><artifactId>edasdemo-api</artifactId><version>0.0.1-SNAPSHOT</version></dependency>

  1. 服务提供者实现接口提供具体的服务,然后发布对应的服务。
package com.edas.demo;public class SayhelloImpl implements Sayhello {public String sayHello() {System.out.println("INFO:执行一次Hello");return "Hello!";}public String sayHello(String name) {return "你好"+name;}}

  1. 在hsf-provider-beans.xml中Spring配置HSF服务。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:hsf="http://www.taobao.com/hsf"xmlns="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://www.taobao.com/hsfhttp://www.taobao.com/hsf/hsf.xsd" default-autowire="byName"><bean id="sayHello" class="com.edas.demo.SayhelloImpl" /><!-- 提供一个服务示例 --><hsf:provider id="sayHelloProvider" interface="com.edas.demo.Sayhello"ref="sayHello" version="1.0.0"></hsf:provider></beans>

编写HSF服务消费者

  1. 编写消费者服务除构建HSF maven工程外,服务消费者需要在pom.xml文件中引入公共模块工程的依赖。
<dependency><groupId>com.edas.demo</groupId><artifactId>edasdemo-api</artifactId><version>0.0.1-SNAPSHOT</version></dependency>

  1. 在hsf-consumer-beans.xml中Spring配置HSF服务。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:hsf="http://www.taobao.com/hsf"xmlns="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://www.taobao.com/hsfhttp://www.taobao.com/hsf/hsf.xsd" default-autowire="byName"><!-- 消费一个服务示例 --><hsf:consumer id="sayHello" interface="com.edas.demo.Sayhello"version="1.0.0"></hsf:consumer></beans>

  1. 编写服务消费者基于接口调用服务提供者的代码SayhelloServlet。
public class SayhelloServlet extends HttpServlet {private static final long serialVersionUID = 1L;public SayhelloServlet() {super();}/*** @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)*/protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());// 根据 Spring 配置中的 Bean ID "item" 获取订阅到的服务final Sayhello sayHello = (Sayhello) ctx.getBean("sayHello");Thread thread = new Thread( new Runnable() {@Overridepublic void run() {while ( true ) {try {Thread.sleep(500l);System.out.println(sayHello.sayHello());System.out.println(sayHello.sayHello("tom"));} catch ( Throwable e ) {e.printStackTrace();}}}});thread.start();}protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}

开发HSF异步调用

异步调用

对于客户端来说,并不是所有的HSF服务都需要同步等待服务端返回结果,对于这些场景,HSF提供异步调用的方式,让客户端不必同步阻塞在HSF操作上。在HSF服务发起异步调用,调用结果都是返回的默认值。而真正的结果要在HSFResponseFuture或者回调函数callback中获取。

Futrue异步调用

HSF与Spring框架无缝集成,可以使用Spring XML的方式进行Future异步调用配置。

<bean id="orderService"class="com.taobao.hsf.app.spring.util.HSFSpringConsumerBean"><property name="interfaceName"value="com.alibaba.middleware.hsf.guide.api.service.OrderService"/><property name="version"value="1.0.0"/><property name="group"value="HSF"/><!--[设置] 订阅服务的接口--><property name="asyncallMethods"><list><value>name:queryOrder;type:future</value></list></property></bean>

Callback异步调用

使用Spring XML进行Callback异步调用配置。

<bean id="CallHelloWorld"class="com.taobao.hsf.app.spring.util.HSFSpringConsumerBean"><property name="interfaceName"value="com.alibaba.middleware.hsf.guide.api.service.OrderService"/><property name="version" value="1.0.0"/><property name="group" value="HSF"/><property name="asyncallMethods"><list><!--name:methodName;type:future|callback--><value>name:queryOrder;type:callback;listener:com.alibaba.middleware.hsf.CallbackHandler</value></list></property></bean>

开发HSF泛化调用

背景信息

相对于依赖业务客户端Jar包的正常调用,需要依赖二方包,使用特定的GenericService接口,而传入需要调用的方法名,方法签名和参数值进行调用服务。泛化调用更适用于一些网关应用,其中hsfops服务测试也是依赖泛化调用功能。

API形式配置HSF服务

将HSFConsumerBean,配置generic为true,标识客户端忽略加载不到接口的异常。

HSFApiConsumerBean hsfApiConsumerBean = newHSFApiConsumerBean();hsfApiConsumerBean.setInterfaceName("com.alibaba.middleware.hsf.guide.api.service.OrderService");hsfApiConsumerBean.setVersion("1.0.0");hsfApiConsumerBean.setGroup("HSF");// [设置] 泛化配置hsfApiConsumerBean.setGeneric("true");hsfApiConsumerBean.init(true);//使用泛化接口获取代理GenericService genericOrderService = (GenericService)hsfApiConsumerBean.getObject();// ---------------------- 调用 -----------------------//// [调用] 发起HSF泛化调用, 返回map类型的result。Map orderModelMap = (Map) genericOrderService.$invoke("queryOrder",new String[] { Long.class.getName() },new Object[] { 1L });

GenericService提供的$invoke方法包含了真实调用的方法名、入参类型和参数,以便服务端找到改方法。由于没有依赖服务端的API jar包,传入的参数如果是自定义的DTO,需要转成客户端可以序列化的Map类型。

Spring配置HSF服务

上面描述了通过API配置HSF服务,也可以通过Spring XML配置HSF服务。

<bean id="CallHelloWorld"class="com.taobao.hsf.app.spring.util.HSFSpringConsumerBean"><!--[设置] 订阅服务的接口--><property name="interfaceName"value="com.alibaba.middleware.hsf.guide.api.service.OrderService"/><!--[设置] 服务的版本--><property name="version" value="1.0.0"/><!--[设置] 服务的归组--><property name="group" value="HSF"/><property name="generic" value="true"/></bean>

调用上下文

背景信息

请求上下文包括一次性调用相关的属性,比如调用的地址,调用方的应用名,超时时间等属性和用户在接口定义的参数之外传递自定义的数据。

设置和获取本次调用上下文

com.taobao.hsf.util.RequestCtxUtil提供设置和获取调用上下文的静态方法,基于ThreadLocal工作,getXXX操作会将XXX属性从当前ThreadLocal变量中remove掉,仅作用于当前线程的单次调用。

表1. 客户端

名称 描述
setRequestTimeout() 设置单次调用的超时时间
setUserId() 设置本次调用的单元化服务的userId(泛化调用中需要通过此方法配置)
getProviderIp() 获取【最近一次】调用的服务端的IP
setTargetServerIp(String ip) 设置当前线程下一次调用的目标服务器IP(此IP必须包含在内存已提供服务的地址列表里)
setDirectTargetServerIp(String targetIp) 设置当前线程下一次调用的目标服务器IP(绕过注册中心,忽略内存里的地址列表)

表 2. 服务端

名称 描述
getClientIp() 服务端获取调用方IP
getAppNameOfClient() 服务端获取调用方的应用名
isHttpRequest() 是否是http调用
getHttpHeader(String key) 获取http请求的header属性

传递自定义请求上下文

RpcContext提供一种不修改接口,向服务端额外传递数据的方式。参数可以是自定义的DO或者基本类型。要保证对端也有该对应的类型,并且可以能够被序列化。

  1. 传递自定义上下文开发示例 ,在构建的Maven项目中导入下面依赖。
<dependency><groupId>com.taobao.hsf</groupId><artifactId>hsf-feature-context</artifactId></dependency>

  1. 客户端发起调用前,设置上下文。
RPCContext rpcContext = RPCContext.getClientContext();rpcContext.putAttachment("tetantId", "123");orderService.queryOrder(1L);

  1. 服务端业务方法内,获取上下文。
RPCContext rpcContext = RPCContext.getServerContext();String myContext = (String)rpcContext.getAttachment("tetantId");

配置序列化

序列化的过程是将JAVA对象转成byte数组在网络中传输,反序列化会将byte数组转成JAVA对象。

序列化方式配置

序列化的选择需要考虑兼容性,性能等因素,HSF的序列化方式支持JAVA、hessian、hessian2、JSON、kyro,默认是hessian2。这些序列化方式的对比和配置(只在服务端配置HSFApiProviderBean)如下表所示:

序列化方式 maven依赖 配置 兼容性 性能
hessian2 <artifactId>hsf-io-serialize-hessian2</artifactId> setPreferSerializeType("hessian2")
java <artifactId>hsf-io-serialize-java</artifactId> setPreferSerializeType("java") 最好 一般
fastjson <artifactId>hsf-io-serialize-json</artifactId> setPreferSerializeType("json")
kryo <artifactId>hsf-io-serialize-kryo</artifactId> setPreferSerializeType("kryo") 一般 最好

API形式配置HSF服务

HSFApiProviderBean hsfApiProviderBean = new HSFApiProviderBean();hsfApiProviderBean.setPreferSerializeType("hessian2");

Spring配置HSF服务

Spring框架是在应用中广泛使用的组件,如果不想通过API的形式配置HSF服务,可以使用Spring XML的形式进行配置,上述例子中的API配置等同于如下XML配置:

<bean class="com.taobao.hsf.app.spring.util.HSFSpringProviderBean" init-method="init"><!--[设置] 发布服务的接口--><property name="serviceInterface" value="com.alibaba.middleware.hsf.guide.api.service.OrderService"/><!--[设置] 服务的实现对象 target必须配置[ref],为需要发布为HSF服务的spring bean id--><property name="target" ref="引用的BeanId"/><!--[设置] 服务的版本--><property name="serviceVersion" value="1.0.0"/><!--[设置] 服务的归组--><property name="serviceGroup" value="HSF"/><!--[设置] 服务的响应时间--><property name="clientTimeout" value="3000"/><!--[设置]  服务传输业务对象时的序列化类型--><property name="preferSerializeType" value="hessian2"/></bean>

超时设置

背景信息

有关网络调用的请求,都需要配置超时,HSF的默认超时时间是3000ms。客户端和服务端都可以设置超时,默认优先采用客户端的配置,如果客户端没有配置,使用服务端的超时配置。在服务端设置超时时,需要考虑到业务本身的执行耗时,加上序列化和网络通讯的时间。所以推荐服务端给每个服务都配置个默认的时间。当然客户端也可以根据自己的业务场景配置超时时间,比如一些前端应用,需要用户快速看到结果,可以把超时时间设置小一些。

客户端超时配置

客户端超时配置有以下两种方式:

  • API形式配置HSF服务,配置HSFApiConsumerBean的clientTimeout属性,单位是ms,我们把接口的超时配置为1000ms,方法queryOrder配置为100ms,代码如下:
HSFApiConsumerBean consumerBean = new HSFApiConsumerBean();//接口级别超时配置consumerBean.setClientTimeout(1000);//xxxMethodSpecial methodSpecial = new MethodSpecial();methodSpecial.setMethodName("queryOrder");//方法级别超时配置,优先于接口超时配置methodSpecial.setClientTimeout(100);consumerBean.setMethodSpecials(new MethodSpecial[]{methodSpecial});

  • Spring配置HSF服务,上述例子中的API配置等同于如下XML配置:
<bean id="CallHelloWorld" class="com.taobao.hsf.app.spring.util.HSFSpringConsumerBean">...<property name="clientTimeout" value="1000" /><property name="methodSpecials"><list><bean class="com.taobao.hsf.model.metadata.MethodSpecial"><property name="methodName" value="queryOrder" /><property name="clientTimeout" value="100" /></bean></list></property>...</bean>

服务端超时配置

服务端超时配置也有两种不同的方式:

  • API形式配置HSF服务,配置HSFApiProviderBean的clientTimeout属性,单位是ms,代码如下:
HSFApiProviderBean providerBean = new HSFApiProviderBean();//接口级别超时配置providerBean.setClientTimeout(1000);//xxxMethodSpecial methodSpecial = new MethodSpecial();methodSpecial.setMethodName("queryOrder");//方法级别超时配置,优先于接口超时配置methodSpecial.setClientTimeout(100);providerBean.setMethodSpecials(new MethodSpecial[]{methodSpecial});

  • Spring配置HSF服务,上述例子中的API配置等同于如下XML配置:
<bean class="com.taobao.hsf.app.spring.util.HSFSpringProviderBean" init-method="init">...<property name="clientTimeout" value="1000" /><property name="methodSpecials"><list><bean class="com.taobao.hsf.model.metadata.MethodSpecial"><property name="methodName" value="queryOrder" /><property name="clientTimeout" value="2000" /></bean></list></property>...</bean>

服务端线程池配置

HSF服务端线程池主要分为IO线程和业务线程,其中IO线程模型就是netty reactor网络模型中使用的。

默认线程池配置

服务端线程池是用来执行业务逻辑的线程池,线程池默认的core size是50,max size是720,keepAliveTime 500s。队列使用的是SynchronousQueue,没有缓存队列,不会堆积用户请求。 当服务端线程池所有线程(720)都在处理请求时,对于新的请求,会立即拒绝,返回Thread pool is full异常。可以使用下面VM参数(-D参数)进行配置。

  • 线程池最小配置:-Dhsf.server.min.poolsize
  • 线程池最大的配置:-Dhsf.server.max.poolsize
  • 线程收敛的存活时间:-Dhsf.server.thread.keepalive

服务线程池配置

对于一些慢服务、并发高,可以为其单独配置线程池,以免占用过多的业务线程,影响应用的其他服务的调用,你可以通过以下两种方式配置HSF应用:

  • API形式配置HSF应用:
HSFApiProviderBean hsfApiProviderBean = new HSFApiProviderBean();//...hsfApiProviderBean.setCorePoolSize("50");hsfApiProviderBean.setMaxPoolSize("200");

  • Spring配置HSF应用:
<bean class="com.taobao.hsf.app.spring.util.HSFSpringProviderBean" init-method="init"><!--[设置] 发布服务的接口--><property name="serviceInterface" value="com.alibaba.middleware.hsf.guide.api.service.OrderService"/><property name="corePoolSize" value="50" /><property name="maxPoolSize" value="200" /></bean>

Pandora Boot开发流程

开发流程节点:

  1. 服务接口:Pandora Boot 的服务基于接口实现,接口需在服务设计时预先定义设计好,生产者将实现该接口以提供具体的实现来提供服务,消费者也是基于此接口作为服务去订阅。
  2. 服务生产者:生产者将实现之前定义的服务接口以提供具体实现,除了代码实现的工作之外,所以还需要再定义服务发布的注解@HSFProvider配置标识为服务提供者。
  3. 服务消费者:消费者基于接口使用服务,具体调用时需要做两个步骤:
    1. Spring 的配置文件使用标签定义好一个Bean。
    2. 在使用的时候从Spring的context中将Bean取出。

开发Pandora Boot应用

构建Pandora Boot maven工程

  1. 构建maven工程,创建完maven工程后,在pom.xml文件中配置EDAS的私服库地址和插件私服库地址。
<repositories><repository><id>central</id><url>http://repo1.maven.org/maven2</url><releases><enabled>true</enabled></releases><snapshots><enabled>true</enabled></snapshots></repository><repository><id>edas-oss-central</id><name>taobao mirror central</name><url>http://edas-public.oss-example.aliyuncs.com/repository</url><snapshots><enabled>true</enabled></snapshots><releases><enabled>true</enabled></releases></repository></repositories><pluginRepositories><pluginRepository><id>central</id><url>http://repo1.maven.org/maven2</url><releases><enabled>true</enabled></releases><snapshots><enabled>true</enabled></snapshots></pluginRepository><pluginRepository><id>edas-oss-plugin-central</id><url>http://edas-public.oss-example.aliyuncs.com/repository</url><snapshots><enabled>true</enabled></snapshots><releases><enabled>true</enabled></releases></pluginRepository></pluginRepositories>

  1. 构建maven工程,创建完maven工程后,在pom.xml文件中定义添加pandora boot和spring boot依赖的版本。
<properties><spring-boot.version>2.1.6.RELEASE</spring-boot.version><pandora-boot.version>2019-06-stable</pandora-boot.version></properties><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></dependencyManagement>

  1. 在pom.xml添加pandora boot 和spring boot开发的依赖。
<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><dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId></dependency><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></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!-- Use Swagger UI for REST API test --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.6.1</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.6.1</version></dependency></dependencies>

  1. 在pom.xml文件中添加pandora boot应用的maven打包插件。
<build><plugins><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>

  1. 在工程目录resources下的application.properties文件中配置应用名和监听端口号。
spring.application.name=hsf-providerserver.port=8082spring.hsf.version=1.0.0spring.hsf.timeout=1000

  1. 添加服务启动的main函数入口。
@SpringBootApplicationpublic class HSFProviderApplication {public static void main(String[] args) {// 启动 Pandora Boot 用于加载 Pandora 容器PandoraBootstrap.run(args);SpringApplication.run(HSFProviderApplication.class, args);// 标记服务启动完成,并设置线程 wait。防止用户业务代码运行完毕退出后,导致容器退出。PandoraBootstrap.markStartupAndWait();}}

编写Pandora Boot服务提供者

  1. 对于服务提供者,其创建过程与以上构建Pandora Boot maven工程步骤一致外,需要定义服务接口EchoService提供给消费者订阅。
public interface EchoService {String echo(String string);String echoFuture(String str);String echoCallback(String str);String echoHSFMix(int id);String echoMQConsumer(String str);}

  1. 创建服务提供者的具体实现类EchoServiceImpl,并通过注解方式发布服务。
@HSFProvider(serviceInterface = EchoService.class, serviceGroup = "HSF", serviceVersion = "1.0.0")public class EchoServiceImpl implements EchoService {@Autowiredprivate EchoDao echoDao;@Autowiredprivate SimpleMQConsumer simpleMQConsumer;@Autowiredprivate SimpleMQProduce simpleMQProduce;public String echo(String str) {return "hello --" + str;}public String echoFuture(String str) {return "welcome --" + str;}public String echoCallback(String str) {return "welcome --" + str;}public String echoHSFMix(int id) {//写消息simpleMQProduce.sendMsg(id+"");return echoDao.findById(id).getUserName();}public String echoMQConsumer(String str) {//订阅消息simpleMQConsumer.receive();return str;}}

编写Pandora Boot消费者服务

  1. 对于服务消费者,其创建过程与以上构建Pandora Boot maven工程步骤一致,添加服务提供者定义的接口复制到消费者服务工程。
public interface EchoService {String echo(String string);String echoFuture(String str);String echoCallback(String str);String echoHSFMix(int id);String echoMQConsumer(String str);}

  1. 添加消费者服务配置类及业务逻辑代码。
消费者服务配置类:@Configurationpublic class HsfConfig {//通过注解的方式将服务消费者的实例注入到Spring的Context中,同步调用@HSFConsumer(clientTimeout = 3000, serviceVersion = "1.0.0")private EchoService echoService;}消费者服务实现调用HSF服务提供者:@RestController@RequestMapping(value = "/poc")@Api(description = "HSF-POC功能测试接口")public class ConsumerController {@Autowiredprivate EchoService echoService;@NacosValue(value = "${useLocalCache:false}", autoRefreshed = true)private String useLocalCache;@ApiOperation(value = "获取服务者返回信息 A->C")@RequestMapping(value = "/hsf-echo", method = RequestMethod.GET)public String echo(@RequestParam("str") String str) {return echoService.echo(str) + "\r\n";}@ApiOperation(value = "通过ID查询数据库获取返回信息、RocketMQ写信息 A->C")@RequestMapping(value = "/hsf-echo-mix", method = RequestMethod.GET)public String echoHSFMix(@RequestParam("id") int id) {return echoService.echoHSFMix(id) + "\r\n";}@ApiOperation(value = "RocketMQ订阅消息 A->C")@RequestMapping(value = "/hsf-echo-mq", method = RequestMethod.GET)public String echoMQConsumer(@RequestParam("str") String str) {return echoService.echoMQConsumer(str) + "\r\n";}@ApiOperation(value = "获取版本信息")@RequestMapping(value = "/echo-version", method = RequestMethod.GET)public String echoVersion() {return "This is pandora boot version 2" + "\r\n";}}

开发Pandora Boot异步调用

对于客户端来说,并不是所有的HSF服务都是需要同步等待服务端返回结果的,对于这些场景,HSF提供异步调用的方式,让客户端不必同步阻塞在HSF操作上。在HSF服务发起异步调用,调用结果都是返回的默认值。而真正的结果要在HSFResponseFuture或者回调函数callback中获取。

Futrue异步调用

  1. 对于服务提供者,其创建过程与以上构建Pandora Boot maven工程步骤一致外,需要定义服务接口EchoService提供给消费者订阅,在EchoService添加Future异步调用的接口及实现类。
public interface EchoService {String echoFuture(String str);}接口实现类:@HSFProvider(serviceInterface = EchoService.class, serviceGroup = "HSF", serviceVersion ="1.0.0")public class EchoServiceImpl implements EchoService {public String echoFuture(String str) {return "welcome --" + str;}}

  1. 对于服务消费者,其创建过程与以上构建Pandora Boot maven工程步骤一致外,编写Future异步调用代码。
在配置类通过注解配置HSF接口方法为异步调用://Future异步调用@HSFConsumer(serviceGroup = "HSF", serviceVersion = "1.0.0", futureMethods = "echoFuture")private EchoService echoService;编写对外暴露请求的Future异步调用代码:@RequestMapping(value = "/hsf-echo-future", method = RequestMethod.GET)public String echoFuture(@RequestParam("str") String str) {String resp = echoService.echoFuture(str) + "\r\n";System.out.println(resp);//及时在当前调用上下文中,获取 future 对象;因为该对象是放在ThreadLocal中,同一线程中后续调用会覆盖future对象,所以要及时取出。HSFFuture hsfFuture = HSFResponseFuture.getFuture();//这里才真正地获取结果,如果调用还未完成,将阻塞等待结果,5000ms是等待结果的最大时间try {System.out.println(hsfFuture.getResponse(5000));} catch (Throwable throwable) {throwable.printStackTrace();}return resp;}

Callback异步调用

  1. 对于服务提供者,其创建过程与以上构建Pandora Boot maven一致外,需要定义服务接口EchoService提供给消费者订阅,在EchoService添加Callback异步调用的接口及实现类。
public interface EchoService {String echoFuture(String str);}接口实现类:@HSFProvider(serviceInterface = EchoService.class, serviceGroup = "HSF", serviceVersion = "1.0.0")public class EchoServiceImpl implements EchoService {public String echoFuture(String str) {return "welcome --" + str;}}

  1. 对于服务消费者,其创建过程与以上构建Pandora Boot maven步骤一致外,编写Future异步调用代码。
注解配置HSF接口方法为callback调用:@AsyncOn(interfaceName = EchoService.class, methodName = "echoCallback")public class CallbackHandler implements HSFResponseCallback {public void onAppException(Throwable t) {t.printStackTrace();}public void onAppResponse(Object result) {//取 callback 调用时设置的上下文Object context = CallbackInvocationContext.getContext();System.out.println(result.toString());System.out.println(context);}public void onHSFException(HSFException e) {e.printStackTrace();}}编写对外暴露请求的Callback异步调用代码:@RequestMapping(value = "/hsf-echo-callback", method = RequestMethod.GET)public String echoCallback(@RequestParam("str") String str) {String resp = echoService.echoCallback(str) + "\r\n";System.out.println(resp);return resp;}

开发Pandora Boot超时设置

背景信息

注解配置HSF服务,SpringBoot广泛使用的今天,使用注解装配SpringBean也成为一种选择,HSF也支持使用注解进行配置,用来订阅服务。

客户端注解超时配置

  1. 首先在Maven项目pom.xml文件中添加依赖Starter:
<dependency><groupId>com.alibaba.boot</groupId><artifactId>pandora-hsf-spring-boot-starter</artifactId></dependency>

  1. 通常一个HSF Consumer需要在多个地方使用,但并不需要在每次使用的地方都用@HSFConsumer来标记。只需要写一个统一个Config类,然后在其它需要使用的地方,直接@Autowired注入即可上述例子中的API配置等同于如下注解配置:
@HSFConsumer(clientTimeout = 1000, methodSpecials =@HSFConsumer.ConsumerMethodSpecial(methodName = "queryOrder", clientTimeout = "100"))private OderService orderService;

服务端注解超时配置

  1. 首先在Maven项目pom.xml文件中添加依赖Starter:
<dependency><groupId>com.alibaba.boot</groupId><artifactId>pandora-hsf-spring-boot-starter</artifactId></dependency>

  1. 服务端注解配置HSF服务超时设置:
@HSFProvider(serviceInterface = OrderService.class, clientTimeout = 3000)public class OrderServiceImpl implements OrderService {@Autowiredprivate OrderDAO orderDAO;@Overridepublic OrderModel queryOrder(Long id) {return orderDAO.queryOrder(id);}}

开发Pandora Boot服务线程池配置

背景信息

注解配置HSF服务,SpringBoot被广泛使用的今天,使用注解装配SpringBean也成为一种选择,HSF也支持使用注解进行配置,用来订阅服务。

  1. 首先在Maven项目pom.xml文件中添加依赖Starter。
<dependency><groupId>com.alibaba.boot</groupId><artifactId>pandora-hsf-spring-boot-starter</artifactId></dependency>

  1. 将@HSFProvider配置到实现的类型上,上述例子中的API配置等同于如下注解配置。
@HSFProvider(serviceInterface = OrderService.class, corePoolSize = 50, maxPoolSize = 200)public class OrderServiceImpl implements OrderService {@Autowiredprivate OrderDAO orderDAO;@Overridepublic OrderModel queryOrder(Long id) {return orderDAO.queryOrder(id);}}

我们是阿里云智能全球技术服务-SRE团队,我们致力成为一个以技术为基础、面向服务、保障业务系统高可用的工程师团队;提供专业、体系化的SRE服务,帮助广大客户更好地使用云、基于云构建更加稳定可靠的业务系统,提升业务稳定性。我们期望能够分享更多帮助企业客户上云、用好云,让客户云上业务运行更加稳定可靠的技术,您可用钉钉扫描下方二维码,加入阿里云SRE技术学院钉钉圈子,和更多云上人交流关于云平台的那些事。

原文链接:https://developer.aliyun.com/article/784841?

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

专有云传统HSF升级Pandora Boot开发相关推荐

  1. “云时代”大势当前,专有云成企业上云首选

    云已经成为企业越来越依赖的技术,企业CIO们纷纷在云上部署应用并将数据迁移到云端,且能够预见:今后几年,云战略的构建.实施都将成为企业的头等大事. 在部署模式上,目前主要分为公有云.私有云和混合云三种 ...

  2. 搭载敏捷飞天底座,阿里云专有云敏捷版全面升级

    6月9日, 在2020阿里云线上峰会上阿里云混合云重磅发布三款新品:专有云敏捷版(Apsara Stack Agility). 混合云管理平台(Apsara Uni-manager)以及下一代企业级一 ...

  3. 搭载敏捷飞天底座 阿里云专有云敏捷版全面升级

    6月9日, 在2020阿里云线上峰会上阿里云混合云重磅发布三款新品:专有云敏捷版(Apsara Stack Agility). 混合云管理平台(Apsara Uni-manager)以及下一代企业级一 ...

  4. 阿里专有云OpenAPI开发实践之消息队列

    目录 阿里专有云OpenAPI开发实践之消息队列 环境介绍 文档资料 消息队列MQ产品的Endpoint 消息队列产品没有相应的SDK 简单调用示例 RAM授权 <开发指南>之外的Open ...

  5. 高效上云?智能升级?就靠百度智能云专有云ABC Stack!

    上云热潮下 既想保持公有云一样的 稳定性.易用性.拓展性 又希望兼顾私有云的安全可控 别急,这些需求专有云通通满足你 拥有了专有云 轻松实现弹性扩展.随付随用.云运维 全方位满足特定性能.应用及安全合 ...

  6. 云计算正在告别DIY时代 阿里云专有云挑起企业级市场大梁

    "云计算的DIY时代已经过去",5月23日在2018云栖大会·武汉峰会上,阿里云专有云事业部总经理马劲表示,DIY式私有云正被时代抛弃,不仅部署费时费力,且难以解决企业云的顽疾.取 ...

  7. 腾讯专有云研发过程首次披露

    2018年11月3日,DevOps国际峰会于深圳圣淘沙酒店举行,上午的腾讯研发效能专场,开场前已座无虚席.由腾讯工蜂Git.腾讯TAPD.腾讯专有云三位产品/技术负责人带来各自产品在DevOps实践上 ...

  8. 阿里宜搭重磅发布专有云版本、精品应用市场,助力政企数字化转型

    6月9日,在2020阿里云线上峰会上,"宜搭"重磅发布专有云版本和精品应用市场,为政企数字化转型提供高效.安全.可靠的服务.宜搭是阿里巴巴集团企业智能事业部自研的低代码应用开发Pa ...

  9. CIPU落地专有云:是“小众需求”还是“机会之门”?

    引言:2022年11月,云栖大会主论坛,阿里巴巴集团副总裁.阿里云智能基础产品事业部负责人蒋江伟分享了阿里云专有云的一项新进展 -- CIPU落地飞天企业版.在分析师峰会上,阿里巴巴集团研究员.阿里云 ...

最新文章

  1. 2021年春季学期-信号与系统-第十四次作业参考答案-第八小题参考答案
  2. 什么是堆,栈,内存泄漏和内存溢出?
  3. python中的np where_python – np.where在我的熊猫中不起作用
  4. leetcode 1293. Shortest Path in a Grid with Obstacles Elimination | 1293. 网格中的最短路径(BFS)
  5. python中的try......except......
  6. echarts 选中bush中lineX
  7. 利用PCF8591进行AD转换
  8. 根据百度的语音识别例子,展示C如何调用C++库
  9. 实验7(2019.6.18)
  10. LoggerFactory.getLogger
  11. Matlab遗传算法工具箱(gaot)下载及安装
  12. (一)使用RED5搭建流媒体服务器
  13. 计算机的发展共经历了哪几个阶段,1. 计算机的发展经历了哪几个阶段?各阶段的主要特征是什么,计算机的发展经历了哪些阶段?...
  14. linux只能单向ping通,两机只能单向Ping通的原因、ping的原理
  15. shell教程(4)变量(二):字符串变量截取、替换和删除
  16. 架构师手册——图形化表达
  17. Java并发编程:Lock
  18. rust闪退修复工具_Rust的错误处理
  19. 华为云云享专家申请流程
  20. 没有钱该如何做好新产品的网络营销推广

热门文章

  1. 从零开始学习docker(七)docker配置环境变量
  2. 使用pg_resetwal时空穿梭找回“幽灵”元组
  3. 一文秒懂!Python字符串格式化之format方法详解
  4. 十一在家都逛哪些技术网站?(程序员必备58个网站汇总)
  5. 骚操作!昨晚停网,我写了一段Python代码破解了隔壁小姐姐的wifi密码...
  6. 一机一码加密软件_加密软件还有哪些功能?
  7. js json制表符报错_JS自学_常见错误复盘
  8. 二、linux命令(ubuntu)
  9. 语音特征提取: MFCC的理解
  10. 回溯法:批量作业调度