精华内容
下载资源
问答
  •  使用top命令查看服务器的资源使用情况,主要分析CPU和内存的使用情况(top 命令是 Linux 下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,默认5秒刷新一下进程列表,所以类似于 Windows 的任务...
  • web 项目 tomcat 引起 请求相应 问题

    千次阅读 2019-07-30 17:34:08
    刚进公司 配置完开发环境,启动项目发现 请求接口一直很 F12 中查看 timing 总有请求或静态资源 stalled 和 content download 非常的 百度了一下午,各种尝试 1.刚开始怀疑网路有问题。但是发现下载速度什么的...

    刚进公司  配置完开发环境,启动项目发现 请求接口一直很慢 F12 中查看 timing  总有请求或静态资源  stalled 和 content download 非常的慢 百度了一下午,各种尝试

    1.刚开始怀疑网路有问题。但是发现下载速度什么的都不慢的。

    2.静态资源需要shiro(顺便吐槽下:古老的项目)权限验证,设置过滤器跳过验证还是很慢

    3.为tomcat设置压缩参数

     

    还是很慢,这个时候我已经崩溃了,快要打算破罐子破摔,就这样凑合的用吧

    然后问了身边的同事,他们说他们的请求不慢的,

    于是我想到我的tomcat是 8.XXX版本,去找了一个 6.X 的再跑一次项目。。发现接口变快了,一切正常。。飞一样的感觉

    最终终于百度找到了答案,话不多说,看图

     

     

    展开全文
  • nginx代理tomcat后访问非常tomcat本身很快,windows服务器环境下) 通过增加红色部分的配置,瞬间看到效果 client_max_body_size 1000m; proxy_connect_timeout 1; proxy_send_timeout 30; proxy_read_timeout ...

    nginx代理tomcat后访问非常慢(tomcat本身很快,windows服务器环境下)

    通过增加红色部分的配置,瞬间看到效果

    client_max_body_size 1000m;
    proxy_connect_timeout 1;
    proxy_send_timeout 30;
    proxy_read_timeout 60;

    
    #user  nobody;
    worker_processes  1;
    
    #error_log  logs/error.log;
    #error_log  logs/error.log  notice;
    #error_log  logs/error.log  info;
    
    #pid        logs/nginx.pid;
    
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
        #                  '$status $body_bytes_sent "$http_referer" '
        #                  '"$http_user_agent" "$http_x_forwarded_for"';
    
        #access_log  logs/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        #keepalive_timeout  0;
        keepalive_timeout  65;
    
        #gzip  on;
    
         fastcgi_connect_timeout 100;
         fastcgi_send_timeout 100;
         fastcgi_read_timeout 100;
         fastcgi_buffer_size 64k;
         fastcgi_buffers 8 128k;
         fastcgi_busy_buffers_size 128k;
         fastcgi_temp_file_write_size 128k;
    
        upstream tomcat_server {
            ip_hash; 
            server 127.0.0.1:51080;
            server 127.0.0.1:52080;
    	server 127.0.0.1:53080;
    
    	#server 127.0.0.1:51080 weight=85;
            #server 127.0.0.1:52080 weight=10;
    	#server 127.0.0.1:53080 weight=5;
        }
        server {
            listen       80;
            server_name  10.226.57.129;
    	access_log  logs/access_10.226.57.129_80.log;
            location / {
                root   html;
                index  index.html index.htm;
    	    proxy_pass   http://tomcat_server;
    	    proxy_cookie_path  / /;
    	    proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    client_max_body_size 1000m;
    proxy_connect_timeout 1;
    proxy_send_timeout 30;
    proxy_read_timeout 60;
            }
        }
        server {
            listen       80;
            server_name  localhost;
    
            #charset koi8-r;
    
            #access_log  logs/host.access.log  main;
    
            location / {
                root   html;
                index  index.html index.htm;
            }
    
            #error_page  404              /404.html;
    
            # redirect server error pages to the static page /50x.html
            #
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
    
            # proxy the PHP scripts to Apache listening on 127.0.0.1:80
            #
            #location ~ \.php$ {
            #    proxy_pass   http://127.0.0.1;
            #}
    
            # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
            #
            #location ~ \.php$ {
            #    root           html;
            #    fastcgi_pass   127.0.0.1:9000;
            #    fastcgi_index  index.php;
            #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            #    include        fastcgi_params;
            #}
    
            # deny access to .htaccess files, if Apache's document root
            # concurs with nginx's one
            #
            #location ~ /\.ht {
            #    deny  all;
            #}
        }
    
    
        # another virtual host using mix of IP-, name-, and port-based configuration
        #
        #server {
        #    listen       8000;
        #    listen       somename:8080;
        #    server_name  somename  alias  another.alias;
    
        #    location / {
        #        root   html;
        #        index  index.html index.htm;
        #    }
        #}
    
    
        # HTTPS server
        #
        #server {
        #    listen       443 ssl;
        #    server_name  localhost;
    
        #    ssl_certificate      cert.pem;
        #    ssl_certificate_key  cert.key;
    
        #    ssl_session_cache    shared:SSL:1m;
        #    ssl_session_timeout  5m;
    
        #    ssl_ciphers  HIGH:!aNULL:!MD5;
        #    ssl_prefer_server_ciphers  on;
    
        #    location / {
        #        root   html;
        #        index  index.html index.htm;
        #    }
        #}
    
    }
    

     

    展开全文
  • 1.检查内存是否溢出 free -h  若内存溢出,首先检查代码是否存在内存泄漏 ,其次就是扩容 2.检查线程池是不是太小,存在线程等待过多 ... 查看tomcat的PID ... 修改tomcat线程池数以及tomcat运行模式(m...

    1.检查内存是否溢出

          free -h

      若内存溢出,首先检查代码是否存在内存泄漏 ,其次就是扩容

    2.检查线程池是不是太小,存在线程等待过多

      查看tomcat的PID

    ps -aux|grep tomcat

      查看tomcat对应的线程数

    ps -Lf PID|wc -l

      修改tomcat线程池数以及tomcat运行模式(maxThreads:tomcat起动的最大线程数,即同时处理的任务个数,默认值为200 acceptCount:当tomcat起动的线程数达到最大 时,接受排队的请求个数,默认值为100)

    在linux上,默认使用的是bio connector。与nio相比,bio性能较低。将<TOMCAT_HOME>/conf/server.xml中的如下配置片段:

    <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />

    修改为:

        <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
                   connectionTimeout="20000"
                   redirectPort="8443" maxThreads="800" acceptCount="1000"/>

    就可将http connector切换至nio了。

     

    更多细节请参考:http://www.365mini.com/page/tomcat-connector-mode.htm

            http://blog.csdn.net/wngua/article/details/70904991

            https://www.cnblogs.com/tyb1222/p/4583983.html

            https://www.cnblogs.com/magmell/p/7086229.html

         

    转载于:https://www.cnblogs.com/LiLiliang/p/8477943.html

    展开全文
  • 1. 前言 参考“The HTTP Connector”...Tomcat的每个请求的持续期间,都需要一个线程。如果当前存在的用来处理请求的线程不足以处理接收到的并发请求,将会创

    1. 前言

    参考“The HTTP Connector”( http://tomcat.apache.org/tomcat-8.5-doc/config/http.html#Introduction ),描述了当Tomcat接收到新的请求,直到超过Tomcat处理能力时,Tomcat的处理过程,涉及到三个相关的属性:maxThreads、maxConnections、acceptCount。

    • Tomcat的每个请求的持续期间,都需要一个线程。如果当前存在的用来处理请求的线程不足以处理接收到的并发请求,将会创建另外的线程,直接达到配置的maxThreads属性。

    • 当连接数量达到了maxConnections属性时,Tomcat服务器会接收(accept),但不会处理更多的请求。额外的请求会被阻塞,直到被处理的连接数量降到maxConnections以下,此时Tomcat服务器会开始接受并处理新的连接。当超过了以上限制时,操作系统可能仍然会基于acceptCount属性值接收新的连接。

    • 如果仍然接收到更多的并发请求,这些请求会堆积在Connector创建的服务器socket内,直到达到配置的acceptCount属性。更多的并发请求会接收到连接被拒绝(connection refused)的错误,直到可以有处理的资源可用为止。

    maxThreads、maxConnections、acceptCount属性是Tomcat标准HTTP Connector(NIO, NIO2,APR/native)都支持的属性。

    maxQueueSize是Executor元素的属性,用于配置处理请求的任务队列长度。

    当Tomcat接收的请求超过了以上属性时,都会导致Tomcat无法正常访问,以下分别进行分析。

    以下使用的Tomcat版本为8.5.63,使用NIO Connector。

    2. Tomcat connector分析

    可参考 https://blog.csdn.net/a82514921/article/details/115359632

    3. maxThreads(处理请求最大线程数)

    maxThreads属性指定当前Connector可以创建用于处理请求的最大线程数,决定了可以处理并发请求的最大数量。该属性默认值为200。

    若当前Connector关联了某个executor时,会使用指定的executor执行任务,而不会使用Connector的内部线程池,maxThreads属性也会被忽略。

    以下首先分析Connector使用内部线程池的情况。

    3.1. 创建处理请求的线程池代码分析

    Tomcat Connector协议类的父类为org.apache.coyote.AbstractProtocol,该类在tomcat-coyote.jar中,使用了Connector的maxThreads属性,get/setMaxThreads()方法调用了AbstractEndpoint类型endpoint对象的get/setMaxThreads()方法,对成员变量maxThreads进行了操作。

    AbstractEndpoint类的子类NioEndpoint、Nio2Endpoint、AprEndpoint中,在startInternal()方法中判断若this.getExecutor()等于null,则执行this.createExecutor()方法,在Nio2Endpoint类的bind()方法中,也执行了该方法。

    createExecutor()方法定义在AbstractEndpoint类中,该方法创建用于处理请求的线程池,执行以下操作:

    • 设置internalExecutor=true,代表Connector使用内部线程池;

    • 创建org.apache.tomcat.util.threads.TaskQueue类的对象,作为任务队列;

    • 创建org.apache.tomcat.util.threads.TaskThreadFactory类的对象,该类继承自java.util.concurrent.ThreadFactory类,在创建以上对象时,namePrefix设置为“this.getName() + “-exec-””;

    在之前分析过,AbstractEndpoint类的getName()返回值等于AbstractProtocol类的getName()返回值,AbstractProtocol各子类及对应的AbstractEndpoint子类,及Connector使用HTTP协议时(使用HTTPS协议时不同)对应的getName()返回值开头如下:

    AbstractProtocol各子类AbstractEndpoint各子类getName()返回值开头
    Http11ProtocolNioEndpointhttp-nio
    Http11NioProtocolNioEndpointhttp-nio
    Http11Nio2ProtocolNio2Endpointhttp-nio2
    Http11AprProtocolAprEndpointhttp-apr
    • 创建org.apache.tomcat.util.threads.ThreadPoolExecutor类的对象,作为线程池,corePoolSize使用this.getMinSpareThreads(),maximumPoolSize使用this.getMaxThreads(),keepAliveTime使用60秒,workQueue使用上述TaskQueue类的对象,threadFactory使用上述TaskThreadFactory类的对象;

    getMinSpareThreads()方法返回值可认为等于minSpareThreads属性值,getMaxThreads()方法返回值可认为等于maxThreads属性值。即以上创建的用于处理请求的线程池,corePoolSize等于minSpareThreads,maximumPoolSize等于maxThreads。

    使用jstack或jconsole命令查看Tomcat进程中Connector相关的线程,可以看到如“http-nio-8080-exec-xxx”之类的线程,即以上代码创建的线程。

    • 调用以上生成的TaskQueue类的对象的setParent()方法,设置为以上生成的ThreadPoolExecutor类的对象。

    3.2. Tomcat线程池与任务队列代码分析

    3.2.1. Tomcat线程池创建过程

    org.apache.tomcat.util.threads.ThreadPoolExecutor类,继承自java.util.concurrent.ThreadPoolExecutor类,在tomcat-util.jar中。

    以上创建org.apache.tomcat.util.threads.ThreadPoolExecutor类对象时,调用的构造方法为“ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)”,在该方法中,会调用父类即java.util.concurrent.ThreadPoolExecutor类的构造方法,传入的RejectedExecutionHandler对象为org.apache.tomcat.util.threads.ThreadPoolExecutor类中的RejectHandler类的对象。

    org.apache.tomcat.util.threads.ThreadPoolExecutor$RejectHandler类实现了RejectedExecutionHandler接口,在rejectedExecution()方法中抛出了RejectedExecutionException异常,与java.util.concurrent.ThreadPoolExecutor$AbortPolicy效果相同。

    即Tomcat Connector内部线程池,拒绝策略使用RejectedExecutionException,即抛出异常以拒绝任务。

    3.2.2. Tomcat任务队列创建过程

    TaskQueue类继承自java.util.concurrent.LinkedBlockingQueue类。

    以上创建TaskQueue类对象时,调用的构造方法为无参数构造方法,会调用父类LinkedBlockingQueue的无参数构造方法。

    LinkedBlockingQueue类的无参数构造方法调用了LinkedBlockingQueue(int capacity)构造方法,传入的容量为Integer.MAX_VALUE,可认为长度是无限。

    即Tomcat Connector内部线程池的任务队列长度为无限(Integer.MAX_VALUE)。

    3.2.3. Tomcat线程池创建新线程的条件

    org.apache.tomcat.util.threads.ThreadPoolExecutor类的execute()方法调用java.util.concurrent.ThreadPoolExecutor类的execute()方法。在java.util.concurrent.ThreadPoolExecutor类中,addWorker()方法用于尝试创建工作线程。

    众所周知,使用java.util.concurrent.ThreadPoolExecutor类,若线程数已达到corePoolSize且未超过maximumPoolSize,当队列满时,才会创建新的线程;使用org.apache.tomcat.util.threads.ThreadPoolExecutor类,若线程数已达到corePoolSize且未超过maximumPoolSize,当有请求没有空闲线程能够处理时,就会创建新的线程。以下针对以上创建新线程条件的不同进行对比。

    在java.util.concurrent.ThreadPoolExecutor类的execute()方法中,若调用workQueue.offer()方法向工作队列中插入元素返回false,则会调用addWorker()方法尝试创建工作线程。

    对于LinkedBlockingQueue类的offer()方法,仅当队列元素满时才会返回false,使java.util.concurrent.ThreadPoolExecutor类的execute()方法创建新的线程。

    对于TaskQueue类的offer()方法,当this.parent.getPoolSize()小于this.parent.getMaximumPoolSize()时会返回false,即TaskQueue类对象关联的org.apache.tomcat.util.threads.ThreadPoolExecutor类对象的线程数量小于maximumPoolSize时,就可以创建新的线程。

    3.3. Tomcat处理请求线程池已满场景模拟及分析

    将Tomcat Connector的maxConnections、acceptCount属性值配置得足够大,将maxThreads设置为1,模拟Tomcat处理请求线程池已满的场景。

    <Connector port="8081" protocol="org.apache.coyote.http11.Http11NioProtocol" acceptCount="100" maxConnections="100" maxThreads="1"/>
    

    使用curl命令发起请求,访问Tomcat对应端口,通过–trace-time参数指定打印curl每一步执行时的时间。

    在多个终端同时执行以下命令,使每次请求将Tomcat处理请求的线程占用指定时间:

    curl -v --trace-time http://127.0.0.1:8081/test/sleep_seconds.jsp?sleep_seconds=5
    

    可以观察到以下现象:

    • 当Tomcat处理请求的线程不够时,新的请求能够建立连接,但无法立刻读取到服务器返回数据,会被阻塞,现象与Acceptor线程被终止时相同,客户端连接不会被Tomcat终止;

    • 当Tomcat处理请求的线程执行完毕变为空闲后,会开始依次执行被阻塞的请求(如在3个终端分别执行以上命令,分别需要等待5、10、15秒读取到服务器返回)。

    以上现象的原因如下:

    • Tomcat处理请求时,当连接完成并被accept之后,使用线程池处理对应请求;

    • 当线程池数量达到maxThreads导致不能再创建线程后,新到的请求如果完成连接并被accept之后,会被加入到任务队列中;

    • Tomcat Connector默认使用内部线程池,对应的任务队列长度为Integer.MAX_VALUE,可认为队列长度为无限;

    • 如果一直没有线程处理结束变为空闲,则处在任务队列中的请求会一直等待,客户端此时无法读取到Tomcat的返回,Tomcat也不会主动将任务队列中的请求结束连接,因此客户端会一直等待;

    • 当有线程处理结束变为空闲后,会依次处理任务队列中的请求,此时客户端可以读取到Tomcat的返回,并结束此次请求。

    以上sleep_seconds.jsp文件用于使Tomcat的处理请求的线程在执行时等待指定的时间,内容如下,

    <%@ page import="java.lang.*"%>
    
    <%
    	String sleepSeconds = request.getParameter("sleep_seconds");
    	System.out.println("begin to sleep: " + Thread.currentThread().getName() + " : " + sleepSeconds);
    	
    	long startTime = System.currentTimeMillis();
    	Thread.sleep(Integer.parseInt(sleepSeconds) * 1000L);
    	System.out.println("after sleep: " + Thread.currentThread().getName() + " : " + sleepSeconds);
    	out.print("start: " + startTime + " end: " + System.currentTimeMillis());
    %>
    

    4. maxQueueSize(处理请求队列长度)

    Tomcat Connector默认使用内部线程池,当Connector使用命名Executor时,可以通过maxQueueSize属性指定处理请求队列长度。

    4.1. Connector使用命名Executor

    Tomcat标准HTTP Connector都支持executor属性,该属性用于指定conf/server.xml配置文件中Executor元素。当有配置该属性,且对应的命名executor存在时,connector会使用对应的executor(否则),其他与线程相关的属性会被忽略。否则connector会使用私有的内部线程池。

    参考 “The Executor (thread pool)”( http://tomcat.apache.org/tomcat-8.5-doc/config/executor.html ),Executor元素支持以下配置:

    • className

    指定线程池实现类,需要实现org.apache.catalina.Executor接口,默认值为org.apache.catalina.core.StandardThreadExecutor。

    • name

    线程池名称,在server.xml可通过该名称进行引用,该属性必须指定,且需要是唯一的。

    • daemon

    指定线程是否需要为daemon线程,默认值为true。

    • namePrefix

    指定由线程池创建的每个线程名称的前缀,线程名称格式为namePrefix + threadNumber。

    • maxThreads

    线程池中活动线程最大数量,默认值为200。该默认值与Connector使用内部线程池时值相同。

    • minSpareThreads

    永远保持活动的线程最小值,默认值为25。当Connector使用内部线程池时,该默认值为10。

    • maxIdleTime

    空闲线程被关闭前的时间毫秒数,默认值为60000(1分钟)。

    • maxQueueSize

    能够进入队列排队的可执行任务最大数量,当超过该值后,Tomcat会拒绝新的任务。默认值为Integer.MAX_VALUE。

    4.2. 命名Executor创建线程池代码分析

    命名Executor默认使用org.apache.catalina.core.StandardThreadExecutor类,该类在catalina.jar中,startInternal()方法中创建了线程池,执行以下操作:

    • 创建TaskQueue对象,作为任务队列,调用构造方法时传入的容量为this.maxQueueSize(创建内部线程池时,无法指定任务队列容量);

    • 创建TaskThreadFactory对象,namePrefix使用this.namePrefix,默认值为“tomcat-exec-”,daemon使用this.daemon;

    • 创建org.apache.tomcat.util.threads.ThreadPoolExecutor类的对象,作为线程池,与AbstractEndpoint.createExecutor()方法中的操作类似;

    • 调用以上生成的TaskQueue类的对象的setParent()方法,设置为以上生成的ThreadPoolExecutor类的对象。

    4.3. Tomcat线程池执行任务代码分析

    StandardThreadExecutor类的execute()方法的执行步骤如下:

    • 调用executor对象,即org.apache.tomcat.util.threads.ThreadPoolExecutor类的execute()方法;

    • 若出现RejectedExecutionException异常,且调用((TaskQueue)this.executor.getQueue()).force()方法向线程池任务队列中再次插入当前任务失败时,抛出异常RejectedExecutionException(“Work queue full.”)。

    org.apache.tomcat.util.threads.ThreadPoolExecutor类的execute()方法的主要执行步骤如下:

    • 调用super即java.util.concurrent.ThreadPoolExecutor类的execute()方法;

    • 若出现RejectedExecutionException异常,且调用((TaskQueue)this.executor.getQueue()).force()方法向线程池任务队列中再次插入当前任务失败时,抛出异常RejectedExecutionException。

    4.4. Tomcat处理请求的任务队列已满场景模拟

    Tomcat maxQueueSize默认值为Integer.MAX_VALUE,大于21亿,超过该值的可能性很小。为了模拟Tomcat maxQueueSize不够的场景,使用以下配置,指定Executor的maxThreads、minSpareThreads与maxQueueSize均为1。

    <Executor name="testThreadPool" maxThreads="1" minSpareThreads="1" maxQueueSize="1"/>
    
    <Connector port="8081" protocol="org.apache.coyote.http11.Http11NioProtocol" executor="testThreadPool"/>
    

    使用curl命令发起以下请求,使每次请求将Tomcat处理请求的线程占用较长的时间:

    curl -v --trace-time http://127.0.0.1:8081/test/sleep_seconds.jsp?sleep_seconds=100
    

    第一个被Tomcat处理的请求会执行以上jsp文件,等待指定的时间后会返回;

    由于Executor的maxThreads为1,第二个请求没有线程能够处理,会进入任务队列中,等待第一个请求被处理完毕后会被执行,再等待指定的时间后会返回;

    由于Executor的maxQueueSize为1,第三个及之后的请求没有线程能够处理,也无法加入到任务队列中,会被拒绝连接,Tomcat会主动断开连接。

    被拒绝连接的curl执行结果如下所示:

    13:15:42.342233 * About to connect() to 127.0.0.1 port 8081 (#0)
    13:15:42.342342 *   Trying 127.0.0.1...
    13:15:42.342450 * Connected to 127.0.0.1 (127.0.0.1) port 8081 (#0)
    13:15:42.342512 > GET /test/sleep_seconds.jsp?sleep_seconds=100 HTTP/1.1
    13:15:42.342512 > User-Agent: curl/7.29.0
    13:15:42.342512 > Host: 127.0.0.1:8081
    13:15:42.342512 > Accept: */*
    13:15:42.342512 >
    13:15:42.345888 * Recv failure: Connection reset by peer
    13:15:42.345931 * Closing connection 0
    curl: (56) Recv failure: Connection reset by peer
    

    查看Tomcat的catalina.out日志,可以看到以下日志,异常信息为“java.util.concurrent.RejectedExecutionException: Work queue full.”,由StandardThreadExecutor.execute()方法抛出,与上述代码一致。

    [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@10dcbc52:org.apache.tomcat.util.net.NioChannel@474893b1:java.nio.channels.SocketChannel[connected local=/127.0.0.1:8081 remote=/127.0.0.1:56713]] for processing
            java.util.concurrent.RejectedExecutionException: Work queue full.
                    at org.apache.catalina.core.StandardThreadExecutor.execute(StandardThreadExecutor.java:172)
                    at org.apache.tomcat.util.net.AbstractEndpoint.processSocket(AbstractEndpoint.java:1105)
                    at org.apache.tomcat.util.net.NioEndpoint$Poller.processKey(NioEndpoint.java:896)
                    at org.apache.tomcat.util.net.NioEndpoint$Poller.run(NioEndpoint.java:872)
                    at java.lang.Thread.run(Thread.java:748)
    

    5. maxConnections(accept连接最大数量)

    maxConnections属性指定了Tomcat服务器在同一时间会accept并处理的连接数量。对于NIO与NIO2 Connector,该默认值为10000,对于APR/nativeConnector,默认值为8192。

    5.1. 创建Acceptor线程的代码

    创建Acceptor线程的代码,可参考 https://blog.csdn.net/a82514921/article/details/115359632

    5.2. 对连接进行accept处理代码分析

    AbstractEndpoint类的startAcceptorThreads()方法中创建了Acceptor线程,在创建Thread对象时,传入的Runnable对象为this.createAcceptor()方法的返回值,AbstractEndpoint类的createAcceptor()方法为抽象方法,AbstractEndpoint子类的createAcceptor()方法返回值如下:

    类名createAcceptor()方法返回值
    NioEndpointnew NioEndpoint.Acceptor()
    Nio2Endpointnew Nio2Endpoint.Acceptor()
    AprEndpointnew AprEndpoint.Acceptor()

    NioEndpoint$Acceptor、Nio2Endpoint$Acceptor、AprEndpoint$Acceptor类都继承自AbstractEndpoint$Acceptor类,实现了Runnable接口。以上类的run()方法中,在调用accept()方法接收连接前,都会调用AprEndpoint.this.countUpOrAwaitConnection()方法;在出现异常,或关闭连接前,都会调用this.countDownConnection()方法。

    countUpOrAwaitConnection()方法定义在AbstractEndpoint类中,在其中调用了类型为LimitLatch的成员变量connectionLimitLatch的countUpOrAwait()方法;countDownConnection()方法也定义在以上类中,在其中调用了类型为LimitLatch的成员变量connectionLimitLatch的countDown()方法。

    AbstractEndpoint类的成员变量connectionLimitLatch在initializeConnectionLatch()方法中,进行实例化,调用LimitLatch类的构建方法,传入的参数为this.getMaxConnections(),即Connector的maxConnections属性值。

    参考 http://tomcat.apache.org/tomcat-8.5-doc/api/org/apache/tomcat/util/threads/LimitLatch.html 。

    LimitLatch类的构造方法,使用指定的初始限制实例化一个LimitLatch对象,该限制用于指定此锁存器并发获取的最大值。

    调用countUpOrAwait()方法时,如果存在可用共享锁存器,则获取一个共享锁存器;如果当前没有可用的共享锁存器,则等待一个共享锁存器。

    countDown()方法可以释放一个共享锁存器,使它可被其他线程使用。

    根据以上代码可知,AbstractEndpoint子类执行accept操作时的并发控制实现如下:

    • 初始化一个最大并发获取数等于maxConnections属性值的共享锁存器;

    • 在执行accept操作前,获取一个共享锁存器,若能获取到则立即执行accept操作;若无法获取到则等待获取到共享锁存器后,再执行accept操作;

    • 当连接出现异常,或需要关闭连接前,释放当前使用的共享锁存器,使其他线程能够使用。

    5.3. ServerSocket不进行accept处理场景分析

    在模拟Tomcat最大连接数已满的场景之前,首先分析Java的ServerSocket监听端口但不进行accept处理时的场景(不进行accept处理,与Tomcat最大连接数已满,无法进行accept处理可以认为是相同的场景)。

    以下代码,分别对应BIO及NIO的ServerSocket不进行accept处理的场景:

    import java.net.InetSocketAddress;
    import java.net.ServerSocket;
    
    public class ServerSocketBIONoAccept {
        public static void main(String[] args) throws Exception {
            ServerSocket serverSocket = new ServerSocket();
            serverSocket.bind(new InetSocketAddress("0.0.0.0", 8080), 1);
    
            while (true) {
                Thread.sleep(1000L);
            }
        }
    }
    
    import java.net.InetSocketAddress;
    import java.nio.channels.ServerSocketChannel;
    
    public class ServerSocketNIONoAccept {
        public static void main(String[] args) throws Exception {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            ServerSocket serverSocket = serverSocketChannel.socket();
            serverSocket.bind(new InetSocketAddress("0.0.0.0", 8080), 1);
    
            while (true) {
                System.out.println("wait accept");
                Socket socket = serverSocket.accept();
                System.out.println("after accept");
            }
        }
    }
    

    分别执行以上代码,会使用ServerSocket监听8080端口,但不会进行accept处理。使用telnet命令或其他客户端连接对应的端口,能够建立连接,但服务器不会有返回,客户端会一直阻塞等待服务器返回。与Tomcat的Acceptor线程终止后的现象一样。

    5.4. Tomcat最大连接数已满场景模拟

    maxConnections属性默认值足够大,Tomcat最大连接数通常情况下并不会被占满。将Tomcat Connector的acceptCount、maxThreads属性值配置得足够大,将maxConnections设置为1,模拟Tomcat最大连接数已满的场景。

    <Connector port="8081" protocol="org.apache.coyote.http11.Http11NioProtocol" acceptCount="100" maxConnections="1" maxThreads="100"/>
    

    在这种情况下,Tomcat的现象与Tomcat处理请求线程池已满,或Acceptor线程终止时的现象相同,即客户端可以建立连接,但服务器没有返回,客户端会一直阻塞等待服务器返回。

    6. acceptCount(connect队列长度)

    acceptCount属性用于指定当所有的处理请求的线程都在被使用时,处理接入连接请求的最大队列长度。默认值为100。

    当该队列已满时,任意接收到的请求会被拒绝。

    6.1. connect队列处理代码分析

    AbstractProtocol类的get/setAcceptCount()方法中,调用了AbstractEndpoint类型endpoint对象的get/setAcceptCount()方法,对成员变量acceptCount进行了操作。

    AbstractEndpoint子类中对于成员变量acceptCount的使用如下:

    • NioEndpoint

    在NioEndpoint类的bind()方法中,调用了“this.serverSock.socket().bind(addr, this.getAcceptCount())”方法,即java.net.ServerSocket类的bind(SocketAddress endpoint, int backlog)方法。

    • Nio2Endpoint

    在Nio2Endpoint类的bind()方法中,调用了“this.serverSock.bind(addr, this.getAcceptCount())”方法,即java.nio.channels.AsynchronousServerSocketChannel类的bind(SocketAddress local, int backlog)方法。

    • AprEndpoint

    在AprEndpoint类的bind()方法中,调用了“Socket.listen(this.serverSock, this.getAcceptCount())”方法,即org.apache.tomcat.jni.Socket类的native方法listen(long sock, int backlog)。可参考 http://tomcat.apache.org/tomcat-8.5-doc/api/org/apache/tomcat/jni/Socket.html#listen(long,%20int) 。

    以上方法均说明backlog参数用于指定Sockect执行bind操作时,接入连接的最大队列长度。

    java.net.ServerSocket及java.nio.channels.AsynchronousServerSocketChannel类的bind()方法说明backlog参数的使用取决于具体的实现,有的实现可能会实现该最大长度的限制,有的实现可能会忽略该参数。

    java.net.ServerSocket类的bind()方法中,调用了“getImpl().listen(backlog)”方法,即java.net.SocketImpl类的listen(int backlog)方法,backlog参数用于指定接入请求的最大队列长度。当队列满后,若有连接请求达到时,连接会被拒绝。

    java.nio.channels.AsynchronousServerSocketChannel及org.apache.tomcat.jni.Socket类对于backlog参数的使用的说明未找到。

    6.2. ServerSocket的backlog已满场景分析

    6.2.1. 不能及时对套接字进行accept处理

    当ServerSocket不能及时对套接字进行accept处理时,以backlog参数值为长度的连接队列可能会被占满。

    如以上ServerSocketBIONoAccept、ServerSocketNIONoAccept类,在调用ServerSocket类的bind()方法时,backlog参数为1。且由于没有对套接字进行accept处理,仅能接受一个连接,之后连接队列会被占满。

    • 在Linux环境监听

    在Linux环境启动以上类后,可以使用“ curl -v http://127.0.0.1:8080 ”或telnet命令访问对应的端口;

    前backlog + 1个连接能够正常建立,之后的请求均无法建立连接。

    • 在Windows环境监听

    在Windows环境启动以上类后,可以使用telnet命令访问对应的端口。

    前backlog个连接能够正常建立,之后的请求均无法建立连接。

    6.2.2. 能够及时对套接字进行accept处理

    当ServerSocket能够及时对套接字进行accept处理时,以backlog参数值为长度的连接队列不会被占满。

    如修改以上ServerSocketBIONoAccept、ServerSocketNIONoAccept类,在执行ServerSocket类的bind()方法后,执行accept()方法,当能够及时对套接字进行accept处理时,连接队列不会被占满,可以接受多个连接。

    6.3. Tomcat连接队列已满场景模拟

    maxConnections属性默认值足够大,能够快速地对连接进行accept操作,连接队列通常情况下并不会被占满。将Tomcat Connector的acceptCount、maxThreads属性值设置为1,将maxConnections配置得足够大,模拟Tomcat连接队列已满的场景。

    <Connector port="8081" protocol="org.apache.coyote.http11.Http11NioProtocol" acceptCount="1" maxConnections="1" maxThreads="100"/>
    
    • Linux环境

    在Linux环境启动Tomcat,在多个客户端同时使用curl命令或其他方式分别访问上述sleep_seconds.jsp,使当前请求等待较长的时间才处理完毕,例如访问的URL为http://127.0.0.1:8081/test/sleep_seconds.jsp?sleep_seconds=100。

    前三个发送到Tomcat服务器的请求会被Tomcat处理,并等待服务器返回。从第四个请求开始连接被拒绝。

    • Windows环境

    前两个发送到Tomcat服务器的请求会被Tomcat处理,并等待服务器返回。从第三个请求开始连接被拒绝。

    展开全文
  • Tomcat服务器响应特别(服务器假死)的解决办法 最近在做项目,突然发现服务器响应太了,点几页就在转圈圈,查了博客才发现是数据库连接池的连接没关,中途增加了个方法,需要获取数据库连接,最后忘记关了,...
  • 作为程序员,应该有一套排查问题的思路,下面以界面响应为出发点进行整理(后端开发程序员一枚,前端不过多描述)。 设计到的工具:jstack、jmap、jstat(这三个是jre自带的)、Windows资源监视器、Windows性能...
  • tomcat加载静态资源进行优化

    千次阅读 2018-05-01 16:31:51
    调整tomcat config/server.xml &lt;Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" executor="...
  • Tomcat面试题+http面试题+Nginx面试题+常见面试题

    千次阅读 多人点赞 2019-12-12 15:04:43
    Tomcat面试题 1、Tomcat的缺省端口是多少?怎么修改?...2、Tomcat有哪几种connector运行模式(服务的请求方式)? 答:三种。修改它的运行模式需要在主配置文件中找到connector字段中的protocol进行修改...
  • 然而由于某些原因,服务器把该第三方地址给拉进黑名单了,导致频繁请求超时,线程耗尽呈一直等待状态,导致后续请求阻塞。 解决方案: 本应是由网管解决网络不通畅的问题。但是由于网管重启技术有限,使用技术手段...
  • 服务器上的tomcat偶尔响应变

    万次阅读 2016-10-10 14:48:41
    例如线程达到150左右时服务端会抛出socket资源用尽的错误,你很难再往上加,响应的速度也变的异常的缓慢,你可以在Tomcat的服务器配置文件中优化一下配置,比如在 server.xml中修改,增加节点数目,可以有效的提高...
  • Java基础知识面试题(2020最新版)

    万次阅读 多人点赞 2020-02-19 12:11:27
    Java面试总结(2021优化...https://thinkwon.blog.csdn.net/article/details/104588679 16 Tomcat面试题(2020最新版) https://thinkwon.blog.csdn.net/article/details/104397665 17 ZooKeeper面试题(2020最新版) ...
  • Tomcat 动态资源服务器部署及应用

    千次阅读 2017-07-06 10:13:53
    Tomcat 动态资源服务器部署及应用 Java 2 EE 计数体系包含如 Serverlet , JSP , JMX 等等。 以OpenJDK为例,当前比较常用的有1.6.0、1.7.0、1.8.0等版本,当一台主机上有多个OpenJDK时,可使用 “alternatives”...
  • Tomcat 启动速度,一直转圈的原因

    千次阅读 2017-10-13 09:26:27
    问题现象在新安装的centos7 系统上Tomcat启动很。开始我以为是程序写的问题,所以把webapps下所有程序都删除掉。(只保留Tomcat自带)灵异的事情发生了,Tomcat停止在——彻底找到 Tomcat 启动速度的元凶我查看...
  • 504超时:这种应该是tomcat接收了请求,放到了请求对列,但是因为线程等资源被前面的资源一直占用,导致一直在排队所以超时。 502 Bad Gateway---05月28日 14:18:05 the proxy server received an invalid ...
  • (静态资源处理)nginx 比tomcat强在哪

    千次阅读 2019-06-26 10:27:57
    nginx有多牛逼 序言 安装 反向代理 静态资源服务器 nginx vs tomcat压测对比 并发结果对比 对服务器影响对比 说在后面的话 序言 对于常用的服务器,大家可能更多的知道apache,tomcat,lls等服务器。我们跟多的...
  • 今日把项目放入阿里云服务器运行...2.打卡了网页F12 查看network 里每个环节耗时,发现js 、css 、jpg 等静态资源耗时竟然达到了1秒以上,心里MLGB这是啥问题啊,然后开始找度娘,有人说优化tomcat 一种是:GZ 也就...
  • 之前在搞性能优化,发现有些通过Spring boot feign的RPC接口比较,达到100-200ms,按理RPC调用都是IP直连,不应该超过100ms的,然后使用阿里开源的arthas工具测试接口执行时间,结果发现同一个接口大概每10秒会...
  • 问题现像:新开一个浏览器,打开网站(本机部署),第一次请求的时候响应很, 但是第二次响应就很快,但是停止操作几分钟后,再请求又变。或者第一次请求响应后,关闭浏览器再重新打开,请求响应也会很! (注...
  • 最近,测试部门的同事找到我,说他们测试时,没一会就发现服务接口请求一直无响应,Tomcat跟死掉了一样,也没有返回任何的错误响应,说让我赶紧排查下;听完后,我瞬间激灵了下,妹的,最近老是出问题,领导都要给我...
  • tomcat处理请求,及servlet工作原理的理解
  • SpringBoot静态资源访问太

    千次阅读 2020-12-20 21:11:22
    1. 在filter 中记录请求时间 ,得到某些静态资源居然600ms,但是主要问题不在这里,是客户端的连接被阻塞了。如上图 2. 然后然后禁用filter(直接spring boot static) 返回 3. 结果还是很 排查过程 二 1. 开启...
  • Tomcat12——tomcat性能

    2020-01-29 22:40:07
    1. tomcat性能测试 对于系统性能,用户最直观的感受就是系统的加载时间和操作时间,即用户执行某项操作的耗时。从更专业的角度上讲,性能可以从两个指标量化: 1)响应时间:为执行某个操作的耗时,大多数情况下...
  • 1、收到一个请求就处理,这个时候就不能处理新的请求,这种为阻塞 这个是单线程模型,无法并发,一个请求没处理完服务器就会阻塞,不会处理下一个请求。一般的服务器不会使用这种方式实现。 2、收到一个请求就新开一...
  • 资源文件可以正常加载,然后我将war包放入tomcat的webapp目录下运行tomcat后,输入localhost:8080/microCourse来访问页面但是此时...
  • Tomcat IO阻塞异常

    2018-05-03 10:44:00
    tomcat的maxThreads、acceptCount(最大线程数、最大排队数) tomcat 的Connector配置如下 <Connectorport="8080"protocol=...
  • 配置JMX Exporter2.1 下载安装JMX Exporter文件2.2 收集Tomcat数据2.3 集成Prometheus3.Tomcat关注指标4.集成Grafana 1.安装部署 1.1 安装Prometheus 部署Prometheus请点击此链接:...
  • JavaWeb笔记

    千次阅读 多人点赞 2019-09-06 10:42:23
    JSP最终会被编译成为Servlet JSP:编写--》翻译-》编译-->执行 JSP最终会变成一个class文件 为什么JSP第一次打开会比较? 因为第一次的打开JSP要经过翻译,编译,执行过程需要消耗时间,而第二次打开不需要再...
  • Tomcat 启动速度优化

    千次阅读 2017-04-27 20:36:19
    本文简单介绍如何让 Tomcat 更快启动, 同时提供一些建议。 我们碰到过JVM被卡了200多秒的情况, 所以才翻译了这篇文章, 【MAVEN的某些插件也可能依赖 `SecureRandom`】。 在新买的Linux服务器上部署了多个 Tomcat ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 26,084
精华内容 10,433
关键字:

tomcat资源请求慢