* 获取令牌
* @return
*/
public boolean tryAcquire() {
return rateLimiter.tryAcquire();
}
}
@Autowired
private GuavaRateLimiterService rateLimiterService;
@ResponseBody
@RequestMapping(“/ratelimiter”)
public Result testRateLimiter(){
if(rateLimiterService.tryAcquire()){
return ResultUtil.success1(1001,“成功获取许可”);
}
return ResultUtil.success1(1002,“未获取到许可”);
}
jmeter起10个线程并发访问接口,测试结果如下:
可以发现,10个并发访问总是只有6个能获取到许可,结论就是能获取到RateLimiter.create(n)中n+1个许可,总体来看Guava的RateLimiter是比较优雅的。本文就是简单的提了下RateLimiter的使用。
推荐:Java进阶视频资源
翻阅发现使用上述方式使用RateLimiter的方式不够优雅,尽管我们可以把RateLimiter的逻辑包在service里面,controller直接调用即可,但是如果我们换成:自定义注解+切面 的方式实现的话,会优雅的多,详细见下面代码:
自定义注解类
import java.lang.annotation.*;
/**
* 自定义注解可以不包含属性,成为一个标识注解
*/
@Inherited
@Documented
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimitAspect {
}
自定义切面类
import com.google.common.util.concurrent.RateLimiter;
import com.simons.cn.springbootdemo.util.ResultUtil;
import net.sf.json.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
@Scope
@Aspect
public class RateLimitAop {
@Autowired
private HttpServletResponse response;
private RateLimiter rateLimiter = RateLimiter.create(5.0); //比如说,我这里设置"并发数"为5
@Pointcut(“@annotation(com.simons.cn.springbootdemo.aspect.RateLimitAspect)”)
public void serviceLimit() {
}
@Around(“serviceLimit()”)
public Object around(ProceedingJoinPoint joinPoint) {
Boolean flag = rateLimiter.tryAcquire();
Object obj = null;
try {
if (flag) {
obj = joinPoint.proceed();
}else{
String result = JSONObject.fromObject(ResultUtil.success1(100, “failure”)).toString();
output(response, result);
}
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println(“flag=” + flag + “,obj=” + obj);
return obj;
}
public void output(HttpServletResponse response, String msg) throws IOException {
response.setContentType(“application/json;charset=UTF-8”);
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
outputStream.write(msg.getBytes(“UTF-8”));
} catch (IOException e) {
e.printStackTrace();
} finally {
outputStream.flush();
outputStream.close();
}
}
}
测试controller类
最后
毕竟工作也这么久了 ,除了途虎一轮,也七七八八面试了不少大厂,像阿里、饿了么、美团、滴滴这些面试过程就不一一写在这篇文章上了。我会整理一份详细的面试过程及大家想知道的一些问题细节
美团面试经验
字节面试经验
菜鸟面试经验
蚂蚁金服面试经验
唯品会面试经验
因篇幅有限,图文无法详细发出
[外链图片转存中…(img-jqRZcx33-1721879457553)]
字节面试经验
[外链图片转存中…(img-kx2dlFL0-1721879457554)]
菜鸟面试经验
[外链图片转存中…(img-KyCWa7WI-1721879457554)]
蚂蚁金服面试经验
[外链图片转存中…(img-plcHof9x-1721879457554)]
唯品会面试经验
[外链图片转存中…(img-bwOQrtYu-1721879457554)]
因篇幅有限,图文无法详细发出