简介:专有云传统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 服务研发的效率、运维的便捷性。
环境筹备流程步骤
在进行开发前,须要筹备以下根本内容:
- JDK根底运行环境:正确装置JDK 7+,正确配置JAVA\_HOME环境变量。
- MAVEN环境及构建HSF MAVEN工程:增加打war包与HSF开发编译依赖。
- 开发IDE:举荐Eclipse或IDEA。
- Eclipse配置:Tomcat4e插件+Pandora配置。
- IDEA:配置AliTomcat+Pandora。
- 轻量级配置核心: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 服务研发的效率、运维的便捷性。
环境筹备流程步骤
在进行开发前,须要筹备一下根本内容:
- JDK根底运行环境:正确装置JDK 7+,正确配置JAVA\_HOME环境变量。
- MAVEN环境及构建Pandora Boot MAVEN工程:增加打FatJar包与Pandora Boot开发编译依赖。
- 开发IDE:举荐Eclipse或IDEA。
- Eclipse配置:启动Pandora Boot利用主函数主动加载Pandora容器。
- IDEA配置:启动Pandora Boot利用主函数主动加载Pandora容器。
- 轻量级注册及配置核心:Pandora Boot利用的注册、发现及配置管理。
HSF开发流程及流程图
开发流程节点:
- 服务接口:HSF的服务基于接口实现,接口需在服务设计时事后定义设计好,生产者将实现该接口以提供具体的实现来提供服务,消费者也是基于此接口作为服务去订阅。
- 服务生产者:生产者将实现之前定义的服务接口以提供具体实现,除了代码实现的工作之外,因为HSF是基于Spring框架来实现的,所以还须要再定义服务公布的XML文件。
- 服务消费者:消费者基于接口应用服务,具体调用时须要做两个步骤
-
- Pandora Boot 的配置文件应用注解@HSFConsumer定义好一个 Bean。
- 在应用的时候从 Spring 的 context 中将 Bean 取出。
图 1. 流程图
开发HSF利用
背景信息
- 无缝兼容:HSF与Spring无缝兼容,规范用法应用Spring的xml配置。
- 规范schema:提供hsf:provider,hsf:consumer两个规范的xml格局。
- 代码无侵入:应用xml形式开发时,代码不须要感知HSF框架,而且POM中只须要引入edas-sdk。
- 框架与WAR包拆散:最终输出的war,不须要蕴含HSF框架,HSF框架依赖AliTomcat+Pandora形式提供。
您须要按以下步骤构建HSF maven工程:
- 构建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>
- 在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服务提供者
- 编写HSF提供者服务除构建HSF maven工程外,服务提供者须要在pom.xml文件中引入公共模块工程的依赖。
<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;
}
}
- 在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/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>
编写HSF服务消费者
- 编写消费者服务除构建HSF maven工程外,服务消费者须要在pom.xml文件中引入公共模块工程的依赖。
<dependency>
<groupId>com.edas.demo</groupId>
<artifactId>edasdemo-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
- 在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/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>
- 编写服务消费者基于接口调用服务提供者的代码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() {
@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操作上。在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 = 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类型。
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或者根本类型。要保障对端也有该对应的类型,并且能够可能被序列化。
- 传递自定义上下文开发示例 ,在构建的Maven我的项目中导入上面依赖。
<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、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);
//xxx
MethodSpecial 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);
//xxx
MethodSpecial 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开发流程
开发流程节点:
- 服务接口:Pandora Boot 的服务基于接口实现,接口需在服务设计时事后定义设计好,生产者将实现该接口以提供具体的实现来提供服务,消费者也是基于此接口作为服务去订阅。
- 服务生产者:生产者将实现之前定义的服务接口以提供具体实现,除了代码实现的工作之外,所以还须要再定义服务公布的注解@HSFProvider配置标识为服务提供者。
- 服务消费者:消费者基于接口应用服务,具体调用时须要做两个步骤:
-
- Spring 的配置文件应用标签定义好一个Bean。
- 在应用的时候从Spring的context中将Bean取出。
开发Pandora Boot利用
构建Pandora Boot maven工程
- 构建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>
- 构建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>
- 在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>
- 在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>
- 在工程目录resources下的application.properties文件中配置利用名和监听端口号。
spring.application.name=hsf-provider
server.port=8082
spring.hsf.version=1.0.0
spring.hsf.timeout=1000
- 增加服务启动的main函数入口。
@SpringBootApplication
public class HSFProviderApplication {
public static void main(String[] args) {
// 启动 Pandora Boot 用于加载 Pandora 容器
PandoraBootstrap.run(args);
SpringApplication.run(HSFProviderApplication.class, args);
// 标记服务启动实现,并设置线程 wait。避免用户业务代码运行结束退出后,导致容器退出。
PandoraBootstrap.markStartupAndWait();
}
}
编写Pandora Boot服务提供者
- 对于服务提供者,其创立过程与以上构建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);
}
- 创立服务提供者的具体实现类EchoServiceImpl,并通过注解形式公布服务。
@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;
}
}
编写Pandora Boot消费者服务
- 对于服务消费者,其创立过程与以上构建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);
}
- 增加消费者服务配置类及业务逻辑代码。
消费者服务配置类:
@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";
}
}
开发Pandora Boot异步调用
对于客户端来说,并不是所有的HSF服务都是须要同步期待服务端返回后果的,对于这些场景,HSF提供异步调用的形式,让客户端不用同步阻塞在HSF操作上。在HSF服务发动异步调用,调用后果都是返回的默认值。而真正的后果要在HSFResponseFuture或者回调函数callback中获取。
Futrue异步调用
- 对于服务提供者,其创立过程与以上构建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;
}
}
- 对于服务消费者,其创立过程与以上构建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异步调用
- 对于服务提供者,其创立过程与以上构建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;
}
}
- 对于服务消费者,其创立过程与以上构建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也反对应用注解进行配置,用来订阅服务。
客户端注解超时配置
- 首先在Maven我的项目pom.xml文件中增加依赖Starter:
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>pandora-hsf-spring-boot-starter</artifactId>
</dependency>
- 通常一个HSF Consumer须要在多个中央应用,但并不需要在每次应用的中央都用@HSFConsumer来标记。只须要写一个对立个Config类,而后在其它须要应用的中央,间接@Autowired注入即可上述例子中的API配置等同于如下注解配置:
@HSFConsumer(clientTimeout = 1000, methodSpecials =
@HSFConsumer.ConsumerMethodSpecial(methodName = "queryOrder", clientTimeout = "100"))
private OderService orderService;
服务端注解超时配置
- 首先在Maven我的项目pom.xml文件中增加依赖Starter:
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>pandora-hsf-spring-boot-starter</artifactId>
</dependency>
- 服务端注解配置HSF服务超时设置:
@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);
}
}
开发Pandora Boot服务线程池配置
背景信息
注解配置HSF服务,SpringBoot被宽泛应用的明天,应用注解拆卸SpringBean也成为一种抉择,HSF也反对应用注解进行配置,用来订阅服务。
- 首先在Maven我的项目pom.xml文件中增加依赖Starter。
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>pandora-hsf-spring-boot-starter</artifactId>
</dependency>
- 将@HSFProvider配置到实现的类型上,上述例子中的API配置等同于如下注解配置。
@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技术学院钉钉圈子,和更多云上人交换对于云平台的那些事。
版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。
发表回复