• Tomcat配置和优化(转)


    ---恢复内容开始---


    本文链接:https://blog.csdn.net/Ezra1991/article/details/88605169

    Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。

    Tomcat的拓扑方案:

    方案一: Tomcat
    方案二: Nginx+Tomcat
    方案三:
    Nginx
    |
    +----------------------------------------------+
    | | | |
    Tomcat1 Tomcat2 Tomcat3 nginx

    一、Tomcat Http Server


    1. 部署JAVA环境
    # tar xf jdk-8u91-linux-x64.tar.gz -C /usr/local
    # ln -s /usr/local/jdk1.8.0_91 /usr/local/java

    # vim /etc/profile.d/jdk.sh
    JAVA_HOME=/usr/local/java
    PATH=$JAVA_HOME/bin:$PATH
    export JAVA_HOME PATH

    # source /etc/profile.d/jdk.sh
    # env |grep JAVA
    JAVA_HOME=/usr/local/java
    # java -version
    java version "1.8.0_91"
    Java(TM) SE Runtime Environment (build 1.8.0_91-b14)
    Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)

    2. 安装Tomcat:
    # tar xf apache-tomcat-7.0.34.tar.gz -C /usr/local/
    # ln -s /usr/local/apache-tomcat-7.0.34 /usr/local/tomcat

    定义Tomcat所需环境变量:
    # vim /etc/profile.d/jdk.sh //定义Tomcat环境变量
    CATALINA_HOME=/usr/local/tomcat //Tomcat安装目录
    PATH=$CATALINA_HOME/bin:$PATH
    export CATALINA_HOME PATH
    # source /etc/profile.d/jdk.sh

    启动Tomcat
    # /usr/local/tomcat/bin/startup.sh //启动tomcat
    Using CATALINA_BASE: /usr/local/tomcat
    Using CATALINA_HOME: /usr/local/tomcat
    Using CATALINA_TMPDIR: /usr/local/tomcat/temp
    Using JRE_HOME: /usr/java/jdk1.7.0_11
    Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
    Tomcat started.

    # netstat -tnlp |grep java
    tcp 0 0 ::ffff:127.0.0.1:8005 :::* LISTEN 6191/java
    tcp 0 0 :::8009 :::* LISTEN 6191/java
    tcp 0 0 :::8080 :::* LISTEN 6191/java

    # /usr/local/tomcat/bin/shutdown.sh //关闭tomcat

    关于tomcat端口:
    Tomcat服务器通过Connector连接器组件与客户程序建立连接,Connector组件负责接收客户的请求,以及把Tomcat服务器的响应结果发送给客户。默认情况下,Tomcat在server.xml中配置了两种连接器:
      第一个连接器监听8080端口,负责建立HTTP连接。在通过浏览器访问Tomcat服务器的Web应用时,使用的就是这个连接器。  
      第二个连接器监听8009端口,负责和其他的HTTP服务器建立连接。在把Tomcat与其他HTTP服务器集成时,就需要用到这个连接器。

    8005是tomcat本身的端口

    3. 测试
    http://192.168.1.6:8080/


     

    二. Tomcat多实例子部署

    多实例运行不同的应用(类似虚拟主机)
    多实例运行相同的应用(实现负载均衡,支持高并发处理)

    (1) 配置多实例目录

    分别在/usr/local/tomcat下创建目录instance1 instance2 instance3,拷贝原来的conf,logs,temp,work到3个目录下

    (2) 配置实例server.xml

    <Server port="****" 管理实例端口
    <Connector port="****" protocol="HTTP/1.1 提供web服务端口
    <Connector port="****" protocol="AJP/1.3" 用于前端如Apache通过AJP方式连接tomcat的端口

    [root@www ~]# vim /usr/local/tomcat/instance1/conf/server.xml

    第一个修改点:22 <Server port="8015" shutdown="SHUTDOWN"> 修改为8015,8025,8035.......

    第二个修改点:71 <Connector port="8081" protocol="HTTP/1.1" 修改为8081,8082,8083...........
    connectionTimeout="20000"
    redirectPort="8443" />

    第三个修改点:93 <Connector port="8019" protocol="AJP/1.3" redirectPort="8443" /> 修改为8019,8029,8039........

    第四个修改点:125 <Host name="localhost" appBase="/webapps1" //修改网站基准目录
    unpackWARs="true" autoDeploy="true">

    (3). 脚本内容(多实例启动脚本)
    [root@www ~]# vim /usr/local/tomcat/instance1/ins1.sh

    #!/bin/bash
    #instance1
    . /etc/init.d/functions
    export CATALINA_BASE="/usr/local/tomcat/instance1"

    case "$1" in
    start)
    $CATALINA_HOME/bin/startup.sh
    ;;
    stop)
    $CATALINA_HOME/bin/shutdown.sh
    ;;
    restart)
    $CATALINA_HOME/bin/shutdown.sh
    sleep 3
    $CATALINA_HOME/bin/startup.sh
    ;;
    esac

    (4). 启动测试
    [root@www ~]# /usr/local/tomcat/instance1/ins1.sh start
    [root@www ~]# /usr/local/tomcat/instance2/ins2.sh start
    [root@www ~]# /usr/local/tomcat/instance3/ins3.sh start

    [root@tomcat instance3]# ss -tnlp |grep :80 |column -t
    LISTEN  0  1    ::ffff:127.0.0.1:8015  :::*  users:(("java",pid=2940,fd=46))
    LISTEN  0  100  :::8080                :::*  users:(("java",pid=2733,fd=42))
    LISTEN  0  100  :::8081                :::*  users:(("java",pid=2940,fd=42))
    LISTEN  0  100  :::8082                :::*  users:(("java",pid=2905,fd=42))
    LISTEN  0  100  :::8083                :::*  users:(("java",pid=2999,fd=42))
    LISTEN  0  100  :::8019                :::*  users:(("java",pid=2940,fd=43))
    LISTEN  0  1    ::ffff:127.0.0.1:8025  :::*  users:(("java",pid=2905,fd=46))
    LISTEN  0  100  :::8029                :::*  users:(("java",pid=2905,fd=43))
    LISTEN  0  1    ::ffff:127.0.0.1:8035  :::*  users:(("java",pid=2999,fd=48))
    LISTEN  0  1    ::ffff:127.0.0.1:8005  :::*  users:(("java",pid=2733,fd=46))
    LISTEN  0  100  :::8039                :::*  users:(("java",pid=2999,fd=43))
    LISTEN  0  100  :::8009                :::*  users:(("java",pid=2733,fd=43))
     

    三. Tomcat负载均衡:

    采用Nginx作为反向代理服务器实现Tomcat负载均衡:

    配置Nginx:

    1. 停止原有web服务器:
    2. 添加普通用户账号来运行nginx:
    # useradd -M -s /sbin/nologin nginx
    3. 安装依赖,解压并安装Nginx:
    #yum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel gcc gcc-c++ make cmake
    # tar xf nginx-1.10.3.tar.gz
    # cd nginx-1.10.3
    # ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module
    # make && make install

    4. 启动:

    [root@tomcat sbin]# vim /etc/profile
    export NGINX_HOME=/usr/local/nginx
    export PATH=$NGINX_HOME/sbin:$PATH
    [root@tomcat sbin]# source /etc/profile
    [root@tomcat sbin]# nginx

    5. 测试:

    [root@tomcat sbin]# netstat -tanp | grep 80
    tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 5614/nginx: master

    #curl 127.0.0.1

    6. 配置负载均衡:

    [root@www ~]# vim /usr/local/nginx/conf/nginx.conf
    http {
    upstream tomcat_pool {                                         //轮询方式
    server 192.168.1.6:8081;
    server 192.168.1.6:8082;
    server 192.168.1.6:8083;
    }

    server {
    location / {
    proxy_pass http://tomcat_pool;
    proxy_redirect off; 开启代理重定向
    proxy_set_header Host $host; 开启使用远程主机
    proxy_set_header X-Real-IP $remote_addr; 获取远程主机IP
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 使用代理主机转发地址
    }
    }
    }

    在三个tomcat发布目录/webapp1/ROOT/中写入对应IP,curl本地回环后出现轮询的负载均衡效果:

    [root@tomcat ROOT]# curl 127.0.0.1
    192.168.1.6:8081
    [root@tomcat ROOT]# curl 127.0.0.1
    192.168.1.6:8082
    [root@tomcat ROOT]# curl 127.0.0.1
    192.168.1.6:8083
     

    四. 优化:

    tomcat调优主要从以下三方面着手:
    1. 内存优化
    2. 并发优化
    3. 内核优化


    1. JVM内存优化

    再讲解JVM内存优化之前,需要大家知道什么是JAVA堆。

    首先:Java把内存划分成两种:一种是栈内存,一种是堆内存。

    其中Java堆是Java虚拟机所管理的内存中最大的一块。Java堆是指:在JAVA中被所有线程所共享的一块内存区域,在虚拟机启动时创建。
    此内存区域的唯一目的就是存储对象实例,几乎所有的对象实例都在这里分配内存。

    内存溢出的处理办法(tomcat内存优化):
    Tomcat内存优化主要是对 tomcat 启动参数优化.
    Tomcat默认使用最大内存为128M,可以修改 tomcat/bin/Catalina.sh 文件增加其内存。(在此文件第一行开始添加新的设置即可)设置 JAVA_OPTS 参数


    JAVA_OPTS=”-server -Xms1024m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=256m -Djava.awt.headless=true”

    -server  以服务端模式启动,启动速度会稍微慢点,但性能会高很多.;  
    -Xms    java虚拟机初始化时的初始堆大小;  
    -Xmx   java虚拟机可使用的最大堆大小;  
    -XX:PermSize     内存永久保留区域  
    -XX:MaxPermSize   内存最大永久保留区域(老生代对象能占用内存的最大值)  
    java.awt.headless=true 与图形操作有关,适用于Linux系统

    注:要加“m”说明是MB,否则就是KB,在启动tomcat时会报内存不足。
    注:永久保存区:是指内存的永久保存区域。这一部分用于存放Class(类)和Meta(+类)的信息,Class在被 Load(加载)的时候被放入PermGen space区域(内存永久保存区域),并且不会在主程序运行期对内存永久保存区进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile(预编译)的时候。jvm的gc是不会清理PemGen space的,导致内存溢出
    ==================================================================

    常见的内存溢出一般会有下面三种情况:
            1.OutOfMemoryError: Java heap space #堆溢出,若不是程序逻辑bug,可能是项目中引用的jar较多导致
            2.OutOfMemoryError: PermGen space #永久保存区域溢出,通常由于加载了过多的类导致
            3.OutOfMemoryError: unable to create new native thread. #当JVM的heap size(堆空间)设置过大时,thread(线程)的创建数量便会减少
    解决:
    1.调整-Xms -Xmx参数可以解决第一种情况

    64位操作系统对堆内存大小没有限制
    堆的大小可以使用 java -Xmx***M  -version 命令来测试,***位置填写想设置的内存大小。支持的话会出现jdk的版本号,不支持会报错。

        -Xms -Xmx一般配置成一样比较好比如set JAVA_OPTS= -Xms1024m -Xmx1024m
       注意:java -Xmx***M  version 命令来测试的最大堆内存是 -Xmx与 -XX:PermSize的和。
       
    2.加大-XX:PermSize  -XX:MaxPermSize来解决第二种情况  
    3.解决问题3方法如下:
      1).如果程序中有bug,导致创建大量不需要的线程或者线程没有及时回收,那么必须解决这个bug,修改参数是不能解决问题的。
      2).如果程序确实需要大量的线程,现有的设置不能达到要求,那么可以通过修改MaxProcessMemory(内存最大永久保留区),JVMMemory(JVM内存),ThreadStackSize(线程栈大小)这三个因素,来增加能创建的线程数:
    如下方式解决:
      a, MaxProcessMemory 使用64位操作系统
      b, JVMMemory   减少JVMMemory的分配  使用tomcat的catalina.sh这里配置,JAVA_OPTS=-Xms1024m -Xmx1024m -XX:PermSize=256M -XX:MaxNewSize=512m-XX:MaxPermSize=256m
      c, ThreadStackSize  减小单个线程的栈大小 

    这个异常问题本质原因是:
    我们创建了太多的线程,而能创建的线程数是有限制的,导致了异常的发生。
    能创建的线程数的具体计算公式如下: 
    (MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads
    一个进程的最大内存——JVm内存——操作系统预留内存)/线程栈大小=线程数
    在java语言里, 当你创建一个线程的时候,虚拟机会在JVM内存创建一个Thread(线程)对象同时创建一个操作系统线程,而这个系统线程的内存用的不是JVMMemory,而是系统中剩下的内存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。由公式得出结论:你给JVM内存越多,那么你能创建的线程越少,越容易发生java.lang.OutOfMemoryError: unable to create new native thread。

    2. 并发优化
    线程池设置:
    线程池指定Web请求负载的数量,因此,为获得更好的性能这部分应小心处理。可以通过调整连接器属性“maxThreads”完成设置。maxThreads的值应该根据流量的大小,如果值过低,将有没有足够的线程来处理所有的请求,请求将进入等待状态,只有当一个的处理线程释放后才被处理;如果设置的太大,Tomcat的启动将花费更多时间。因此并发优化好坏取决于我们是否给maxThreads设置了一个正确的值。
    #vim server.xml
    <Connector port="8080" protocol="HTTP/1.1"
    maxThreads="500"
    connectionTimeout="20000"
    redirectPort="8443" />

    在上述配置中,maxThreads值设定为“500”,指定可以由服务器处理的并发请求的最大数量是500。如果没有指定,这个属性的默认值为“200”。任何多出的并发请求将收到“拒绝连接”的错误提示,直到另一个处理请求进程被释放。错误看起来如下,
    [ org.apache.tomcat.util.threads.ThreadPool logFull SEVERE: All threads (500) are  currently busy, waiting. Increase maxThreads (500) or check the servlet status  

    最好使用“Tomcat集群”的多个实例。也就是说,如果有“1000”请求,两个Tomcat实例设置“maxThreads= 500”,而不在单Tomcat实例的情况下设置maxThreads=1000。

    -----------------------------
    <Connector port="9027"      
                    protocol="HTTP/1.1"     
                    maxHttpHeaderSize="8192"     
     maxThreads="1000"      客户请求最大线程数
                    minSpareThreads="100"      Tomcat初始化时创建的 socket 线程数
                    maxSpareThreads="1000"   Tomcat连接器的最大空闲 socket 线程数   
                    minProcessors="100"     服务器创建时的最小处理线程数
                    maxProcessors="1000"    服务器同时最大处理线程数
                    enableLookups="false"      若设为true, 则支持域名解析,可把 ip 地址解析为主机名
                    URIEncoding="utf-8"     URL统一编码
                    acceptCount="1000"      监听端口队列最大数,满了之后客户请求会被拒绝(不能小于maxSpareThreads  )
                    redirectPort="8443"      在需要基于安全通道的场合,把客户请求转发到基于SSL 的 redirectPort 端口
                    disableUploadTimeout="true"/> 

    3. 内核优化
    Tomcat运行过程中可能会出现大量ESTABLISHED(已建立的)连接与Time_Wait(等待)连接
    # netstat -n | awk '/^tcp/ {++y[$NF]} END {for(w in y) print w, y[w]}'
    CLOSE_WAIT 348 已关闭的等待链接
    ESTABLISHED 1240 已建立的链接
    TIME_WAIT 5621 等待连接,也是监控web与tomcat之间的链接端口
    #netstat -n | grep 8009 | wc -l
    7198
    1、怎样解决time_wait过多的问题:
    通过调整内核参数:
    # vim /etc/sysctl.conf #编辑文件,加入以下内容:
    net.ipv4.tcp_syncookies = 1
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1
    net.ipv4.tcp_fin_timeout = 30
    # /sbin/sysctl -p #让参数生效。
    配置说明:
    net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
    net.ipv4.tcp_tw_reuse = 1    表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
    net.ipv4.tcp_tw_recycle = 1  表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭;
    net.ipv4.tcp_fin_timeout=30修改系統默认的 TIMEOUT 时间。

    如果以上配置调优后性能还不理想,可继续修改一下配置:
    # vi /etc/sysctl.conf
    net.ipv4.tcp_keepalive_time = 1200
    #表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。keepalive,是在TCP中一个可以检测死连接的机制。
    net.ipv4.ip_local_port_range = 1024 65000
    #表示用于向外连接的端口范围。缺省情况下很小:32768到61000,可以改为1024到65000。
    net.ipv4.tcp_max_syn_backlog = 8192
    #表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
    net.ipv4.tcp_max_tw_buckets = 5000
    #表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。
    默认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于 Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。
    调优完毕,再压一下看看效果:
    # netstat -n | awk '/^tcp/ {++y[$NF]} END {for(w in y) print w, y[w]}'
    ESTABLISHED 968


    2、怎么解决请求结束后依然存在大量ESTABLISHED没有被释放
    初步推断是tomcat服务器回收session时出了问题,这个一般都跟服务器的Timeout设置有联系。
    查看tomcat的配置文件 server.xml
    <Connector port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" URIEncoding="UTF-8"/>
    *****检查配置得出链接的超时时间为20000毫秒的时候acceptCount(承受链接数统计)=”100” ,明显不合理,连接数也太小了。
    所以进一步优化:
    connectionTimeout="20000" 改为 connectionTimeout="100"
    acceptCount="100"改为acceptCount="5000"

     
    ————————————————
    版权声明:本文为CSDN博主「WUYANGEZRA」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/ezra1991/article/details/88605169

    ---恢复内容结束---


    本文链接:https://blog.csdn.net/Ezra1991/article/details/88605169

    Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。

    Tomcat的拓扑方案:

    方案一: Tomcat
    方案二: Nginx+Tomcat
    方案三:
    Nginx
    |
    +----------------------------------------------+
    | | | |
    Tomcat1 Tomcat2 Tomcat3 nginx

    一、Tomcat Http Server


    1. 部署JAVA环境
    # tar xf jdk-8u91-linux-x64.tar.gz -C /usr/local
    # ln -s /usr/local/jdk1.8.0_91 /usr/local/java

    # vim /etc/profile.d/jdk.sh
    JAVA_HOME=/usr/local/java
    PATH=$JAVA_HOME/bin:$PATH
    export JAVA_HOME PATH

    # source /etc/profile.d/jdk.sh
    # env |grep JAVA
    JAVA_HOME=/usr/local/java
    # java -version
    java version "1.8.0_91"
    Java(TM) SE Runtime Environment (build 1.8.0_91-b14)
    Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)

    2. 安装Tomcat:
    # tar xf apache-tomcat-7.0.34.tar.gz -C /usr/local/
    # ln -s /usr/local/apache-tomcat-7.0.34 /usr/local/tomcat

    定义Tomcat所需环境变量:
    # vim /etc/profile.d/jdk.sh //定义Tomcat环境变量
    CATALINA_HOME=/usr/local/tomcat //Tomcat安装目录
    PATH=$CATALINA_HOME/bin:$PATH
    export CATALINA_HOME PATH
    # source /etc/profile.d/jdk.sh

    启动Tomcat
    # /usr/local/tomcat/bin/startup.sh //启动tomcat
    Using CATALINA_BASE: /usr/local/tomcat
    Using CATALINA_HOME: /usr/local/tomcat
    Using CATALINA_TMPDIR: /usr/local/tomcat/temp
    Using JRE_HOME: /usr/java/jdk1.7.0_11
    Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
    Tomcat started.

    # netstat -tnlp |grep java
    tcp 0 0 ::ffff:127.0.0.1:8005 :::* LISTEN 6191/java
    tcp 0 0 :::8009 :::* LISTEN 6191/java
    tcp 0 0 :::8080 :::* LISTEN 6191/java

    # /usr/local/tomcat/bin/shutdown.sh //关闭tomcat

    关于tomcat端口:
    Tomcat服务器通过Connector连接器组件与客户程序建立连接,Connector组件负责接收客户的请求,以及把Tomcat服务器的响应结果发送给客户。默认情况下,Tomcat在server.xml中配置了两种连接器:
      第一个连接器监听8080端口,负责建立HTTP连接。在通过浏览器访问Tomcat服务器的Web应用时,使用的就是这个连接器。  
      第二个连接器监听8009端口,负责和其他的HTTP服务器建立连接。在把Tomcat与其他HTTP服务器集成时,就需要用到这个连接器。

    8005是tomcat本身的端口

    3. 测试
    http://192.168.1.6:8080/


     

    二. Tomcat多实例子部署

    多实例运行不同的应用(类似虚拟主机)
    多实例运行相同的应用(实现负载均衡,支持高并发处理)

    (1) 配置多实例目录

    分别在/usr/local/tomcat下创建目录instance1 instance2 instance3,拷贝原来的conf,logs,temp,work到3个目录下

    (2) 配置实例server.xml

    <Server port="****" 管理实例端口
    <Connector port="****" protocol="HTTP/1.1 提供web服务端口
    <Connector port="****" protocol="AJP/1.3" 用于前端如Apache通过AJP方式连接tomcat的端口

    [root@www ~]# vim /usr/local/tomcat/instance1/conf/server.xml

    第一个修改点:22 <Server port="8015" shutdown="SHUTDOWN"> 修改为8015,8025,8035.......

    第二个修改点:71 <Connector port="8081" protocol="HTTP/1.1" 修改为8081,8082,8083...........
    connectionTimeout="20000"
    redirectPort="8443" />

    第三个修改点:93 <Connector port="8019" protocol="AJP/1.3" redirectPort="8443" /> 修改为8019,8029,8039........

    第四个修改点:125 <Host name="localhost" appBase="/webapps1" //修改网站基准目录
    unpackWARs="true" autoDeploy="true">

    (3). 脚本内容(多实例启动脚本)
    [root@www ~]# vim /usr/local/tomcat/instance1/ins1.sh

    #!/bin/bash
    #instance1
    . /etc/init.d/functions
    export CATALINA_BASE="/usr/local/tomcat/instance1"

    case "$1" in
    start)
    $CATALINA_HOME/bin/startup.sh
    ;;
    stop)
    $CATALINA_HOME/bin/shutdown.sh
    ;;
    restart)
    $CATALINA_HOME/bin/shutdown.sh
    sleep 3
    $CATALINA_HOME/bin/startup.sh
    ;;
    esac

    (4). 启动测试
    [root@www ~]# /usr/local/tomcat/instance1/ins1.sh start
    [root@www ~]# /usr/local/tomcat/instance2/ins2.sh start
    [root@www ~]# /usr/local/tomcat/instance3/ins3.sh start

    [root@tomcat instance3]# ss -tnlp |grep :80 |column -t
    LISTEN  0  1    ::ffff:127.0.0.1:8015  :::*  users:(("java",pid=2940,fd=46))
    LISTEN  0  100  :::8080                :::*  users:(("java",pid=2733,fd=42))
    LISTEN  0  100  :::8081                :::*  users:(("java",pid=2940,fd=42))
    LISTEN  0  100  :::8082                :::*  users:(("java",pid=2905,fd=42))
    LISTEN  0  100  :::8083                :::*  users:(("java",pid=2999,fd=42))
    LISTEN  0  100  :::8019                :::*  users:(("java",pid=2940,fd=43))
    LISTEN  0  1    ::ffff:127.0.0.1:8025  :::*  users:(("java",pid=2905,fd=46))
    LISTEN  0  100  :::8029                :::*  users:(("java",pid=2905,fd=43))
    LISTEN  0  1    ::ffff:127.0.0.1:8035  :::*  users:(("java",pid=2999,fd=48))
    LISTEN  0  1    ::ffff:127.0.0.1:8005  :::*  users:(("java",pid=2733,fd=46))
    LISTEN  0  100  :::8039                :::*  users:(("java",pid=2999,fd=43))
    LISTEN  0  100  :::8009                :::*  users:(("java",pid=2733,fd=43))
     

    三. Tomcat负载均衡:

    采用Nginx作为反向代理服务器实现Tomcat负载均衡:

    配置Nginx:

    1. 停止原有web服务器:
    2. 添加普通用户账号来运行nginx:
    # useradd -M -s /sbin/nologin nginx
    3. 安装依赖,解压并安装Nginx:
    #yum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel gcc gcc-c++ make cmake
    # tar xf nginx-1.10.3.tar.gz
    # cd nginx-1.10.3
    # ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module
    # make && make install

    4. 启动:

    [root@tomcat sbin]# vim /etc/profile
    export NGINX_HOME=/usr/local/nginx
    export PATH=$NGINX_HOME/sbin:$PATH
    [root@tomcat sbin]# source /etc/profile
    [root@tomcat sbin]# nginx

    5. 测试:

    [root@tomcat sbin]# netstat -tanp | grep 80
    tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 5614/nginx: master

    #curl 127.0.0.1

    6. 配置负载均衡:

    [root@www ~]# vim /usr/local/nginx/conf/nginx.conf
    http {
    upstream tomcat_pool {                                         //轮询方式
    server 192.168.1.6:8081;
    server 192.168.1.6:8082;
    server 192.168.1.6:8083;
    }

    server {
    location / {
    proxy_pass http://tomcat_pool;
    proxy_redirect off; 开启代理重定向
    proxy_set_header Host $host; 开启使用远程主机
    proxy_set_header X-Real-IP $remote_addr; 获取远程主机IP
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 使用代理主机转发地址
    }
    }
    }

    在三个tomcat发布目录/webapp1/ROOT/中写入对应IP,curl本地回环后出现轮询的负载均衡效果:

    [root@tomcat ROOT]# curl 127.0.0.1
    192.168.1.6:8081
    [root@tomcat ROOT]# curl 127.0.0.1
    192.168.1.6:8082
    [root@tomcat ROOT]# curl 127.0.0.1
    192.168.1.6:8083
     

    四. 优化:

    tomcat调优主要从以下三方面着手:
    1. 内存优化
    2. 并发优化
    3. 内核优化


    1. JVM内存优化

    再讲解JVM内存优化之前,需要大家知道什么是JAVA堆。

    首先:Java把内存划分成两种:一种是栈内存,一种是堆内存。

    其中Java堆是Java虚拟机所管理的内存中最大的一块。Java堆是指:在JAVA中被所有线程所共享的一块内存区域,在虚拟机启动时创建。
    此内存区域的唯一目的就是存储对象实例,几乎所有的对象实例都在这里分配内存。

    内存溢出的处理办法(tomcat内存优化):
    Tomcat内存优化主要是对 tomcat 启动参数优化.
    Tomcat默认使用最大内存为128M,可以修改 tomcat/bin/Catalina.sh 文件增加其内存。(在此文件第一行开始添加新的设置即可)设置 JAVA_OPTS 参数


    JAVA_OPTS=”-server -Xms1024m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=256m -Djava.awt.headless=true”

    -server  以服务端模式启动,启动速度会稍微慢点,但性能会高很多.;  
    -Xms    java虚拟机初始化时的初始堆大小;  
    -Xmx   java虚拟机可使用的最大堆大小;  
    -XX:PermSize     内存永久保留区域  
    -XX:MaxPermSize   内存最大永久保留区域(老生代对象能占用内存的最大值)  
    java.awt.headless=true 与图形操作有关,适用于Linux系统

    注:要加“m”说明是MB,否则就是KB,在启动tomcat时会报内存不足。
    注:永久保存区:是指内存的永久保存区域。这一部分用于存放Class(类)和Meta(+类)的信息,Class在被 Load(加载)的时候被放入PermGen space区域(内存永久保存区域),并且不会在主程序运行期对内存永久保存区进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile(预编译)的时候。jvm的gc是不会清理PemGen space的,导致内存溢出
    ==================================================================

    常见的内存溢出一般会有下面三种情况:
            1.OutOfMemoryError: Java heap space #堆溢出,若不是程序逻辑bug,可能是项目中引用的jar较多导致
            2.OutOfMemoryError: PermGen space #永久保存区域溢出,通常由于加载了过多的类导致
            3.OutOfMemoryError: unable to create new native thread. #当JVM的heap size(堆空间)设置过大时,thread(线程)的创建数量便会减少
    解决:
    1.调整-Xms -Xmx参数可以解决第一种情况

    64位操作系统对堆内存大小没有限制
    堆的大小可以使用 java -Xmx***M  -version 命令来测试,***位置填写想设置的内存大小。支持的话会出现jdk的版本号,不支持会报错。

        -Xms -Xmx一般配置成一样比较好比如set JAVA_OPTS= -Xms1024m -Xmx1024m
       注意:java -Xmx***M  version 命令来测试的最大堆内存是 -Xmx与 -XX:PermSize的和。
       
    2.加大-XX:PermSize  -XX:MaxPermSize来解决第二种情况  
    3.解决问题3方法如下:
      1).如果程序中有bug,导致创建大量不需要的线程或者线程没有及时回收,那么必须解决这个bug,修改参数是不能解决问题的。
      2).如果程序确实需要大量的线程,现有的设置不能达到要求,那么可以通过修改MaxProcessMemory(内存最大永久保留区),JVMMemory(JVM内存),ThreadStackSize(线程栈大小)这三个因素,来增加能创建的线程数:
    如下方式解决:
      a, MaxProcessMemory 使用64位操作系统
      b, JVMMemory   减少JVMMemory的分配  使用tomcat的catalina.sh这里配置,JAVA_OPTS=-Xms1024m -Xmx1024m -XX:PermSize=256M -XX:MaxNewSize=512m-XX:MaxPermSize=256m
      c, ThreadStackSize  减小单个线程的栈大小 

    这个异常问题本质原因是:
    我们创建了太多的线程,而能创建的线程数是有限制的,导致了异常的发生。
    能创建的线程数的具体计算公式如下: 
    (MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads
    一个进程的最大内存——JVm内存——操作系统预留内存)/线程栈大小=线程数
    在java语言里, 当你创建一个线程的时候,虚拟机会在JVM内存创建一个Thread(线程)对象同时创建一个操作系统线程,而这个系统线程的内存用的不是JVMMemory,而是系统中剩下的内存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。由公式得出结论:你给JVM内存越多,那么你能创建的线程越少,越容易发生java.lang.OutOfMemoryError: unable to create new native thread。

    2. 并发优化
    线程池设置:
    线程池指定Web请求负载的数量,因此,为获得更好的性能这部分应小心处理。可以通过调整连接器属性“maxThreads”完成设置。maxThreads的值应该根据流量的大小,如果值过低,将有没有足够的线程来处理所有的请求,请求将进入等待状态,只有当一个的处理线程释放后才被处理;如果设置的太大,Tomcat的启动将花费更多时间。因此并发优化好坏取决于我们是否给maxThreads设置了一个正确的值。
    #vim server.xml
    <Connector port="8080" protocol="HTTP/1.1"
    maxThreads="500"
    connectionTimeout="20000"
    redirectPort="8443" />

    在上述配置中,maxThreads值设定为“500”,指定可以由服务器处理的并发请求的最大数量是500。如果没有指定,这个属性的默认值为“200”。任何多出的并发请求将收到“拒绝连接”的错误提示,直到另一个处理请求进程被释放。错误看起来如下,
    [ org.apache.tomcat.util.threads.ThreadPool logFull SEVERE: All threads (500) are  currently busy, waiting. Increase maxThreads (500) or check the servlet status  

    最好使用“Tomcat集群”的多个实例。也就是说,如果有“1000”请求,两个Tomcat实例设置“maxThreads= 500”,而不在单Tomcat实例的情况下设置maxThreads=1000。

    -----------------------------
    <Connector port="9027"      
                    protocol="HTTP/1.1"     
                    maxHttpHeaderSize="8192"     
     maxThreads="1000"      客户请求最大线程数
                    minSpareThreads="100"      Tomcat初始化时创建的 socket 线程数
                    maxSpareThreads="1000"   Tomcat连接器的最大空闲 socket 线程数   
                    minProcessors="100"     服务器创建时的最小处理线程数
                    maxProcessors="1000"    服务器同时最大处理线程数
                    enableLookups="false"      若设为true, 则支持域名解析,可把 ip 地址解析为主机名
                    URIEncoding="utf-8"     URL统一编码
                    acceptCount="1000"      监听端口队列最大数,满了之后客户请求会被拒绝(不能小于maxSpareThreads  )
                    redirectPort="8443"      在需要基于安全通道的场合,把客户请求转发到基于SSL 的 redirectPort 端口
                    disableUploadTimeout="true"/> 

    3. 内核优化
    Tomcat运行过程中可能会出现大量ESTABLISHED(已建立的)连接与Time_Wait(等待)连接
    # netstat -n | awk '/^tcp/ {++y[$NF]} END {for(w in y) print w, y[w]}'
    CLOSE_WAIT 348 已关闭的等待链接
    ESTABLISHED 1240 已建立的链接
    TIME_WAIT 5621 等待连接,也是监控web与tomcat之间的链接端口
    #netstat -n | grep 8009 | wc -l
    7198
    1、怎样解决time_wait过多的问题:
    通过调整内核参数:
    # vim /etc/sysctl.conf #编辑文件,加入以下内容:
    net.ipv4.tcp_syncookies = 1
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1
    net.ipv4.tcp_fin_timeout = 30
    # /sbin/sysctl -p #让参数生效。
    配置说明:
    net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
    net.ipv4.tcp_tw_reuse = 1    表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
    net.ipv4.tcp_tw_recycle = 1  表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭;
    net.ipv4.tcp_fin_timeout=30修改系統默认的 TIMEOUT 时间。

    如果以上配置调优后性能还不理想,可继续修改一下配置:
    # vi /etc/sysctl.conf
    net.ipv4.tcp_keepalive_time = 1200
    #表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。keepalive,是在TCP中一个可以检测死连接的机制。
    net.ipv4.ip_local_port_range = 1024 65000
    #表示用于向外连接的端口范围。缺省情况下很小:32768到61000,可以改为1024到65000。
    net.ipv4.tcp_max_syn_backlog = 8192
    #表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
    net.ipv4.tcp_max_tw_buckets = 5000
    #表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。
    默认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于 Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。
    调优完毕,再压一下看看效果:
    # netstat -n | awk '/^tcp/ {++y[$NF]} END {for(w in y) print w, y[w]}'
    ESTABLISHED 968


    2、怎么解决请求结束后依然存在大量ESTABLISHED没有被释放
    初步推断是tomcat服务器回收session时出了问题,这个一般都跟服务器的Timeout设置有联系。
    查看tomcat的配置文件 server.xml
    <Connector port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" URIEncoding="UTF-8"/>
    *****检查配置得出链接的超时时间为20000毫秒的时候acceptCount(承受链接数统计)=”100” ,明显不合理,连接数也太小了。
    所以进一步优化:
    connectionTimeout="20000" 改为 connectionTimeout="100"
    acceptCount="100"改为acceptCount="5000"

     

  • 相关阅读:
    解决document.write问题
    js操作css样式
    最强大的对联广告,所有浏览器支持,ie6无抖动,缩放页面ie6没有横向滚动条
    JavaScript绘制图形Canvas
    DDD关键知识点整理汇总
    聚合(根)、实体、值对象精炼思考总结
    DDD领域驱动设计基本理论知识总结
    GVMStart 正常结果
    Ubuntu20.04安装、配置openvas 9
    VS Code MarkDown即时渲染编写插件
  • 原文地址:https://www.cnblogs.com/shmily2018/p/11590112.html
Copyright © 2020-2023  润新知