对于那些实时性要求不高,但却计算密集或者需要处理大数据量的耗时较长的任务,或是有较慢 I/O 的任务,选择异步化是一个不错的选择。在系统层面,像引入消息中间件来解耦系统,将耗时长的任务放在中间件后异步执行。在方法层面,像把耗时较长的任务放到其他线程中去异步执行。
异步任务的两种类型:
(1)列表异步任务执行后对任务发起方或调用方有感知,比如发出一个事件或通知
(2)列表异步任务执行后对任务发起方或调用方没有感知,只是改变了系统中的某些状态
招商店铺中目前存在的都是第2种情况,在业务上的异步主要分以下两类:
1.订单导出类的功能:导出的订单数据较多,使用异步进行交互
2.提交到batch批处理进行处理
像这样异步场景怎么进行自动化集成呢?
之前也有做法就是通过Thread.sleep(经验值)来进行等待异步任务处理,但中间等待的时间是不确定的。
现介绍一款开源工具awaitility:https://github.com/awaitility/awaitility,
该工具提供轮询的方式,判断操作是否完成,以最短的时间获取异步任务结果。
以下用订单批量受理场景进行举例:
点击【批量受理】后,提交任务到batch落地任务流水。
具体的受理动作由batch批处理中心进行受理。
awaitility 使用步骤:
(1)maven工程在pom.xml添加awaitility依赖:
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>2.0.0</version>
</dependency>
(2)测试类import相关Class:
import java.util.concurrent.Callable;
import static java.util.concurrent.TimeUnit.*;
import static org.awaitility.Awaitility.*;
import static org.awaitility.Duration.*;
import static org.awaitility.pollinterval.FibonacciPollInterval.*;
(3)订单受理的测试脚本,如下:
@Test(dataProvider = "DefaultDataProvider", dataProviderClass = DataProviderDriver.class)
public void TestAcceptByIdList(String testcase[]) {
dal.setTitle("订单受理-批量受理_" + testcase[0])
.setPriority("P0")
.setTest_object("com.hipac.seller.hop.order.api.HopTradeAcceptApi")
.setIs_exception("false")
.setCase_name(Thread.currentThread().getStackTrace()[1].getMethodName());
String data = testcase[1];
String user = testcase[2];
String password = testcase[3];
String exceptCode = testcase[4];
String exceptMsg = testcase[5];
String orderAcceptFlag = testcase[6];
supplyId = testcase[7];
String queryOrderData = testcase[8];
//1.设置供应商isv配置订单推送开关 ->关闭
if(!isvManagerUtil.isOrderAccecptOpen(supplyId)) {
//设置供应商推单开关为 - 》 关
isvManagerUtil.setOrderAccecpt(supplyId,"orderPush","0");
}
//2.创建订单
orderNo = OrderUtil.createOrder(user,15461,"已支付订单");
queryOrderData = queryOrderData.replace("\n","").replace("${orderNo}",orderNo);
//3.调用订单查询接口 获取订单交易id
String orderId = getOrderIdByNo(user,password,queryOrderData);
//4.check供应商isv配置是否与场景预期的前置一致
if(orderAcceptFlag.equals("1")) { //推单
if(!isvManagerUtil.isOrderAccecptOpen(supplyId)) {
//设置供应商推单开关为 - 》 开
isvManagerUtil.setOrderAccecpt(supplyId,"orderPush","1");
}
} else if(orderAcceptFlag.equals("0")) {
if(isvManagerUtil.isOrderAccecptOpen(supplyId)) {
//设置供应商推单开关为 - 》 关
isvManagerUtil.setOrderAccecpt(supplyId,"orderPush","0");
}
}
//5.进行批量订单受理
data = data.replace("${orderId}",orderId);
String result = PostRequestAPI("hipac.seller.order.hpc.batch.accept",user,password,data);
String actCode = HttpUtil.checkHttpResCode(result);
String actMsg = JsonUtil.parseJson2Map(result).get("message");
//6.轮询进行订单状态检测:是否已到达已受理状态
// 轮询5s 每隔500毫秒进行轮询,延迟100毫秒后进行校验
await().atMost(5, TimeUnit.SECONDS).pollInterval(FIVE_HUNDRED_MILLISECONDS).and().with().pollDelay(100, TimeUnit.MILLISECONDS)
.await().until(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
int orderStatus = getOrderStatus(supplyId, orderNo);
return orderStatus == OrderStatus.ACCEPT.getCode();
}
});
}
这里使用轮询的方式检查订单是否到达已受理状态:
// 轮询5s 每隔500毫秒进行轮询,延迟100毫秒后进行校验
await().atMost(5, TimeUnit.SECONDS).pollInterval(FIVE_HUNDRED_MILLISECONDS).and().with().pollDelay(100, TimeUnit.MILLISECONDS)
.await().until(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
int orderStatus = getOrderStatus(supplyId, orderNo);
return orderStatus == OrderStatus.ACCEPT.getCode();
}
});