问题分析
tomcat在某些情况下会返回:
429 Too Many Requests
意思就是tomcat接收的请求太多
源码解析
org.apache.catalina.filters.RateLimitFilter
tomcat默认会有一个RateLimitFilter 实现的doFilter核心逻辑:
- 获取远程ip
- 计算当前ip在周期类的请求数
- 判断当前周期内的请求数是否超过限制
- 超过就返回异常码429
- 否则就走下一个Filter
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
String ipAddr = request.getRemoteAddr();
int reqCount = bucketCounter.increment(ipAddr);
request.setAttribute(RATE_LIMIT_ATTRIBUTE_COUNT, Integer.valueOf(reqCount));
if (enforce && (reqCount > actualRequests)) {
((HttpServletResponse) response).sendError(statusCode, statusMessage);
log.warn(sm.getString("rateLimitFilter.maxRequestsExceeded", filterName, Integer.valueOf(reqCount), ipAddr,
Integer.valueOf(getActualRequests()), Integer.valueOf(getActualDurationInSeconds())));
return;
}
chain.doFilter(request, response);
}
actualRequests默认情况下是300 统计窗口周期为10秒
调优
<filter>
<filter-name>rateLimiterFilter</filter-name>
<filter-class>
org.apache.catalina.filters.RateLimitFilter
</filter-class>
<init-param>
<param-name>bucketRequests</param-name>
<param-value>500</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>rateLimiterFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
调整bucketRequests来提高每个ip在10秒内可以处理的请求数,但是需要根据具体业务、情况来,提高这个值会导致cpu、内存提高以及可能导致gc的一些问题。