平台技术-API批量调用简介
1、为什么要批量调用
可以提高应用性能,更快的响应
比如做一个页面需要调用7个不同的HSF服务拉取数据,然后渲染页面。这种情况下, 如想加快页面响应,可能会考虑并发发起7次HSF调用等到数据都返回来再进行页面渲染。但是这样的编程模型对于调用者来说响应时间会比较长且调用繁琐,如果TOP把7次的HSF调用通过内部串行方式由TOP直接来完成,1次调用返回多个数据结果,那则可以大大提高每次请求响应时间。那对于某些复杂的API调用(单次调用RT可能会达到100MS的业务),那么就有很好的优化效果
使用更少的流量
单次API调用会传重复的系统或者业务入参,比如:sign、method、时间戳、fileds等参数,在很多情况下这些重复参数占用了请求体里面的大部分空间。API批量调用可以将这些参数在协议层面上进行合并,实现参数的复用。对于移动端调用、服务端高并发调用中优化网络使用是很有帮助的。
2、批量调用API特性
- 支持目前所有安全和业务特性
- 支持除文件上传外的所有API自由组合调用
- 支持多session混合调用
- 调用结果互不干扰
- API响应顺序和请求顺序完全一致,无需排序或按编号查询结果
- 极速体验,M次交易API+N次商品API调用,RT约为1次交易API调用(假设交易API RT> 商品API)
- Servlet、HSF、HTTP混合全异步化调用模式,平稳支撑低RT + 高RT混合场景,提高服务端吞吐能力
- 公共参数和方法名称可进行合并,精简请求报文
- 简单的调用协议,不用SDK也能快速实现批量API调用
3、批量调用技术简介
3.1 协议内容
请求URL:
http://gw.api.taobao.com/router/batchPOST:
PAYLOAD:
- Payload以from的形式去承载每个API,默认以\r\n-S-\r\n进行分割;参数值需要进行URL Encode
- 自定义分隔符方式:httpHeader.put(“top-api-separator”,”????”)
- 第一行#PUBLIC#开始,可提取公共参数和API名称,为可选。如不需要提取公共参数,同时去掉#PUBLIC#行和第一个分隔符
- 参数优先级:API行参数 ===覆盖===> #PUBLIC#参数 ===覆盖===> URL参数
- 签名方式,类似于rest签名:hmac(其他类似) byte2hex (hmac(key1value1key2value2...payloadsecret))
- 占位符:假设你把一个API的所有参数都抽象到了#PUBLIC#区域,请放入一个占位符N,标示我其实是一个API;如上所示
3.2 协议内容-响应
Response:情况1
Response:情况2
-S-
{"time_get_response":{"time":"2016-01-05 10:53:02","request_id":"16t6sm2gxmm5q"}}
-S-
{"trade_fullinfo_get_response":{"trade":{"orders":{"order":[{"adjust_fee":"0.00","buyer_rate":false,"cid":50069506,"consign_time":"2015-12-03 14:01:07","discount_fee":"0.00","end_time":"2015-12-03 16:18:19","invoice_no":"0000","is_oversold":false,"logistics_company":"电 子凭 证","num":1,"num_iid":2100727710059,"oid":193923500416510,"order_from":"TAOBAO","payment":"11.00","pic_path":"http:\/ \/img04.daily.taobao.net\/bao\/uploaded\/i4 \/TB1EG6SXXXXXXaBXXXXXXXXXXXX_!!0- item_pic.jpg","price":"11.00","refund_status":"NO_REFUND","seller_rate":false,"seller_type":"C","shipping_type":"virtual","snapshot_url":"d:193923500416510_1","status":"TRADE_FINISHED","title":" 测试发布收费课 2015123","total_fee":"11.00"}]},"payment":"11.00","receiver_address":"15988161275","receiver_mobile":"","receiver_name":" 不****","status":"TRADE_FINISHED","tid":193923500416510,"type":"eticket"},"request_id":"16t6sm2gxmm5q"}}
-S-
{"error_response":{"code":27,"msg":"Invalid session","sub_code":"invalid-sessionkey","request_id":"16t6sm2gxmm5q"}}
- Response,情况1:响应报文只有一条结果;比如签名,appkey不存在;这些都是共性,比如我们只进行一次签名,那么一条API签名错误,意味着所以api都会签名错误。
- Response,情况2:响应报文和请求报文里面的API个数一致,响应顺序也会和请求顺序保持一致。比如你提交15条请求,可能会出现10条成功,3条流控,2条HSF服务提供端异常;但是我们的响应体依然会有15条请求响应。
- 自定义分隔符方式:默认分隔符为\r\n-S-\r\n ;自定义方式在提交请求是,使用httpHeader.put(“top-api-separator”,”????”);请求和响应体分隔符保持一致
4 、SDK使用方式
4.1 创建Client
”, “appkey”,“secret");} //注:使用该方式,需要下载最新的sdk,老的sdk暂未支持批量调用功能
4.2 创建BatchRequest
4.3 添加请求API
.addRequest(timeGetRequest2)
.addRequest(timeGetRequest3)
.addRequest(timeGetRequest4)
.addRequest(fullinfosRequest1)
.addRequest(fullinfosRequest2)
.addRequest(fullinfosRequest3);
4.4 提交请求
4.5 遍历结果
for (int i = 0; i < response.getResponseList().size(); i++)
println("body:" + response.getResponseList().get(i).getBody());
}
4.6 随机查询结果
TimeGetResponse resp1 = response.getResponse(timeGetRequest1);
if(timeGetResponse1.isSuccess())
println(“服务器时间:" + resp1.getTime());
TradeFullinfoGetResponse rep2 = response.getResponse(fullinfosRequest3);
}
注:使用sdk实现批量api调用功能 ,需要下载最新的sdk,sdk下载及使用点 这里 。
5、典型使用场景举例
以调用接口获取订单详情为例,原来要查询某个商家多个订单详情,需要重复发起多次请求;现如果使用批量方式调用,1次请求就可以返回多个结果,可以大大提高API调用效率。以下是常用使用场景sdk调用示例(java):
5.1、查询单个商家多个订单详情
TradeFullinfoGetRequest req1 = new TradeFullinfoGetRequest();
req1.setFields( "tid");
req1.setTid(6666666666661L); //订单1
TradeFullinfoGetRequest req2 = new TradeFullinfoGetRequest();
req2.setFields( "tid");
req2.setTid(6666666666662L); //订单2
TaobaoBatchRequest req = new TaobaoBatchRequest();
req.addRequest(req1);
req.addRequest(req2);
TaobaoBatchResponse rsp = client.execute(req, "test"); //test表示商家的sessionkey
5.2、查询多个商家多个订单详情
TradeFullinfoGetRequest req1 = new TradeFullinfoGetRequest();
req1.setFields( "tid");
req1.setTid(6666666666661L); //商家a的订单1
TradeFullinfoGetRequest req2 = new TradeFullinfoGetRequest();
req2.setFields( "tid");
req2.setTid(6666666666662L); //商家a的订单2
TradeFullinfoGetRequest req3 = new TradeFullinfoGetRequest();
req3.setFields( "tid");
req3.setTid(8888888888881L); //商家b的订单1
req3.setBatchApiSession( "testtest"); //商家b的sessionkey
TaobaoBatchRequest req = new TaobaoBatchRequest();
req.addRequest(req1);
req.addRequest(req2);
req.addRequest(req3);
TaobaoBatchResponse rsp = client.execute(req, "test"); //商家a的sessionkey
5.3、查询多个商家订单和商品详情
TradeFullinfoGetRequest req1 = new TradeFullinfoGetRequest();
req1.setFields( "tid");
req1.setTid(6666666666661L); //商家a的订单1
TradeFullinfoGetRequest req2 = new TradeFullinfoGetRequest();
req2.setFields( "tid");
req2.setTid(6666666666662L); //商家a的订单2
ItemSellerGetRequest req3 = new ItemSellerGetRequest();
req3.setFields( "num_iid");
req3.setNumIid(8888888881L); //商家b的商品1
req3.setBatchApiSession( "testtest"); //商家b的sessionkey
TaobaoBatchRequest req = new TaobaoBatchRequest();
req.addRequest(req1);
req.addRequest(req2);
req.addRequest(req3);
TaobaoBatchResponse rsp = client.execute(req, "test"); //商家a的sessionkey
FAQ
测试环境下与正式环境下的API调用量有限制吗?