面试官问我:什么是高并发下的请求合并? (中)

简介: 面试官问我:什么是高并发下的请求合并? (中)

高并发的请求合并


理解了请求合并,那我们再来说说当他前面加上高并发这三个字之后,会发生什么变化。

首先不论是在请求合并的前面加上多么狂拽炫酷吊炸天的形容词,说的多么的天花乱坠,它也还是一个请求合并。

那么队列和定时任务的这个基础结构肯定是不会变的。

高并发的情况下,就是请求量非常的大嘛,那我们把定时任务的频率调高一点不就行了?

以前 100ms 内就会过来 50 笔请求,我每收到一笔就是立即处理了。

现在我们把请求先放到队列里面缓存着,然后每 100ms 就执行一次定时任务。

100ms 到了之后,就会有定时任务把这 100ms 内的所有请求取走,统一处理。

同时,我们还可以控制队列的长度,比如只要 50ms 队列的长度就达到了 50,这个时候我也进行合并处理。不需要等待到 100ms 之后。

其实写到这里,高并发的请求合并的答案已经出来了。关键点就三个:

一是需要借助队列加定时任务实现。

二是控制定时任务的执行时间.

三是控制缓冲队列的任务长度。

方案都想到了,把代码写出来岂不是很容易的事情。而且对于这种面试的场景图,一般都是讨论技术方案,而不太会去讨论具体的代码。

当讨论到具体的代码的时候,要么是对你的方案存疑,想具体的探讨一下落地的可行性。要么就是你答对了,他要准备从代码的交易开始衍生另外的面试题了。

总之,大部分情况下,不会在你给了一个面试官觉得错误的方案之后,他还和你讨论代码细节。你们都不在一个频道了,赶紧换题吧,还聊啥啊。

实在要往代码实现上聊,那么大概率他是在等着你说出一个框架:Hystrix。


Hystrix框架


其实这题,你要是知道 Hystrix,很容易就能给出一个比较完美的回答。

因为 Hystrix 就有请求合并的功能。给大家演示一下。

假设我们有一个学生信息查询接口,调用频率非常的高。对于这个接口我们需要做请求合并处理。

做请求合并,我们至少对应着两个接口,一个是接收单个请求的接口,一个处理把单个请求汇总之后的请求接口。

所以我们需要先提供两个 service:


image.png


其中根据指定 id 查询的接口,对应的 Controller 是这样的:


image.png


服务启动起来后,我们用线程池结合 CountDownLatch 模拟 20 个并发请求:


image.png


从控制台可以看到,瞬间接受到了 20 个请求,执行了 20 次查询 sql:


image.png

很明显,这个时候我们就可以做请求合并。每收到 10 次请求,合并为一次处理,结合 Hystrix 代码就是这样的,为了代码的简洁性,我采用的是注解方式:


image.png

在上面的图片中,有两个方法,一个是 getUserId,直接返回的是null,因为这个方法体不重要,根本就不会执行。

在 @HystrixCollapser 里面可以看到有一个 batchMethod 的属性,其值是 getUserBatchById。

也就是说这个方法对应的批量处理方法就是 getUserBatchById。当我们请求 getUserById 方法的时候,Hystrix 会通过一定的逻辑,帮我们转发到 getUserBatchById 上。

所以我们调用的还是 getUserById 方法:

image.png

同样,我们用线程池结合 CountDownLatch 模拟 20 个并发请求,只是变换了请求地址:

image.png

同样是接受到了 20 个请求,但是每 10 个一批,只执行了两个sql语句。

从 20 个 sql 到 2 个 sql,这就是请求合并的威力。请求合并的处理速度甚至比单个处理还快,这也是性能的提升。

那假设我们只有 5 个请求过来,不满足 10 个这个条件呢?

别忘了,我们还有定时任务呢。

在 Hystrix 中,定时任务默认是每 10ms 执行一次:

image.png

同时我们可以看到,如果不设置 maxRequestsInBatch,那么默认是 Integer.MAX_VALUE。

也就是说,在 Hystrix 中做请求合并,它更加侧重的是时间方面。

功能演示,其实就这么简单,代码量也不多,有兴趣的朋友可以直接搭个 Demo 跑跑看。看看 Hystrix 的源码。

我这里只是给大家指几个关键点吧。

第一个肯定是我们需要找到方法入口。

你想,我们的 getUserById 方法的方法体里面直接是 return null,也就是说这个方法体是什么根本就不重要,因为不会去执行方法体中的代码。它只需要拦截到方法入参,并缓存起来,然后转发到批量方法中去即可。

然后方法体上面有一个 @HystrixCollapser 注解。

那么其对应的实现方式你能想到什么?

肯定是 AOP 了嘛。

所以,我们拿着这个注解的全路径,进行搜索,啪的一下,很快啊,就能找到方法的入口:

com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect#methodsAnnotatedWithHystrixCommand

image.png

在入口处打上断点,就可以开始调试了:


image.png

目录
相关文章
|
4月前
|
缓存 前端开发 中间件
[go 面试] 前端请求到后端API的中间件流程解析
[go 面试] 前端请求到后端API的中间件流程解析
|
2月前
|
缓存 负载均衡 API
抖音抖店API请求获取宝贝详情数据、原价、销量、主图等参数可支持高并发调用接入演示
这是一个使用Python编写的示例代码,用于从抖音抖店API获取商品详情,包括原价、销量和主图等信息。示例展示了如何构建请求、处理响应及提取所需数据。针对高并发场景,建议采用缓存、限流、负载均衡、异步处理及代码优化等策略,以提升性能和稳定性。
|
2月前
|
缓存 算法 架构师
京东面试:如何设计600Wqps高并发ID?如何解决时钟回拨问题?
资深架构师尼恩在其读者交流群中分享了关于分布式ID系统的设计与实现,特别是针对高并发场景下的解决方案。他强调了分布式ID系统在高并发核心组件中的重要性,并详细介绍了百度的UidGenerator,这是一个基于Snowflake算法改进的Java实现,旨在解决分布式系统中的唯一ID生成问题。UidGenerator通过自定义workerId位数和初始化策略,支持虚拟化环境下的实例自动重启和漂移,其单机QPS可达600万。此外尼恩的技术分享不仅有助于提升面试表现,还能帮助开发者在实际项目中应对高并发挑战。
京东面试:如何设计600Wqps高并发ID?如何解决时钟回拨问题?
|
4月前
|
JavaScript 前端开发 Java
面试官:假如有几十个请求,如何去控制并发?
面试官:假如有几十个请求,如何去控制并发?
|
5月前
|
监控 网络协议 Java
Java面试题:解释Java NIO与BIO的区别,以及NIO的优势和应用场景。如何在高并发应用中实现NIO?
Java面试题:解释Java NIO与BIO的区别,以及NIO的优势和应用场景。如何在高并发应用中实现NIO?
76 0
|
5月前
|
设计模式 安全 NoSQL
Java面试题:设计一个线程安全的单例模式,并解释其内存占用和垃圾回收机制;使用生产者消费者模式实现一个并发安全的队列;设计一个支持高并发的分布式锁
Java面试题:设计一个线程安全的单例模式,并解释其内存占用和垃圾回收机制;使用生产者消费者模式实现一个并发安全的队列;设计一个支持高并发的分布式锁
72 0
|
5月前
|
设计模式 安全 Java
Java面试题:如何实现一个线程安全的单例模式,并确保其在高并发环境下的内存管理效率?如何使用CyclicBarrier来实现一个多阶段的数据处理任务,确保所有阶段的数据一致性?
Java面试题:如何实现一个线程安全的单例模式,并确保其在高并发环境下的内存管理效率?如何使用CyclicBarrier来实现一个多阶段的数据处理任务,确保所有阶段的数据一致性?
68 0
|
5月前
|
设计模式 存储 缓存
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
59 0
|
5月前
|
存储 安全 Java
Java面试题:假设你正在开发一个Java后端服务,该服务需要处理高并发的用户请求,并且对内存使用效率有严格的要求,在多线程环境下,如何确保共享资源的线程安全?
Java面试题:假设你正在开发一个Java后端服务,该服务需要处理高并发的用户请求,并且对内存使用效率有严格的要求,在多线程环境下,如何确保共享资源的线程安全?
71 0
|
5月前
|
并行计算 安全 算法
Java面试题:Java内存管理与多线程并发处理,设计一个Java应用,该应用需要处理大量并发用户请求,同时要求对内存使用进行优化,如何通过垃圾回收机制优化内存使用?
Java面试题:Java内存管理与多线程并发处理,设计一个Java应用,该应用需要处理大量并发用户请求,同时要求对内存使用进行优化,如何通过垃圾回收机制优化内存使用?
43 0