簡介:專有云傳統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技術學院釘釘圈子,和更多雲上人交流關於雲平臺的那些事。
本文內容由阿里雲實名註冊用戶自發貢獻,版權歸原做者全部,阿里雲開發者社區不擁有其著做權,亦不承擔相應法律責任。具體規則請查看《阿里雲開發者社區用戶服務協議》和《阿里雲開發者社區知識產權保護指引》。若是您發現本社區中有涉嫌抄襲的內容,填寫侵權投訴表單進行舉報,一經查實,本社區將馬上刪除涉嫌侵權內容。