简介: 专有云传统 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 技术学院钉钉圈子,和更多云上人交换对于云平台的那些事。
版权申明: 本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。