简介:专有云传统HSF升级Pandora Boot开发
本次最佳实践,分析传统HSF应用的劣势及升级至Pandora Boot开发的优点。将结合HSF代码和Pandora Boot代码进行详解传统HSF应用如何升级至Pandora Boot开发。前端
HSF开发应用的劣势在于HSF要使用指定的Ali-Tomcat容器,还须要在Ali-Tomcat等容器中加入sar包扩展,对用户运行环境的侵入性大。而HSF开发的应用程序最终以WAR包的形式运行,不符合微服务设计的轻量应用理念。而且开发过程注入Bean须要编写较多的xml文件配置。java
而Pandora Boot开发应用的优点就在于依赖容器Pandora,不须要Ali-Tomcat。并且Pandora Boot开发也兼容了完整的HSF功能,同时与Spring Boot无缝集成。因此使用Pandora Boot的同时也能够引入Spring Boot提供开箱即用的依赖模板。快速、敏捷的开发Spring框架的应用程序,享受开发的便利。react
Pandora Boot开发的应用最终以FatJar包的形式运行,而且Pandora环境也能够直接在IDE中启动,开发调试等效率将获得极大的提升。而Pandora Boot注入Bean经过注解的方式,也减小了繁杂的xml配置文件编写,提升开发效率。web
由于在传统客户中有HSF应用升级至Pandora Boot开发的需求,因此针对客户的须要,本次最佳实践将详细描述传统HSF应用和PandoraBoot应用的开发,使单体微服务应用的敏捷开发及拓展性有所提升。spring
HSF结构分为6个部分,共同组合在一块儿能够提供全功能的分布式服务,分别是:数据库
在进行开发前,须要准备如下基本内容:apache
HSF结构分为6个部分,共同组合在一块儿能够提供全功能的分布式服务,分别是:json
在进行开发前,须要准备一下基本内容:api
图 1. 流程图数组
您须要按如下步骤构建HSF maven工程:
<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>
<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); }
<dependency> <groupId>com.edas.demo</groupId> <artifactId>edasdemo-api</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
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; } }
<?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/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.taobao.com/hsf http://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>
<dependency> <groupId>com.edas.demo</groupId> <artifactId>edasdemo-api</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
<?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/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.taobao.com/hsf http://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>
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() { @Override public 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服务发起异步调用,调用结果都是返回的默认值。而真正的结果要在HSFResponseFuture或者回调函数callback中获取。
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>
使用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>
相对于依赖业务客户端Jar包的正常调用,须要依赖二方包,使用特定的GenericService接口,而传入须要调用的方法名,方法签名和参数值进行调用服务。泛化调用更适用于一些网关应用,其中hsfops服务测试也是依赖泛化调用功能。
将HSFConsumerBean,配置generic为true,标识客户端忽略加载不到接口的异常。
HSFApiConsumerBean hsfApiConsumerBean = new HSFApiConsumerBean(); 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类型。
上面描述了经过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或者基本类型。要保证对端也有该对应的类型,而且能够可以被序列化。
<dependency> <groupId>com.taobao.hsf</groupId> <artifactId>hsf-feature-context</artifactId> </dependency>
RPCContext rpcContext = RPCContext.getClientContext(); rpcContext.putAttachment("tetantId", "123"); orderService.queryOrder(1L);
RPCContext rpcContext = RPCContext.getServerContext(); String myContext = (String)rpcContext.getAttachment("tetantId");
序列化的过程是将JAVA对象转成byte数组在网络中传输,反序列化会将byte数组转成JAVA对象。
序列化的选择须要考虑兼容性,性能等因素,HSF的序列化方式支持JAVA、hessian、hessian二、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") | 通常 | 最好 |
HSFApiProviderBean hsfApiProviderBean = new HSFApiProviderBean(); hsfApiProviderBean.setPreferSerializeType("hessian2");
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。客户端和服务端均可以设置超时,默认优先采用客户端的配置,若是客户端没有配置,使用服务端的超时配置。在服务端设置超时时,须要考虑到业务自己的执行耗时,加上序列化和网络通信的时间。因此推荐服务端给每一个服务都配置个默认的时间。固然客户端也能够根据本身的业务场景配置超时时间,好比一些前端应用,须要用户快速看到结果,能够把超时时间设置小一些。
客户端超时配置有如下两种方式:
HSFApiConsumerBean consumerBean = new HSFApiConsumerBean(); //接口级别超时配置 consumerBean.setClientTimeout(1000); //xxx MethodSpecial methodSpecial = new MethodSpecial(); methodSpecial.setMethodName("queryOrder"); //方法级别超时配置,优先于接口超时配置 methodSpecial.setClientTimeout(100); consumerBean.setMethodSpecials(new MethodSpecial[]{methodSpecial});
<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>
服务端超时配置也有两种不一样的方式:
HSFApiProviderBean providerBean = new HSFApiProviderBean(); //接口级别超时配置 providerBean.setClientTimeout(1000); //xxx MethodSpecial methodSpecial = new MethodSpecial(); methodSpecial.setMethodName("queryOrder"); //方法级别超时配置,优先于接口超时配置 methodSpecial.setClientTimeout(100); providerBean.setMethodSpecials(new MethodSpecial[]{methodSpecial});
<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参数)进行配置。
对于一些慢服务、并发高,能够为其单独配置线程池,以避免占用过多的业务线程,影响应用的其余服务的调用,你能够经过如下两种方式配置HSF应用:
HSFApiProviderBean hsfApiProviderBean = new HSFApiProviderBean(); //... hsfApiProviderBean.setCorePoolSize("50"); hsfApiProviderBean.setMaxPoolSize("200");
<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>
<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>
<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>
<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>
<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>
spring.application.name=hsf-provider server.port=8082 spring.hsf.version=1.0.0 spring.hsf.timeout=1000
@SpringBootApplication public class HSFProviderApplication { public static void main(String[] args) { // 启动 Pandora Boot 用于加载 Pandora 容器 PandoraBootstrap.run(args); SpringApplication.run(HSFProviderApplication.class, args); // 标记服务启动完成,并设置线程 wait。防止用户业务代码运行完毕退出后,致使容器退出。 PandoraBootstrap.markStartupAndWait(); } }
public interface EchoService { String echo(String string); String echoFuture(String str); String echoCallback(String str); String echoHSFMix(int id); String echoMQConsumer(String str); }
@HSFProvider(serviceInterface = EchoService.class, serviceGroup = "HSF", serviceVersion = "1.0.0") public class EchoServiceImpl implements EchoService { @Autowired private EchoDao echoDao; @Autowired private SimpleMQConsumer simpleMQConsumer; @Autowired private 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; } }
public interface EchoService { String echo(String string); String echoFuture(String str); String echoCallback(String str); String echoHSFMix(int id); String echoMQConsumer(String str); }
消费者服务配置类: @Configuration public 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 { @Autowired private 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"; } }
对于客户端来讲,并非全部的HSF服务都是须要同步等待服务端返回结果的,对于这些场景,HSF提供异步调用的方式,让客户端没必要同步阻塞在HSF操做上。在HSF服务发起异步调用,调用结果都是返回的默认值。而真正的结果要在HSFResponseFuture或者回调函数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; } }
在配置类经过注解配置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; }
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; } }
注解配置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; }
注解配置HSF服务,SpringBoot普遍使用的今天,使用注解装配SpringBean也成为一种选择,HSF也支持使用注解进行配置,用来订阅服务。
<dependency> <groupId>com.alibaba.boot</groupId> <artifactId>pandora-hsf-spring-boot-starter</artifactId> </dependency>
@HSFConsumer(clientTimeout = 1000, methodSpecials = @HSFConsumer.ConsumerMethodSpecial(methodName = "queryOrder", clientTimeout = "100")) private OderService orderService;
<dependency> <groupId>com.alibaba.boot</groupId> <artifactId>pandora-hsf-spring-boot-starter</artifactId> </dependency>
@HSFProvider(serviceInterface = OrderService.class, clientTimeout = 3000) public class OrderServiceImpl implements OrderService { @Autowired private OrderDAO orderDAO; @Override public OrderModel queryOrder(Long id) { return orderDAO.queryOrder(id); } }
注解配置HSF服务,SpringBoot被普遍使用的今天,使用注解装配SpringBean也成为一种选择,HSF也支持使用注解进行配置,用来订阅服务。
<dependency> <groupId>com.alibaba.boot</groupId> <artifactId>pandora-hsf-spring-boot-starter</artifactId> </dependency>
@HSFProvider(serviceInterface = OrderService.class, corePoolSize = 50, maxPoolSize = 200) public class OrderServiceImpl implements OrderService { @Autowired private OrderDAO orderDAO; @Override public OrderModel queryOrder(Long id) { return orderDAO.queryOrder(id); } }
咱们是阿里云智能全球技术服务-SRE团队,咱们致力成为一个以技术为基础、面向服务、保障业务系统高可用的工程师团队;提供专业、体系化的SRE服务,帮助广大客户更好地使用云、基于云构建更加稳定可靠的业务系统,提高业务稳定性。咱们指望可以分享更多帮助企业客户上云、用好云,让客户云上业务运行更加稳定可靠的技术,您可用钉钉扫描下方二维码,加入阿里云SRE技术学院钉钉圈子,和更多云上人交流关于云平台的那些事。
本文内容由阿里云实名注册用户自发贡献,版权归原做者全部,阿里云开发者社区不拥有其著做权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。若是您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将马上删除涉嫌侵权内容。