tomcat项目接口每隔一段时间出现延迟慢

1、问题出现

以前在搞性能优化,发现有些经过Spring boot feign的RPC接口比较慢,达到100-200ms,按理RPC调用都是IP直连,不该该超过100ms的,而后使用阿里开源的arthas工具测试接口执行时间,结果发现同一个接口大概每10秒会出现一次慢100+ms,如图:java

但实际上服务方的API层响应很快:算法

2、缘由分析

一、负载均衡到其它开发机

        疑点:因为我的开发机链接测试环境的注册地址,有可能测试接口会调用我的地址,但测试机ip为10.8,我的开发机为192.168,但如果分到我的机器应该不止100ms。spring

        操做:使用单独的测试机依然重现api

        结论:排除此缘由缓存

二、httpclient配置出错

        疑点: 1)怀疑线程keepalive过短,过时后从新开启线程,增长延迟,查看代码确实设置了keepalive=5,但开启线程不该该100ms那么多tomcat

        2)怀疑配置出错致使负载均衡算法延迟性能优化

        操做:使用arthas测试执行时间,以下图,能够看出最慢是读取流操做了session

        结论:排除此缘由负载均衡

三、服务方的tomcat配置问题

        疑点: 既然不是调用者问题,那就从接收者身上找问题好了,从tomcat接收请求开始跟踪,果真发现执行时间长的位置工具

这是什么模块呢?简单来讲就是加载jar中的静态资源,接口请求过来以后须要判断是否命中jar中的静态资源。查看源码发现每次加载完会缓存起来,但隔一段时间就从新加载,代表应该有地方清了缓存。搜索发现有个后台线程ContainerBackgroundProcessor执行gc方法,方法内会将缓存设null

// ContainerBackgroundProcessor部分代码
while(!ContainerBase.this.threadDone) {
    try {
        Thread.sleep((long)ContainerBase.this.backgroundProcessorDelay * 1000L);
    } catch (InterruptedException var8) {
        ;
    }
    if (!ContainerBase.this.threadDone) {
        // 用于重载standardContext、处理过时的session、清除jar中的静态资源缓存等等
        this.processChildren(ContainerBase.this);
    }
}
// AbstractArchiveResourceSet清除jar中的静态资源缓存
public void gc() {
    Object var1 = this.archiveLock;
    synchronized(this.archiveLock) {
        if (this.archive != null && this.archiveUseCount == 0L) {
            try {
                this.archive.close();
            } catch (IOException var4) {
                ;
            }
            this.archive = null;
            this.archiveEntries = null;
        }
 
    }
}

因为backgroundProcessorDelay默认为10,因此每10秒清一次缓存,这也印证了现象中的状况!注意ContainerBackgroundProcessor只清除是jar中的静态资源,项目中的静态资源并不会缓存于此,也就不会有影响了。

经过debug发现,每次加载的静态资源出处是springfox-swagger-ui.jar(自动生成api文档),里面的确存在静态资源,因而将其依赖去掉,发现延迟100ms的状况也消失了!

结论:tomcat在启动时,经过StaticResourceConfigurer.addResourceJars将全部jar中的静态资源路径保存到list中,请求过来时先今后list中加载所有资源并检查是否命中,是则返回,若全部jar均没有静态资源则不会加载;为了增长性能,在加载完静态资源后会缓存下来,但设置了一个后台线程,定时清除缓存(我的认为:tomcat这样作应该是为了热部署,但彻底没有配置控制不gc的确有点沙雕,虽然耗时只有100+ms)。

3、结论

最终结论:没事不要把静态资源扔到jar里!!!

最终结论:没事不要把静态资源扔到jar里!!!

最终结论:没事不要把静态资源扔到jar里!!!

相关文章
相关标签/搜索