返回主页
猿天地
博客园 首页 新随笔 联系 管理 订阅订阅 随笔- 99 文章- 0 评论- 81
让API并行调用变得如丝般顺滑的绝招
当数据量较大的时候,都会通过分库分表来拆分,分担读写的压力。分库分表后比较麻烦的就是查询的问题,如果不是直接根据分片键去查询的话,需要对多个表进行查询。
在一些复杂的业务场景下,比如订单搜索,除了订单号,用户,商家 这些常用的搜索条件,可能还有时间,商品等等。
目前常见的做法将数据同步到ES这类搜索框架中进行查询,然后通过搜出来的结果,一般是主键ID, 再去具体的数据表中查询完整的数据,组装返回给调用方。
比如下面这段代码,首先查询出文章信息,然后根据文章中的用户ID去查询用户的昵称。
List articleBos = articleDoPage.getRecords().stream().map(r -> {
String nickname = userManager.getNickname(r.getUserId());
return articleBoConvert.convertPlus(r, nickname);
}).collect(Collectors.toList());
如果文章有10条数据,那么就需要调用10次用户服务提供的接口,而且是同步调用操作。
当然我们也可以用并行流来实现并发调用,代码如下:
List articleBos = articleDoPage.getRecords().parallelStream().map(r -> {
String nickname = userManager.getNickname(r.getUserId());
return articleBoConvert.convertPlus(r, nickname);
}).collect(Collectors.toList());
并行流的优点很明显,代码不用做特别大的改动。需要注意如果用并行流,最好单独定义一个ForkJoinPool。
除了用并行流,还可以使用批量查询的方式来提高性能,降低RPC的调用次数,代码如下:
List userIds = articleDoPage.getRecords().stream().map(article -> article.getUserId()).collect(Collectors.toList());
Map<Long, String> nickNameMap = userManager.queryByIds(userIds).stream().collect(Collectors.toMap(UserResponse::getId, UserResponse::getNickname));
List articleBos = articleDoPage.getRecords().stream().map(r -> {
String nickname = nickNameMap.containsKey(r.getUserId()) ? nickNameMap.get(r.getUserId()) : CommonConstant.DEFAULT_EMPTY_STR;
return articleBoConvert.convertPlus(r, nickname);
}).collect(Collectors.toList());
但批量查询还是同步模式,下面介绍如果使用CompletableFuture来实现异步并发调用,直接用原生的CompletableFuture也可以,但是编排能力没有那么强,这里我们选择一款基于CompletableFuture封装的并行编排框来实现,详细介绍查看我之前的这篇文章:https://mp.weixin.qq.com/s/3EE8ccydK16gC1oY4AWnoA
稍微做了下封装,提供了更方便使用的工具类来实现并发调用多个接口的逻辑。
第一种方式,适用于比如从ES查出了一批ID, 然后根据ID去数据库中或者调用RPC查询真实数据,最后得到一个Map,可以根据Key获取对应的数据。
内部是多线程并发调用,会等到结果全部返回。
public Object aggregationApi() {
long s = System.currentTimeMillis();
List ids = new ArrayList<>();
ids.add(“1”);
ids.add(“2”);
ids.add(“3”);
Map<String, UserResponse> callResult = AsyncTemplate.call(ids, id -> {
return userService.getUser(id);
}, u -> u.getId(), COMMON_POOL);
long e = System.currentTimeMillis();
System.out.println(“耗时:” + (e-s) + “ms”);
return “”;
}
另一个场景就是API聚合的场景,需要并行调用多个接口,将结果进行组装。
List params = new ArrayList<>();
AsyncCall<Integer, Integer> goodsQuery = new AsyncCall(“goodsQuery”, 1);
params.add(goodsQuery);
AsyncCall<String, OrderResponse> orderQuery = new AsyncCall(“orderQuery”, “100”);
params.add(orderQuery);
UserQuery q = new UserQuery();
q.setAge(18);
q.setName(“yinjihuan”);
AsyncCall<UserQuery, UserResponse> userQuery = new AsyncCall(“userQuery”, q);
params.add(userQuery);
AsyncTemplate.call(params, p -> {
if (p.getTaskId().equals(“goodsQuery”)) {
AsyncCall<Integer, Integer> query = p;
return goodsService.getGoodsName(query.getParam());
}
if (p.getTaskId().equals(“orderQuery”)) {
AsyncCall<String, OrderResponse> query = p;
return orderService.getOrder(query.getParam());
}
if (p.getTaskId().equals(“userQuery”)) {
AsyncCall<UserQuery, UserResponse> query = p;
return userService.getUser(query.getParam());
}
return null;
});
AsyncCall中定义参数和响应的类型,响应结果会在执行完后会自动设置到AsyncCall中。在call方法中需要根据taskId去做对应的处理逻辑,不同的taskId调用的接口不一样。
源码参考:https://github.com/yinjihuan/kitty
关于作者:尹吉欢,简单的技术爱好者,《Spring Cloud微服务-全栈技术与案例解析》, 《Spring Cloud微服务 入门 实战与进阶》作者, 公众号猿天地发起人。
欢迎大家关注我的微信公众号‘猿天地’, 猿天地由《Spring Cloud微服务-全栈技术与案例解析》作者尹吉欢创建。 JAVA方向为主(Spring Boot, Spring Cloud,Sharding JDBC,Elastic Job,Mongodb等)。 技术之路很漫长,我们一起前行吧。 作者代码分享GitHub地址:https://github.com/yinjihuan , 个人网站:http://cxytiandi.com/course , 有任何问题或者合作请联系我。微信号:jihuan900
好文要顶 关注我 收藏该文
猿天地
关注 - 0
粉丝 - 39
+加关注
0 0
« 上一篇: 面试官:如果让你写个分布式配置中心,就问你慌不慌
posted @ 2020-12-29 12:16 猿天地 阅读(62) 评论(0) 编辑 收藏
刷新评论刷新页面返回顶部
登录后才能发表评论,立即 登录 或 注册, 访问 网站首页
写给园友们的一封求助信
【推荐】News: 大型组态、工控、仿真、CADGIS 50万行VC++源码免费下载
【推荐】有你助力,更好为你——博客园用户消费观调查,附带小惊喜!
【推荐】博客园x丝芙兰-圣诞特别活动:圣诞选礼,美力送递
【推荐】了不起的开发者,挡不住的华为,园子里的品牌专区
【福利】AWS携手博客园为开发者送免费套餐+50元京东E卡
【推荐】未知数的距离,毫秒间的传递,声网与你实时互动
【推荐】新一代 NoSQL 数据库,Aerospike专区新鲜入驻
相关博文:
· 【一般BB】【19/10/20】
· [Python3]040文件一般使用
· API
· windows-API劫持(API-HOOK)
· mongodb-API
» 更多推荐…
最新 IT 新闻:
· 小米11上手体验:下了狠手,也留了一手
· 连摘两项大奖 腾讯云IPv6产品实力和领先部署能力再获权威机构认可
· 郭德帆:2021年对科技公司的一些预判
· 苹果造车:一场没有惊喜的心智战争
· 亚马逊在假日季期间销售了数十亿件产品 全球第三方销售增长50%
» 更多新闻…
昵称: 猿天地
园龄: 1年9个月
粉丝: 39
关注: 0
+加关注
< 2020年12月 >
日 一 二 三 四 五 六
29 30 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 1 2
3 4 5 6 7 8 9
搜索
找找看
谷歌搜索
常用链接
我的随笔
我的评论
我的参与
最新评论
我的标签
更多链接
我的标签
java(25)
Spring Cloud(15)
Sentinel(11)
ShardingJdbc(5)
nacos(4)
微信小程序(3)
redis(2)
mongodb(2)
Zuul(2)
SpringCloud(1)
更多
随笔档案
2020年12月(1)
2020年11月(4)
2020年10月(3)
2020年9月(5)
2020年8月(4)
2020年7月(4)
2020年6月(3)
2020年5月(5)
2020年4月(7)
2020年3月(6)
2020年2月(4)
2020年1月(2)
2019年12月(2)
2019年8月(1)
2019年7月(5)
更多
最新评论
- Re:Token认证,如何快速方便获取用户信息
给力 老表
–cc_mm_cc - Re:笑话:大厂都在用的任务调度框架我能不知道吗???
真·大厂(京东、OPPO、思科、浪潮等)都在用的调度框架
项目地址:
–KFCFans - Re:天天说要做性能优化,到底在优化什么?
赞
–一個未来 - Re:想要做读写分离,送你一些小经验
@小柒2012 巧了…
–猿天地 - Re:想要做读写分离,送你一些小经验
mark
–yi.shion
阅读排行榜 - spring cloud gateway 全局过滤器(12973)
- Spring Cloud Alibaba整合Sentinel流控(11801)
- 阿里Sentinel支持Spring Cloud Gateway啦(10914)
- Spring Cloud Gateway的全局异常处理(8850)
- Nacos做配置中心经常被问到的问题(8818)
评论排行榜 - 被产品经理怼了,线上出Bug为啥你不知道(19)
- 惊讶!我定的日志规范被CTO在全公司推广了(11)
- 恕我直言,牛逼哄哄的MongoDB你可能只会30%(7)
- 刚刚,给学妹普及了登录的两大绝学(4)
- 为了控制Bean的加载我使出了这些杀手锏(4)
推荐排行榜 - 惊讶!我定的日志规范被CTO在全公司推广了(20)
- 被产品经理怼了,线上出Bug为啥你不知道(7)
- 恕我直言,牛逼哄哄的MongoDB你可能只会30%(6)
- 天天说要做性能优化,到底在优化什么?(5)
- 大写的服,看完这篇你还不懂RocketMQ算我输(5)
Copyright © 2020 猿天地
Powered by .NET 5.0 on Kubernetes