精华内容
下载资源
问答
  • Zabbix在线监控tomcat线程数,因为线上没有配置jmx,所以使用jstack pid的方式获取thread线程。脚本结合zabbix的自动发现,可以实现多个tomcat实例的自动发现配置。免去以后tomcat增加后一个个手动添加的烦恼。 ...

    Zabbix在线监控tomcat的线程数,因为线上没有配置jmx,所以使用jstack pid的方式获取thread线程。脚本结合zabbix的自动发现,可以实现多个tomcat实例的自动发现配置。免去以后tomcat增加后一个个手动添加的烦恼。

    zabbix agent的配置和路径目录结构

    主目录:/etc/zabbix

    自定义脚本目录:/etc/zabbix/custom,里面有如下几个路径:

    conf                         zabbix的配置文件目录
    externalscripts        外部命令脚本
    public                      zabbix公共文件,例如保存的ip和密码
    scripts                     zabbix自定义的脚本
    template                 zabbix模板文件

    自动发现脚本

    这个脚本能够打印出当前服务器上所有的tomcat实例名称,pid进程号和home路径。zabbix会定期执行这个脚本,做到自动发现当前所有的tomcat实例。具体脚本如下:

    # coding: utf-8
    
    import sys
    import re
    import json
    from optparse import OptionParser
    
    from qiueer.python.cmds import cmds
    
    def get_tomcat_list():
        cmdstr = "ps -ef|grep java|grep -v grep|grep \"Dcatalina.home\"|awk '{print $2 ,$(NF-3)}'|sed 's/-Dcatalina.home=//g'"
        c2 = cmds(cmdstr, timeout=3)
        stdo = c2.stdo()
        stde = c2.stde()
        # retcode = c2.code()
        
        (stdo_list, stde_list) = (re.split("\n", stdo), re.split("\n", stde))
        
        data = list()
        for tomcat in stdo_list:
            if not tomcat:continue
            data.append({
                         "{#TOMCAT_PID}":tomcat.split()[0],
                         "{#TOMCAT_PATH}": tomcat.split()[1],
                         "{#TOMCAT_NAME}":tomcat.split()[1].split('/')[-1],
                         })
        return json.dumps({'data': data}, sort_keys=True, indent=7, separators=(",",":"))
    
    def main():
        try:
            usage = "usage: %prog [options]\ngGet Tomcat Stat"
            parser = OptionParser(usage)
            
            parser.add_option("-l", "--list",  
                              action="store_true", dest="is_list", default=False,  help="if list all tomcat")
            
            (options, args) = parser.parse_args()
            if 1 >= len(sys.argv):
                parser.print_help()
                return
    
            if options.is_list == True:
                print get_tomcat_list()
                return
    
        except Exception as e:
            import traceback
            tb = traceback.format_exc()
            print tb
    
    if __name__ == "__main__":
        main()

    监控脚本

    监控脚本是实际执行jstack的地方,用法如下:

    ./tomcat_thread_status.sh pid username

    pid: tomcat进程号

    username:  运行tomcat的用户名

    脚本:

    #!/bin/bash
    
    #### 添加sudo权限 ####
    #zabbix ALL=(root) NOPASSWD:/etc/zabbix/custom/scripts/tomcat_thread_status.sh
    #Defaults:zabbix   !requiretty
    ####
    
    export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
    
    pid=$1
    user=$2
    
    STATS=(NEW:0 RUNNABLE:0 BLOCKED:0 WAITING:0 TIMED_WAITING:0 TERMINATED:0 TOTAL:0)
    
    if [ $pid ];then
      STATUS=`su - $user -c "jstack $pid|grep -i \"java.lang.Thread.State:\""|awk '{print $2}'|sort|uniq -c|awk '{print $2":"$1}'`
    fi
    
    if [ ! -z "$STATUS" ];then
      total=0
      for s in $STATUS;do
        key=`echo $s|cut -d: -f1`
        val=`echo $s|cut -d: -f2`
    
        i=0
        for t in ${STATS[@]};do
          if [ `echo $t|grep -c $key` -eq 1 ];then
            idx=$i
            break
          fi
          let i=$i+1
    
        done
    
        STATS[$i]=${key}":"${val}
    
        let total=$total+${val}
      done
      STATS[6]="TOTAL:"${total}
    fi
    
    echo ${STATS[@]} | sed -e s/' '/',"'/g -e s/':'/'":'/g -e s/^/'{"thread_status":{"'/g -e s/'$'/'}}'/g

    脚本执行后会返回json格式的字符串,包括new、runnable、blocked等线程状态的数据。

    zabbix agent配置

    UserParameter=custom.tomcat_thread.discovery,python /etc/zabbix/custom/scripts/tomcat_thread_discovery.py --list 2>/dev/null
    UserParameter=custom.tomcat_thread_status.item[*],sudo /etc/zabbix/custom/scripts/tomcat_thread_status.sh "$1" "$2"

    配置单独放在/etc/zabbix/custom/conf里,记得需要在主配置文件/etc/zabbix/zabbix_agentd.conf里include该路径,否则配置不会生效。

    都准备好后重启zabbix agent。

    导入模板配置

    模板配置可以参考这个,下载后导入即可。

    下载地址:https://raw.githubusercontent.com/zhangnq/zabbix/master/template/tomcat_thread_status_zbx_v3_template.xml

    配置主机

    最后在主机的template中添加导入的模板,过会就会发现tomcat已自动发现并添加相关线程的监控。

    写在最后

    具体脚本也可在github上下载:

    自动发现:https://github.com/zhangnq/zabbix/blob/master/scripts/tomcat_thread_discovery.py

    线程监控:https://github.com/zhangnq/zabbix/blob/master/scripts/tomcat_thread_status.sh

    模板:https://github.com/zhangnq/zabbix/blob/master/template/tomcat_thread_status_zbx_v3_template.xml

    配置:https://github.com/zhangnq/zabbix/blob/master/conf/tomcat_thread_status.conf

    项目地址:https://github.com/zhangnq/zabbix

    独立地址:https://zhangnq.com/2994.html

    展开全文
  • Zabbix在线监控tomcat线程数,因为线上没有配置jmx,所以使用jstack pid的方式获取thread线程。脚本结合zabbix的自动发现,可以实现多个tomcat实例的自动发现配置。免去以后tomcat增加后一个个手动添加的烦恼。...

    Zabbix在线监控tomcat的线程数,因为线上没有配置jmx,所以使用jstack pid的方式获取thread线程。脚本结合zabbix的自动发现,可以实现多个tomcat实例的自动发现配置。免去以后tomcat增加后一个个手动添加的烦恼。

    zabbix agent的配置和路径目录结构

    主目录:/etc/zabbix

    自定义脚本目录:/etc/zabbix/custom,里面有如下几个路径:

    conf                         zabbix的配置文件目录

    externalscripts        外部命令脚本

    public                      zabbix公共文件,例如保存的ip和密码

    scripts                     zabbix自定义的脚本

    template                 zabbix模板文件

    自动发现脚本

    这个脚本能够打印出当前服务器上所有的tomcat实例名称,pid进程号和home路径。zabbix会定期执行这个脚本,做到自动发现当前所有的tomcat实例。具体脚本如下:

    # coding: utf-8

    import sys

    import re

    import json

    from optparse import OptionParser

    from qiueer.python.cmds import cmds

    def get_tomcat_list():

    cmdstr = "ps -ef|grep java|grep -v grep|grep \"Dcatalina.home\"|awk '{print $2 ,$(NF-3)}'|sed 's/-Dcatalina.home=//g'"

    c2 = cmds(cmdstr, timeout=3)

    stdo = c2.stdo()

    stde = c2.stde()

    # retcode = c2.code()

    (stdo_list, stde_list) = (re.split("\n", stdo), re.split("\n", stde))

    data = list()

    for tomcat in stdo_list:

    if not tomcat:continue

    data.append({

    "{#TOMCAT_PID}":tomcat.split()[0],

    "{#TOMCAT_PATH}": tomcat.split()[1],

    "{#TOMCAT_NAME}":tomcat.split()[1].split('/')[-1],

    })

    return json.dumps({'data': data}, sort_keys=True, indent=7, separators=(",",":"))

    def main():

    try:

    usage = "usage: %prog [options]\ngGet Tomcat Stat"

    parser = OptionParser(usage)

    parser.add_option("-l", "--list",

    action="store_true", dest="is_list", default=False, help="if list all tomcat")

    (options, args) = parser.parse_args()

    if 1 >= len(sys.argv):

    parser.print_help()

    return

    if options.is_list == True:

    print get_tomcat_list()

    return

    except Exception as e:

    import traceback

    tb = traceback.format_exc()

    print tb

    if __name__ == "__main__":

    main()

    监控脚本

    监控脚本是实际执行jstack的地方,用法如下:

    ./tomcat_thread_status.sh pid username

    pid: tomcat进程号

    username:  运行tomcat的用户名

    脚本:

    #!/bin/bash

    #### 添加sudo权限 ####

    #zabbix ALL=(root) NOPASSWD:/etc/zabbix/custom/scripts/tomcat_thread_status.sh

    #Defaults:zabbix !requiretty

    ####

    export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

    tomcat_path=$1

    user=$2

    STATS=(NEW:0 RUNNABLE:0 BLOCKED:0 WAITING:0 TIMED_WAITING:0 TERMINATED:0 TOTAL:0)

    pid=`ps -ef|grep "java .*$tomcat_path"|grep -v grep|awk '{print $2}'`

    if [ $pid ];then

    STATUS=`su - $user -c "jstack $pid|grep -i \"java.lang.Thread.State:\""|awk '{print $2}'|sort|uniq -c|awk '{print $2":"$1}'`

    fi

    if [ ! -z "$STATUS" ];then

    total=0

    for s in $STATUS;do

    key=`echo $s|cut -d: -f1`

    val=`echo $s|cut -d: -f2`

    i=0

    for t in ${STATS[@]};do

    if [ `echo $t|grep -c $key` -eq 1 ];then

    idx=$i

    break

    fi

    let i=$i+1

    done

    STATS[$i]=${key}":"${val}

    let total=$total+${val}

    done

    STATS[6]="TOTAL:"${total}

    fi

    echo ${STATS[@]} | sed -e s/' '/',"'/g -e s/':'/'":'/g -e s/^/'{"thread_status":{"'/g -e s/'$'/'}}'/g

    脚本执行后会返回json格式的字符串,包括new、runnable、blocked等线程状态的数据。

    zabbix agent配置

    UserParameter=custom.tomcat_thread.discovery,python /etc/zabbix/custom/scripts/tomcat_thread_discovery.py --list 2>/dev/null

    UserParameter=custom.tomcat_thread_status.item[*],sudo /etc/zabbix/custom/scripts/tomcat_thread_status.sh "$1" "$2"

    配置单独放在/etc/zabbix/custom/conf里,记得需要在主配置文件/etc/zabbix/zabbix_agentd.conf里include该路径,否则配置不会生效。

    都准备好后重启zabbix agent。

    导入模板配置

    模板配置可以参考这个,下载后导入即可。

    配置主机

    最后在主机的template中添加导入的模板,过会就会发现tomcat已自动发现并添加相关线程的监控。

    写在最后

    具体脚本也可在github上下载:

    自动发现:https://github.com/zhangnq/zabbix/blob/master/scripts/tomcat_thread_discovery.py

    线程监控:https://github.com/zhangnq/zabbix/blob/master/scripts/tomcat_thread_status.sh

    模板:https://github.com/zhangnq/zabbix/blob/master/template/tomcat_thread_status_zbx_v3_template.xml

    配置:https://github.com/zhangnq/zabbix/blob/master/conf/tomcat_thread_status.conf

    项目地址:https://github.com/zhangnq/zabbix

    展开全文
  • Tomcat 内存和线程配置

    2017-01-10 14:29:50
    当在对其进行并发测试时,基本上30个USER上去就当机了,还要修改默认连接数设置:以下红色四行TOMCAT6中好相没有,手工加上就可以了,基本上可以解决连接数过大引起的死机。...maxThreads="600" ///最大线程数


    转载地址:http://blog.csdn.net/linlzk/article/details/7761195


    当在对其进行并发测试时,基本上30个USER上去就当机了,还要修改默认连接数设置:以下红色四行TOMCAT6中好相没有,手工加上就可以了,基本上可以解决连接数过大引起的死机。具体数值可跟据实际情况设置

     <Connector port="80" protocol="HTTP/1.1" maxThreads="600" minSpareThreads="100" maxSpareThreads="500" acceptCount="700" connectionTimeout="20000" redirectPort="8443" />

    maxThreads="600" ///最大线程数

    minSpareThreads="100"///初始化时创建的线程数

    maxSpareThreads="500"///一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程。

    acceptCount="700"//指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理 Tomcat6使用安装版本进行安装后,使用内存的调整无法利用修改启动文件的方式进行,但按缺省方式启动后如果启动的应用较多的话Tomcat经常会因为内存不足而失去响应,这个时候必须人工调整内存参数: 1.“开始”--“Apache Tomcat 6”--“Configure Tomcat”

    2.选择Java标签,在“Initial memory pool(初始内存)”和“Maximum memory pool(最大内存)”中输入你需要的内存参数即可 与内存相关的tomcat错误处理: 1.java.lang.OutOfMemoryError:这个错误是因为tomcat JVM的Permanent Generation space(内存的永久保存区域)不足引起的,这个区域是JVM用于用于存放Class和Meta的信息的内存区域,GC(Garbage Collection)不会在主程序运行期对 PermGen space进行清理,所以如果你的应用中有很多CLASS的话,就很可能出现PermGen space错误, 这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了,症状是tomcat运行一段时间后失去反应,服务中tomcat服务正常,重启 tomcat服务后网站又正常响应了。解决方案是人工调整确认大小设置,使用regedit修改注册表 HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Procrun 2.0\Tomcat6\Parameters\Java中的 Options参数,在后面增加一下数据: -XX:PermSize=64M
    -XX:MaxPermSize=128m

    2.java.lang.OutOfMemoryError: Java heap space Heap size 设置 JVM堆的设置是指java程序运行过程中JVM可以调配使用的内存空间的设置.JVM在启动的时候会自动设置Heap size的值,其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置。Heap size 的大小是Young Generation 和Tenured Generaion 之和。

    提示:在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候将抛出此异常信息。

    提示:Heap Size 最大不要超过可用物理内存的80%,一般的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值。使用前面所说的方法进行调整即可

     

    =================== Tomcat内存、连接数等性能参数设置 默认参数不适合生产环境使用,因此需要修改一些参数

    1、修改启动时内存参数、并指定JVM时区(在windows server 2008 下时间少了8个小时): 在Tomcat上运行j2ee项目代码时,经常会出现内存溢出的情况,解决办法是在系统参数中增加系统参数: window下, 在catalina.bat最前面: set JAVA_OPTS=-XX:PermSize=64M -XX:MaxPermSize=128m -Xms512m -Xmx1024m 一定加在catalina.bat最前面。 linux下,在catalina.sh最前面增加: JAVA_OPTS="-XX:PermSize=64M -XX:MaxPermSize=128m -Xms512m -Xmx1024m -Duser.timezone=Asia/Shanghai" 注意:前后二者区别,有无set,有无双引号。
    2、线程池配置(Tomcat6下) 使用线程池,用较少的线程处理较多的访问,可以提高tomcat处理请求的能力。使用方式: 首先。打开/conf/server.xml,增加 <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="500" minSpareThreads="20" maxIdleTime="60000" /> 最大线程500(一般服务器足以),最小空闲线程数20,线程最大空闲时间60秒。 然后,修改<Connector ...>节点,增加executor属性,如:
    <Connector executor="tomcatThreadPool" port="80" protocol="HTTP/1.1" connectionTimeout="60000" keepAliveTimeout="15000" maxKeepAliveRequests="1" redirectPort="443" ....../>
    注意:可以多个connector公用1个线程池。
    3、调整连接相关Connector的参数:
    <Connector executor="tomcatThreadPool" port="80" protocol="HTTP/1.1" connectionTimeout="60000" keepAliveTimeout="15000" maxKeepAliveRequests="1" redirectPort="443" maxHttpHeaderSize="8192" URIEncoding="UTF-8" enableLookups="false" acceptCount="100" disableUploadTimeout="true"/> 参数说明: * connectionTimeout - 网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒。 * keepAliveTimeout - 长连接最大保持时间(毫秒)。此处为15秒。 * maxKeepAliveRequests - 最大长连接个数(1表示禁用,-1表示不限制个数,默认100个。一般设置在100~200之间) the maximum number of HTTP requests that can be held in the pipeline until the connection is closed by the server. Setting this attribute to 1 disables HTTP/1.0 keep-alive, as well as HTTP/1.1 keep-alive and pipelining. Setting this to -1 allows an unlimited number of pipelined or keep-alive HTTP requests. If not specified, this attribute is set to 100. * maxHttpHeaderSize - http请求头信息的最大程度,超过此长度的部分不予处理。一般8K。 * URIEncoding - 指定Tomcat容器的URL编码格式。 * acceptCount - 指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理,默认为10个。defines the maximum queue length for incoming connection requests when all possible request processing threads are in use. Any requests received when the queue is full are refused. The default value is 10. * disableUploadTimeout - 上传时是否使用超时机制 * enableLookups - 是否反查域名,取值为:true或false。为了提高处理能力,应设置为false * bufferSize - defines the size (in bytes) of the buffer to be provided for input streams created by this connector. By default, buffers of 2048 bytes are provided.
    * maxSpareThreads - 做多空闲连接数,一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程 the maximum number of unused request processing threads that are allowed to exist until the thread pool starts stopping the unnecessary threads. The default value is 50. * maxThreads - 最多同时处理的连接数,Tomcat使用线程来处理接收的每个请求。这个值表示Tomcat可创建的最大的线程数。。 the maximum number of request processing threads to be created by this Connector, which therefore determines the maximum number of simultaneous requests that can be handled. If not specified, this attribute is set to 200. * minSpareThreads - 最小空闲线程数,Tomcat初始化时创建的线程数 the number of request processing threads that are created when this Connector is first started. The connector will also make sure it has the specified number of idle processing threads available. This attribute should be set to a value smaller than that set for maxThreads. The default value is 4. * minProcessors - 最小空闲连接线程数,用于提高系统处理性能,默认值为10。(用于Tomcat4中) * maxProcessors - 最大连接线程数,即:并发处理的最大请求数,默认值为75。(用于Tomcat4中) 备注: Tomcat4中可以通过修改minProcessors和maxProcessors的值来控制线程数。 在Tomcat5+主要对以下参数调整 maxThreads Tomcat使用线程来处理接收的每个请求。这个值表示Tomcat可创建的最大的线程数。 acceptCount 指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理。 connnectionTimeout 网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒。 minSpareThreads Tomcat初始化时创建的线程数。 maxSpareThreads 一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程。
    4、负载均衡、集群的配置 Tomcat6支持分布式部署,可以实现集群功能,提高响应能力。

    5、利用JMX监控Tomcat运行情况,需要手工调整启动参数,如下: 打开cataline.bat,增加一行 set JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote.port=10090
    -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file="%CATALINA_BASE%\conf\logging.properties" linux下修改cataline.sh: JAVA_OPTS="-Dcom.sun.management.jmxremote.port=10090 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file=%CATALINA_BASE\conf\logging.properties" 注意JDK\jre\lib\management\management.properties文件必须存在。 重新启动tomcat节点,然后用jconsole连接(此处端口wei10090)

     6、Tomcat增加一个应用 在server.xml的Host标签中增加行 <Context displayName="OA" docBase="/app/web-apps/GACWP" path="" /> path代表上下文名称,空表示是根路径。 ================================= Tomcat6.x目录与server.xml详解 tomcat 服务器是一个免费的开放源代码的Web 应用服务器,目前最新版本是6.x,相对5.x性能提升很多,主要优化了内存使用,增强IO能力,重新构造集群功能。 近期对Tomcat6.x作深入学习,参考上述声明的Tomcat全攻略,由于笔者是2001年针对Tomcat4.x所写,故参考之并针对 Tomcat6.x做了总结,形成此篇学习笔记,希望对学习的人有所帮助,本文涵盖了:Tomcat目录、Server.xml元素讲解,数据库连接池配置、线程池配置、虚拟目录配置。关于如何下载、安装、运行Tomcat略,请google,相信有详细的文章讲述。 tomcat的目录结构如下: 目录名 bin 存放启动和关闭tomcat脚本
    conf 包含不同的配置文件,server.xml(Tomcat的主要配置文件)和web.xml work 存放jsp编译后产生的class文件 webapp 存放应用程序示例,以后你要部署的应用程序也要放到此目录 logs 存放日志文件 lib 这三个目录主要存放tomcat所需的jar文件
    server.xml配置简介
    元素名
    属性 解释 server port 指定一个端口,这个端口负责监听关闭tomcat的请求 shutdown
    指定向端口发送的命令字符串 GlobalNamingResources
    服务器的全局JNDI资源,可以有子标签<Resource></Resource> Executor(线程池,一个或多个Connector可以共享此线程池) name 线程池名称,名称必须唯一 namePrefix
    线程的名字前缀,用来标记线程名字的,这样每个线程就用这个前缀加上线程编号了,比如 catalina-exec-1 、catalina-exec-2 maxThreads
    允许的最大线程池里的线程数量,默认是200,大的并发应该设置的高一些,反正只是限制而已,不占用资源 minSpareThreads
    最小的保持活跃的线程数量,默认是25.这个要根据负载情况自行调整了。太小了就影响反应速度,太大了白白占用资源 maxIdleTime
    最小的保持活跃的线程数量,默认是25.这个要根据负载情况自行调整了。太小了就影响反应速度,太大了白白占用资源 threadPriority
    线程的等级。默认是Thread.NORM_PRIORITY service name 指定service的名字 Connector (表示客户端和service之间的连接) port
    指定服务器端要创建的端口号,并在这个断口监听来自客户端的请求 minProcessors 服务器启动时创建的处理请求的线程数 maxProcessors
    最大可以创建的处理请求的线程数 enableLookups
    如果为true,则可以通过调用request.getRemoteHost()进行DNS查询来得到远程客户端的实际主机名,若为false则不进行DNS查询,而是返回其ip地址 redirectPort
    指定服务器正在处理http请求时收到了一个SSL传输请求后重定向的端口号 acceptCount
    指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理 connectionTimeout
    指定超时的时间数(以毫秒为单位) Engine (表示指定service中的请求处理机,接收和处理来自Connector的请求) name defaultHost
    指定缺省的处理请求的主机名,它至少与其中的一个host元素的name属性值是一样的 jvmRoute host (表示一个虚拟主机、并且可以包含Context子节点配置虚拟目录)
    name
    指定主机名 appBase
    应用程序基本目录,即存放应用程序的目录 unpackWARs
    如果为true,则tomcat会自动将WAR文件解压,否则不解压,直接从WAR文件中运行应用程序 autoDeploy
    自动部署 xmlValidation
    是否验证xml xmlNamespaceAware Realm (表示存放用户名,密码及role的数据库) className
    指定Realm使用的类名,此类必须实现org.apache.catalina.Realm接口 Context(host子节点配置虚拟目录)
    Path
    虚拟目录名称 docBase
    物理路径 Debug Debug模式 Reload True 重新加载,修改后自动加载 上面我们讲述了server .xml个元素的含义,下面我们给出详细示例 Tomcat数据库连接池配置如下: server.xml配置Resource Xml代码

    1. <Resource name="jdbc/ExampleDB" auth="Container" type="javax.sql.DataSource"

    2. maxActive="100" maxIdle="30" maxWait="10000"

    3. username="APP" password="APP"
    driverClassName="org.apache.derby.jdbc.ClientDriver"

    4. url="jdbc:derby://localhost:1527/springside-example;create=true"/>

    context.xml文件增加: Xml代码

     <WatchedResource>WEB-INF/web.xml</WatchedResource>

     <ResourceLink name="jdbc/ExampleDB" global="jdbc/ExampleDB" type="javax.sql.DataSource"/>

     4. Tomcat共享线程池配置: 取消Executor注释,修改连接数至自己合适的数值既可。

    Xml代码

    1. <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"

    2. maxThreads="200" minSpareThreads="100" maxIdleTime="60000"/> executor="tomcatThreadPool" 标明此连接使用上面配置的名称为tomcatThreadPool的连接池,无属性共享连接不会生效

     protocol表示使用的是 http协议 端口号为8080 Java代码

    1. <Connector port="8080" protocol="HTTP/1.1" redirectPort="8443"

    2. connectionTimeout="20000"

    3. executor="tomcatThreadPool"

    4. acceptCount="100"

    5. useBodyEncodingForURI="true"

    6. enableLookups="false"

    7. /> 虚拟目录配置: 在<host></host>之间增加如下 <!-- 配置虚拟目录,例如:http://localhost:8080 --> Xml代码

    1. <Context path="/" docBase="D:\workspace\code\HBJH\web"></Context> 附件中是取自springside3中,Tomcat production config配置示例,即生产环境下Tomcat配置

    展开全文
  • 一直以来很迷惑TOMCAT的连接,网上也是众说纷纭,所以今天自己专门来测试一下,配置参数请参考: TOMCAT配置参数说明 ,本人比较懒,所以只测试了BIO和NIO,没有ARP模式(主要是看说的...

    一直以来很迷惑TOMCAT的连接数,网上也是众说纷纭,所以今天自己专门来测试一下,配置参数请参考: TOMCAT配置参数说明 ,本人比较懒,所以只测试了BIO和NIO,没有APR模式(主要是看说的那么多,不想配置),下面正式开始:

    1、测试环境

        TOMCAT:TOMCAT8

        JAVA:JDK1.8.0_121

        ServerSocket的启动方式:继承至HttpServlet随容器启动

    2、服务端统一测试代码

        ServerSocket

    package test.server;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    
    public class StartSocketServlet extends HttpServlet {
    
    	ControlScoketServer ass = null;
    
    	@Override
    	public void init() throws ServletException {
    		// TODO Auto-generated method stub
    		super.init();
    
    		// MiniBasic.isDebug=true;
    
    		ass = new ControlScoketServer();
    		ass.setDaemon(true);
    		ass.start();
    
    		System.out.println("服务已经开启");
    
    	}
    
    	@Override
    	public void destroy() {
    		// TODO Auto-generated method stub
    		super.destroy();
    		try {
    			ass.stopScoketServer();
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		try {
    			ass.interrupt();
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    
    }
    

    package test.server;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    import zhw.basic.CheckUtils;
    import zhw.server.basic.ssh.MiniBasic;
    
    public class ControlScoketServer extends Thread {
    
    	public boolean isStop = false;
    	protected ServerSocket serverSocket;
    	// private ExecutorService cachedThreadPool ;
    	private String ip;
    	private int port;
    	public final static ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    	
    	public static void startThread(Runnable run){
    		cachedThreadPool.execute(run);
    	}
    
    	public ControlScoketServer() {
    		this.ip = "127.0.0.1";
    		this.port = 10083;
    	}
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		try {
    			startServer();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    
    	public void stopScoketServer() {
    		isStop = true;
    		try {
    			serverSocket.close();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    
    	}
    
    	public void startServer() throws IOException {
    		isStop = false;
    		serverSocket = new ServerSocket();
    		try {
    			serverSocket.setSoTimeout(0);
    		} catch (Exception e1) {
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    		}
    		if (!CheckUtils.String_IsNullOrEmpty(ip)) {
    			serverSocket.bind(new InetSocketAddress(ip, port));
    		} else {
    			serverSocket.bind(new InetSocketAddress(port));
    		}
    		MiniBasic.getLogger().info("Socket服务器开启,IP:" + ip + ",端口:" + port);
    		int i = 0;
    		while (!isStop) {
    			try {
    				Socket client = serverSocket.accept();
    				i++;
    				ClientSocketHandler csh = new ClientSocketHandler(client, i);
    				startThread(csh);
    			} catch (Exception e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	}
    
    }
    
    package test.server;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    
    import zhw.server.basic.ssh.MiniBasic;
    
    public class ClientSocketHandler implements Runnable {
    
    	private int threadId = 0;
    	Socket client;
    	private InputStream is;
    	private OutputStream os;
    
    	public ClientSocketHandler(Socket client, int threadId) {
    		this.threadId = threadId;
    		this.client = client;
    	}
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		try {
    			is = this.client.getInputStream();
    		} catch (IOException e1) {
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    		}
    		try {
    			os = this.client.getOutputStream();
    		} catch (IOException e1) {
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    		}
    		byte[] bt = new byte[512];
    		while (true) {
    			MiniBasic.showInfo("线程:  " + threadId + "  开始执行,等待客户端输入..");
    			try {
    				while (is.read(bt) != 0) {
    					MiniBasic.showInfo("**************线程:  " + threadId + " 客户端输入为:" + new String(bt));
    				}
    			} catch (IOException e1) {
    				// TODO Auto-generated catch block
    				e1.printStackTrace();
    				break;
    			}
    			try {
    				Thread.sleep(5 * 1000);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    
    	}
    
    }
    

    HttpServer

    package test.server;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class HttpServerServlet extends HttpServlet {
    
    	@Override
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		
    		
    		System.out.println("有客户端连接,参数:"+req.getParameter("TESTPARAM"));
    		
    		try {
    			//保持连接
    			Thread.sleep(30*1000);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    		resp.getWriter().print("SERVER RESPONSE:"+req.getParameter("TESTPARAM"));
    		resp.getWriter().close();
    	}
    
    	
    	
    	
    }
    

    WebsocketServer

    package test.server;
    
    import java.io.IOException;
    import java.util.concurrent.CopyOnWriteArrayList;
    
    import javax.websocket.EndpointConfig;
    import javax.websocket.OnClose;
    import javax.websocket.OnError;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    
    import zhw.server.basic.ssh.MiniBasic;
    import zhw.server.basic.ssh.websocket.ZhwWebSocketServer;
    
    @ServerEndpoint(value = "/testwebsocket")
    public class WebSocketServer {
    
    	public static CopyOnWriteArrayList<WebSocketServer> wbSockets = new CopyOnWriteArrayList<WebSocketServer>();
    
    	private Session session;
    
    	@OnOpen
    	public void start(Session session, EndpointConfig config) {
    		this.session = session;
    		System.out.println("新的客户端:" + this.session.getId());
    		wbSockets.add(this);
    	}
    
    	@OnClose
    	public void end() {
    		MiniBasic.getLogger().error("websocket关闭:" + this.session.getId());
    		socketClosed();
    	}
    
    	private void socketClosed() {
    		if (wbSockets != null && wbSockets.contains(this)) {
    			wbSockets.remove(this);
    		}
    	}
    
    	@OnMessage
    	public void incoming(String message) {
    		// Never trust the client
    		MiniBasic.showInfo("websocket 收到信息: " + message);
    	}
    
    	@OnError
    	public void onError(Throwable t) throws Throwable {
    
    		MiniBasic.getLogger().error("websocket出错:" + this.session.getId() + "--" + t.getMessage());
    
    	}
    
    	public void sendData(String data) {
    		try {
    			MiniBasic.showInfo("------------发送socket数据。。。。。。。。。。。" + data);
    			this.session.getBasicRemote().sendText(data);
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    
    }
    
    web.xml
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
    	license agreements. See the NOTICE file distributed with this work for additional 
    	information regarding copyright ownership. The ASF licenses this file to 
    	You under the Apache License, Version 2.0 (the "License"); you may not use 
    	this file except in compliance with the License. You may obtain a copy of 
    	the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
    	by applicable law or agreed to in writing, software distributed under the 
    	License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
    	OF ANY KIND, either express or implied. See the License for the specific 
    	language governing permissions and limitations under the License. -->
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    	metadata-complete="true" version="3.1">
    	
    	<context-param>
    		<param-name>log4jConfigLocation</param-name>
    		<param-value>/WEB-INF/classes/log4j.properties</param-value>
    	</context-param>
    	
    	
    	<servlet>
    		<servlet-name>testserver</servlet-name>
    		<servlet-class>test.server.HttpServerServlet</servlet-class>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    	
    	<servlet>
    		<servlet-name>socketserver</servlet-name>
    		<servlet-class>test.server.StartSocketServlet</servlet-class>
    		<load-on-startup>2</load-on-startup>
    	</servlet>
    	
    	<servlet-mapping>
    		<servlet-name>testserver</servlet-name>
    		<url-pattern>*.test</url-pattern>
    	</servlet-mapping>
    	
    	<session-config>
    		<session-timeout>0</session-timeout>
    	</session-config>
    	<welcome-file-list>
    		<welcome-file>index.jsp</welcome-file>
    	</welcome-file-list>
    </web-app>
    3、客户端代码,根据测试不同需要更改

    HttpClient

    package test.client;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    import zhw.basic.http.HttpHelper;
    
    public class HttpClient {
    	
    	public final static ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    	
    	public static void main(String[] args) throws Exception {
    		HttpHelper helper = new HttpHelper();
    		for (int i = 0; i < 260; i++) { //根据测试不同更改数量
    			ExcuteHttpRequest ehr = new ExcuteHttpRequest(i + 1, helper);
    			cachedThreadPool.execute(ehr);
    			Thread.sleep(10);
    		}
    		Thread.sleep(3 * 1000);
    
    	}
    }
    class ExcuteHttpRequest implements Runnable {
    
    	private int clid;
    	private HttpHelper helper;
    
    	public ExcuteHttpRequest(int clid, HttpHelper helper) {
    		this.clid = clid;
    		this.helper = helper;
    	}
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		System.out.println(this.clid + "开始连接..");
    		try {
    			String responseText = this.helper.sendRequest("http://127.0.0.1/test/testhttp.test",
    					"TESTPARAM=HTTPCLIENT-" + this.clid, "UTF-8");
    			System.out.println(this.clid + "接受到的数据:" + responseText);
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			System.out.println(this.clid +"连接出错:"+e.getMessage());
    		}
    
    	}
    
    }

    SocketClient

    package test.client;
    
    import java.io.IOException;
    import java.net.Socket;
    import java.util.ArrayList;
    import java.util.List;
    
    public class SocketClient {
    	public static void main(String[] args) throws Exception {
    		// TODO Auto-generated method stub
    
    		List<Socket> ls = new ArrayList<Socket>();
    
    		for (int i = 0; i < 5000; i++) { //
    			Socket s = new Socket("127.0.0.1", 10083);
    			// s.setKeepAlive(true);
    			s.setOOBInline(false);
    			s.setSoTimeout(0);
    			ls.add(s);
    			Thread.sleep(10);
    			System.out.println("已连接:" + i);
    		}
    
    		Thread.sleep(3 * 1000);
    		int i = 0;
    		while (true) {
    			for (Socket ws : ls) {
    				i++;
    				try {
    					ws.getOutputStream().write(("SOCKET CLIENT:" + i).getBytes());
    				} catch (IOException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    				Thread.sleep(10);
    			}
    			i = 0;
    			Thread.sleep(20 * 1000);
    		}
    	}
    }
    

    WebSocketClient

    package test.client;
    
    import java.io.IOException;
    import java.net.URI;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.websocket.ClientEndpoint;
    import javax.websocket.ContainerProvider;
    import javax.websocket.Session;
    import javax.websocket.WebSocketContainer;
    
    @ClientEndpoint
    public class WebSocketClient {
    
    	private String deviceId;
    
    	private Session session;
    
    	public WebSocketClient() {
    	}
    
    	public WebSocketClient(String deviceId) {
    		this.deviceId = deviceId;
    	}
    
    	protected boolean start() {
    		WebSocketContainer container = ContainerProvider.getWebSocketContainer();
    		String uri = "ws://127.0.0.1/test/testwebsocket";
    		System.out.println("Connecting to " + uri);
    		try {
    			session = container.connectToServer(WebSocketClient.class, URI.create(uri));
    			System.out.println("count: " + deviceId);
    		} catch (Exception e) {
    			e.printStackTrace();
    			return false;
    		}
    		return true;
    	}
    
    	public static void main(String[] args) throws InterruptedException {
    		List<WebSocketClient> ar = new ArrayList<WebSocketClient>();
    		for (int i = 1; i < 260; i++) {// 根据测试不同更改数量
    			WebSocketClient wSocketTest = new WebSocketClient(String.valueOf(i));
    			if (!wSocketTest.start()) {
    				System.out.println("测试结束!");
    				break;
    			} else {
    				ar.add(wSocketTest);
    				Thread.sleep(10);
    			}
    		}
    		Thread.sleep(3 * 1000);
    		while (true) {
    			for (WebSocketClient ws : ar) {
    				try {
    					ws.session.getBasicRemote().sendText("CLIENT:" + ws.deviceId);
    				} catch (IOException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    				Thread.sleep(10);
    			}
    			Thread.sleep(20 * 1000);
    		}
    	}
    
    }
    

    ComblineTest

    package test.client;
    
    import java.net.Socket;
    
    import zhw.basic.http.HttpHelper;
    
    public class ComblineTest {
    
    	public static void main(String[] args) {
    
    		HttpHelper helper = new HttpHelper();
    
    		for (int i = 0; i < 100; i++) {
    			ExcuteHttpRequest ehr = new ExcuteHttpRequest(i + 1, helper);
    			HttpClient.cachedThreadPool.execute(ehr);
    			try {
    				Thread.sleep(10);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    
    		for (int i = 100; i < 250; i++) {// 根据测试不同更改数量
    			WebSocketClient wSocketTest = new WebSocketClient(String.valueOf(i));
    			if (!wSocketTest.start()) {
    				System.out.println("测试结束!");
    				break;
    			} else {
    				try {
    					Thread.sleep(10);
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		}
    
    		for (int i = 250; i < 400; i++) {
    			ExcuteHttpRequest ehr = new ExcuteHttpRequest(i + 1, helper);
    			HttpClient.cachedThreadPool.execute(ehr);
    			try {
    				Thread.sleep(10);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    
    		for (int i = 400; i < 1400; i++) { //
    			try {
    				Socket s = new Socket("127.0.0.1", 10083);
    				// s.setKeepAlive(true);
    				s.setOOBInline(false);
    				s.setSoTimeout(0);
    				Thread.sleep(10);
    				System.out.println("已连接:" + i);
    			} catch (Exception e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    
    	}
    
    }
    

    BIO模式测试

        catalina.bat 启动项配置:

    set JAVA_OPTS=-server -Xms128m -Xmx512m -Xss1m -XX:PermSize=128m -XX:MaxNewSize=256m -XX:MaxPermSize=256m

        server.xml配置:

     <Executor name="tomcatThreadPool" 
            namePrefix="tomcatThreadPool-" 
            maxThreads="200" 
    	maxSpareThreads="300"
            minSpareThreads="100"/>
    <Connector executor="tomcatThreadPool" 
    	port="80" 
    	protocol="org.apache.coyote.http11.Http11Protocol"
        	maxHttpHeaderSize="8192"
    	acceptCount="50"
            connectionTimeout="20000"
            keepAliveTimeout="36000000" 
    	maxKeepAliveRequests="-1"
            redirectPort="443" />

    HttpClient

    创建260个连接 连接数测试结果:

    260开始连接..
    251连接出错:请求失败:Connection refused: connect
    252连接出错:请求失败:Connection refused: connect
    253连接出错:请求失败:Connection refused: connect
    254连接出错:请求失败:Connection refused: connect
    255连接出错:请求失败:Connection refused: connect
    256连接出错:请求失败:Connection refused: connect
    257连接出错:请求失败:Connection refused: connect
    258连接出错:请求失败:Connection refused: connect
    259连接出错:请求失败:Connection refused: connect
    260连接出错:请求失败:Connection refused: connect

    可以看出第251个开始就不能连接了,符合 200个最大线程+50个 队列 数

    197接受到的数据:SERVER RESPONSE:HTTPCLIENT-197
    198接受到的数据:SERVER RESPONSE:HTTPCLIENT-198
    199接受到的数据:SERVER RESPONSE:HTTPCLIENT-199
    200接受到的数据:SERVER RESPONSE:HTTPCLIENT-200
    202接受到的数据:SERVER RESPONSE:HTTPCLIENT-202
    201接受到的数据:SERVER RESPONSE:HTTPCLIENT-201
    ....
    248接受到的数据:SERVER RESPONSE:HTTPCLIENT-248
    249接受到的数据:SERVER RESPONSE:HTTPCLIENT-249
    250接受到的数据:SERVER RESPONSE:HTTPCLIENT-250
    

    250个结果都正确返回

    SocketClient

    创建1000个连接 连接数测试结果:

    已连接:996
    已连接:997
    已连接:998
    已连接:999
    服务端接受结果

    ServerSocket 不受tomcat配置的连接池限制

    WebSocket

    创建260个连接,连接数测试结果:

    count: 200
    Connecting to ws://127.0.0.1/test/testwebsocket
    测试结束!
    javax.websocket.DeploymentException: The HTTP request to initiate the WebSocket connection failed

    200就已经不能创建了,受到200个最大线程数限制

    WebSocket+HttpClient+SocketServer 联合测试

    • 创建100个http连接,0-99(显示+1了)
    • 98开始连接..
      99开始连接..
      100开始连接..
      Connecting to ws://127.0.0.1/test/testwebsocket
      count: 100
      Connecting to ws://127.0.0.1/test/testwebsocket
      count: 101
      全部连接成功

    • 然后创建150个websocket连接,100-249
    • count: 199
      Connecting to ws://127.0.0.1/test/testwebsocket
      测试结束!
      javax.websocket.DeploymentException: The HTTP request to initiate the WebSocket connection failed
      第200个时连接失败,因为已经到了200MaxThread

    • 创建200个http连接,250-399(显示+1了)
    • 397开始连接..
      398开始连接..
      399开始连接..
      400开始连接..
      301连接出错:请求失败:Connection refused: connect
      300连接出错:请求失败:Connection refused: connect
      第300个失败,acceptCount 起作用

    • 创建1000个socket连接     400-1399
    • 已连接:1398
      已连接:1399
      8接受到的数据:SERVER RESPONSE:HTTPCLIENT-8

            全部连接成功

    BIO模式测试完成



    NIO模式测试

    把server中的connector修改为如下,其他不变:

    <Connector executor="tomcatThreadPool" 
    	port="80" 
    	protocol="org.apache.coyote.http11.Http11NioProtocol"
        	maxHttpHeaderSize="8192"
    	acceptCount="50"
            connectionTimeout="20000"
            keepAliveTimeout="36000000" 
    	maxKeepAliveRequests="-1"
            redirectPort="443" />

    HttpClient

    创建500个连接 连接数测试结果:

    499开始连接..
    500开始连接..
    13接受到的数据:SERVER RESPONSE:HTTPCLIENT-13
    17接受到的数据:SERVER RESPONSE:HTTPCLIENT-17
    客户端不会报错,服务每次只处理200个,这个跟maxthread设置有关系,处理完成后再依次处理后续请求,acceptcount无效。为了确认是不是因为请求数少了而没有报错,我使用了创建5000个连接但是在1200多的时候,eclise 显示 oom,不过我估计确实NIO不会受accpet限制 1228开始连接..
    1229开始连接..
    1230开始连接..
    Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

    SocketClient

    创建3000个连接 连接数测试结果:

    已连接:2997
    已连接:2998
    已连接:2999

    同时连接且能同时正常通信


    Websocket

    创建500个连接,均连接成功并都能正常通信


    WebSocket+HttpClient+SocketServer 联合测试

    这个测试的有些多,主要修改下联合测试的代码,测试结果:

    SokcetServer连接不受限制

    单独HTTP和单独websocket连接不受acceptcount限制,可以无限等待队列

    先HTTP连接超过maxthreads后websocket将不能连接,直接报错,也就是说一般情况下http和websocket混合连接时,超过连接数限制websocket会报错,http会等待

    先websocket连接超过maxthreads后HTTP能连接,但是进入等待队列,如果HTTP没有处理完成,WEBSOCKET会进入等待状态,可能是用例中http是线程等待,而websocket是IO等待的原因(才疏学浅,弄不明白)


    总结一下:

    两种模式下ScoektServer虽然是从tomcat中启动,但是不受tomcat连接数限制

    HTTP和WEBSOCKET 单独不混合连接时 BIO 模式下都要受Maxthreads 限制,NIO模式下连接不受限制,但是要进入等待,要受等待时间限制

    HTTP和WEBSOCKET混合连接时 BIO 模式下都要受Maxthreads 限制,NIO模式下超过Maxthread, WEBSOCKET 要报错,HTTP还是可以连接但是受等待时间限制

    以上如果要配置TOMCAT 并发量 需要考虑 JVM的内存大小 和 Maxthreads 的数量

    其他说明:

    上面Connector没有配置 maxConnections 所以测试几千的连接的时候都可以,可以确认的是Tomcat默认的maxConnections 不会是200,具体是多少,我也不知道,如果需要更高的并发量可以显视配置 maxConnections ,如其名 它会影响 HTTP和 WEBSOCKET 的连接上限,超过上限直接报错,不能连接。所以高并发时最好是 maxConnections 和 Maxthredas 一样,或maxConnections 比Maxthredas 大。







    展开全文
  • tomcat 线程数相关问题

    2015-12-14 10:27:16
    基于tomcat为容器做web service,...此前在TMD项目中没有在代码里配置线程池的大小,而是使用tomcat自身线程管控。 地址:conf/server.xml    connectionTimeout="20000"  maxThreads="3000"  minSpareThre
  • tomcat 的Connector配置如下 其中最后两个参数意义如下:  maxThreads:tomcat起动的最大线程数,即同时处理的任务个数,默认值为200 ...情况1:接受一个请求,此时tomcat起动的线程数没有到达maxThr
  • tomcat 6的Connector配置如下 其中最后两个参数意义如下: maxThreads:tomcat起动的最大线程数,即同时处理的任务个数,默认值为200 ...情况1:接受一个请求,此时tomcat起动的线程数没有...
  • 当在对其进行并发测试时,基本上30个USER上去就当机了,还要修改默认连接设置:以下红色四行TOMCAT6中好相没有,手工加上就可以了,基本上可以解决连接过大引起的死机。具体数值可跟据实际情况设置    maxT
  • 我的网站使用的是apache+tomcat的传统配置方式,每当晚上10点左右的时候,apache的并发连接有300左右,而每个网页包含的最少文件为4个,这样算下来的话,tomcat的工作线程最多有80-100,但是观察其当前busy的...
  • 使用tomcat中间件时,需要依据实际情况进行配置,以下是我在开发和生产环境下使用的配置参考以及相关说明...Tomcat可创建的最大线程数。150~250。 (2)minSpareThreads="25" 表示即使没有人使用也开这么...
  • tomcat配置server.xml

    2016-08-19 23:46:35
    tomcat 6的Connector配置如下    其中最后两个参数意义如下:  maxThreads:tomcat起动的最大线程数,即同时处理的任务个数,默认值为200  ...情况1:接受一个请求,此时tomcat起动的线程数没有到达ma
  • nginx加2台tomcat。session 没有共享。有时间把ssl配置也做以下。 以下是nginx的conf配置文件 ...#nginx 启动进程数或线程数 worker_processes 1; error_log logs/error.log crit; #error_log logs...
  • 2. 方便项目启动,不需要下载Tomcat或者Jetty针对目前的容器优化,目前来说没有太多地方,需要考虑如下几个点线程数超时时间jvm优化针对上述的优化点来说,首先线程数是一个重点,初始线程数和最大线程数,初始线程...
  • 服务器配置:linux+tomcat...原因:tomcat默认最大连接数(线程数)200个,默认每一个连接的生命周期2小时(7200秒),tomcat使用http 1.1协议,而http1.1默认是长连接。tomcat接受处理完请求后,socket没有主动关闭,因此...
  • Tomcat并发优化和设置

    千次阅读 2016-07-06 15:12:46
     请注意:很抱歉,在tomcat6在默认的配置选项中是没有把NIO功能打开。所以很多正在使用Tomcat6的朋友们本以为能快活的使用上NIO。 而NIO则是使用单线程(单个CPU)或者只使用少量的多线程(多CPU)来接受Socket,而由...
  • weblogic9线程数调整

    2015-06-17 08:48:58
    我们的应用在tomcat上一直运行正常,移植到weblogic9上,同样的应用会因为获取不到数据库连接的错误而崩溃,经同事研究发现原因是weblogic9默认配置提供的可用连接太少(4)所致,可是weblogic9控制台又没有提供...
  • 之前有个项目上的同事突然问我,我们XX服务最大的并发量是多少,因为我们使用的是springboot来运行的服务,配置文件中也没有配置其他的参数,应该就是使用默认的tomcat线程配置了;因此整理了一下: server: ...
  • 并发量较高的时候(150+),apache的进程,会迅速的给占满,导致服务无法访问 此时查看cpu,各个服务器的利用率均...于是就怀疑是不是apache的mod_jk里面有参数没有配置好造成的。 于是查看mod_jk 的日志,发现有类
  • minSpareThreads:最小备用线程数tomcat启动时的初始化的线程数(即使没有人使用也开这么多空线程等待);   maxSpareThreads:最大备用线程数,一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程; ...
  • weblogic9修改线程数

    2009-12-31 14:01:37
    我们的应用在tomcat上一直运行正常,移植到weblogic9上,同样的应用会因为获取不到数据库连接的错误而崩溃,经同事研究发现原因是weblogic9默认配置提供的可用连接太少(4)所致,可是weblogic9控制台又没有提供...
  • Tomcat详解

    2019-06-25 11:48:31
    一、前言 ...这里不介绍Tomcat的一些线程数配置了,网上一大堆,核心介绍网上没有的。 另外,每个公司的业务场景不一样,Tomcat的部署方案可能有所不能,所以请大家轻喷! 二、Tomcat组件 我们先回...
  •  请注意:很抱歉,在tomcat6在默认的配置选项中是没有把NIO功能打开。所以很多正在使用Tomcat6的朋友们本以为能快活的使用上NIO。 而NIO则是使用单线程(单个CPU)或者只使用少量的多线程(多CPU)来接受Socket,而由...
  • 生产环境下到底该如何部署Tomcat

    千次阅读 2019-06-02 13:32:20
    作者:享学课堂老顾 微信公众号: 享学课堂online ...这里不介绍Tomcat的一些线程数配置了,网上一大堆,核心介绍网上没有的。 另外,每个公司的业务场景不一样,Tomcat的部署方案可能有所不能,...
  • Tomcat 假死

    2017-11-23 15:58:55
    服务器配置:linux+tomcat现象:...原因:tomcat默认最大连接数(线程数)200个,默认每一个连接的生命周期2小时(7200秒),tomcat使用http 1.1协议,而http1.1默认是长连接。tomcat接受处理完请求后,socket没有主动关闭,因

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 139
精华内容 55
关键字:

tomcat没有配置线程数