• TOMCAT


      参考:http://blog.oldboyedu.com/java-tomcat/

      一,Tomcat简介

      Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发而成。

    Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选。

    Tomcat和Nginx、Apache(httpd)、lighttpd等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Nginx/Apache服务器。

      二,安装TOMCAT  

      先安装java环境

      上传jar包jdk-8u60-linux-x64.tar.gz  apache-tomcat-8.0.27.tar.gz 

      配置java环境

    tar -xf jdk-8u60-linux-x64.tar.gz 
    mv jdk1.8.0_60/ /application/
    cd /application/
    mv jdk1.8.0_60/ jdk
    sed -i.ori '$a export JAVA_HOME=/application/jdk
    export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
    export CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar' /etc/profile
    source /etc/profile
    

      验证

    java -version
    

      解压配置tomcat

    tar -xf apache-tomcat-8.0.27.tar.gz
    mv apache-tomcat-8.0.27 /application/tomcat
    echo 'export TOMCAT_HOME=/application/tomcat'>>/etc/profile
    source /etc/profile
    

      

      三,TOMCAT目录介绍

    tree tomcat/ -L 1
    
    tomcat/
    ├── bin                            #启动关闭 sh是linux系统下使用的 bat是window下使用的
    ├── conf                          #配置文件
    ├── lib                             #存放web应用能访问的JAR包
    ├── LICENSE                   
    ├── logs                          #日志文件
    ├── NOTICE
    ├── RELEASE-NOTES
    ├── RUNNING.txt
    ├── temp                         #临时文件
    ├── webapps                  #Web应用程序跟目录
    └── work                         #用以产生由JSP编译出的Servlet的.java和.class文件
    

      web程序跟目录

    drwxr-xr-x. 14 root root 4096 4月  28 06:56 docs              #tomcat帮助文档
    drwxr-xr-x.  6 root root   83 4月  28 06:56 examples          #web应用实例
    drwxr-xr-x.  5 root root   87 4月  28 06:56 host-manager      #管理
    drwxr-xr-x.  5 root root  103 4月  28 06:56 manager          #管理
    drwxr-xr-x.  3 root root 4096 4月  28 06:56 ROOT              #默认网站根目录
    

      

      四,启动和关闭tomcat

    /application/tomcat/bin/startup.sh   
    /application/tomcat/bin/shutdown.sh
    

      默认启动端口为8080

    netstat -tunlp|grep java
    

      通过web界面访问

       默认访问的首页位置为/application/tomcat/webapps/ROOT/index.jsp

      假如删除访问会出现404找不到文件提示

      启动日志

    tail -f /application/tomcat/logs/catalina.out
    

      PS:catalina.out日志会每天自动切割,但是不会清除分割后的日子,运行时间久了使用重定向>清空,不要直接删除文件

      localhost_access_log.2018-04-28.txt为访问日志

      五,tomcat管理

      测试用,生产不要用

      Tomcat管理功能用于对Tomcat自身以及部署在Tomcat上的应用进行管理的web应用。在默认情况下是处于禁用状态的。如果需要开启这个功能,就需要配置管理用户,即配置前面说过的tomcat-users.xml。

      点击Server Status出现页面需要输入用户名和密码

      取消报401没有认证错误,并且告诉怎么配置

       修改配置文件/application/tomcat/conf/tomcat-users.xml 

      在</tomcat-users>前面加三行

    <role rolename="manager-gui"/>
    <role rolename="admin-gui"/>
    <user username="tomcat" password="tomcat" roles="manager-gui,admin-gui"/>
    

      重启tomcat

    /application/tomcat/bin/shutdown.sh
    /application/tomcat/bin/startup.sh 
    

      然后输入用户名tomcat和密码tomcat访问

      通过web端关闭应用

      可以上传war包

      添加虚拟主机

      类似于nginx的虚拟主机,生产中不常用,因为tomcat主要处理动态请求,生产中一个tomcat就是一个站点,如果有多个站点就启动多个tomcat(一般一个tomcat分配内存1.5-2G)类似于MySQL多实例

      tomcat生产优化: 把docs  examples  host-manager  manager全部移除,ROOT目录下所有文件移除,然后在打一个tar包统一用于生产主机

       

      六,tomcat配置文件

      配置文件路径

    /application/tomcat/conf/server.xml
    

      使用本机往8005端口发送SHUTDOWN关闭tomcat

      自动解压和加载

      配置文件注释

    <?xml version='1.0' encoding='utf-8'?>
    <!--
    <Server>元素代表整个容器,是Tomcat实例的顶层元素.由org.apache.catalina.Server接口来定义.它包含一个<Service>元素.并且它不能做为任何元素的子元素.
        port指定Tomcat监听shutdown命令端口.终止服务器运行时,必须在Tomcat服务器所在的机器上发出shutdown命令.该属性是必须的.
        shutdown指定终止Tomcat服务器运行时,发给Tomcat服务器的shutdown监听端口的字符串.该属性必须设置
    -->
    <Server port="8005" shutdown="SHUTDOWN">
      <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
      <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
      <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
      <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
      <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
      <GlobalNamingResources>
        <Resource name="UserDatabase" auth="Container"
                  type="org.apache.catalina.UserDatabase"
                  description="User database that can be updated and saved"
                  factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
                  pathname="conf/tomcat-users.xml" />
      </GlobalNamingResources>
      <!--service服务组件-->
      <Service name="Catalina">
        <!--
        connector:接收用户请求,类似于httpd的listen配置监听端口.
            port指定服务器端要创建的端口号,并在这个端口监听来自客户端的请求。
            address:指定连接器监听的地址,默认为所有地址(即0.0.0.0)
            protocol连接器使用的协议,支持HTTP和AJP。AJP(Apache Jserv Protocol)专用于tomcat与apache建立通信的, 在httpd反向代理用户请求至tomcat时使用(可见Nginx反向代理时不可用AJP协议)。
            minProcessors服务器启动时创建的处理请求的线程数
            maxProcessors最大可以创建的处理请求的线程数
            enableLookups如果为true,则可以通过调用request.getRemoteHost()进行DNS查询来得到远程客户端的实际主机名,若为false则不进行DNS查询,而是返回其ip地址
            redirectPort指定服务器正在处理http请求时收到了一个SSL传输请求后重定向的端口号
            acceptCount指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理
            connectionTimeout指定超时的时间数(以毫秒为单位)
        -->
        <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />
        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
        <!--engine,核心容器组件,catalina引擎,负责通过connector接收用户请求,并处理请求,将请求转至对应的虚拟主机host
            defaultHost指定缺省的处理请求的主机名,它至少与其中的一个host元素的name属性值是一样的
        -->
        <Engine name="Catalina" defaultHost="localhost">
          <!--Realm表示存放用户名,密码及role的数据库-->
          <Realm className="org.apache.catalina.realm.LockOutRealm">
            <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                   resourceName="UserDatabase"/>
          </Realm>
          <!--
          host表示一个虚拟主机
            name指定主机名
            appBase应用程序基本目录,即存放应用程序的目录.一般为appBase="webapps" ,相对于CATALINA_HOME而言的,也可以写绝对路径。
            unpackWARs如果为true,则tomcat会自动将WAR文件解压,否则不解压,直接从WAR文件中运行应用程序
            autoDeploy:在tomcat启动时,是否自动部署。
            xmlValidation:是否启动xml的校验功能,一般xmlValidation="false"。
            xmlNamespaceAware:检测名称空间,一般xmlNamespaceAware="false"。
          -->
          <Host name="localhost"  appBase="webapps"
                unpackWARs="true" autoDeploy="true">
            <!--
            Context表示一个web应用程序,通常为WAR文件
                docBase应用程序的路径或者是WAR文件存放的路径,也可以使用相对路径,起始路径为此Context所属Host中appBase定义的路径。
                path表示此web应用程序的url的前缀,这样请求的url为http://localhost:8080/path/****
                reloadable这个属性非常重要,如果为true,则tomcat会自动检测应用程序的/WEB-INF/lib 和/WEB-INF/classes目录的变化,自动装载新的应用程序,可以在不重启tomcat的情况下改变应用程序
            -->
            <Context path="" docBase="" debug=""/>
            <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
                   prefix="localhost_access_log" suffix=".txt"
                   pattern="%h %l %u %t "%r" %s %b" />
          </Host>
        </Engine>
      </Service>
    

      

      七,WEB站点部署

      上线的代码有两种方式,第一种方式是直接将程序目录放在webapps目录下面,这种方式大家已经明白了,就不多说了。第二种方式是使用开发工具将程序打包成war包,然后上传到webapps目录下面。下面让我们见识一下这种方式。

      上传war包

      上传后会自动解压

      web访问http://192.168.56.11:8080/memtest/meminfo.jsp

      

      tomcat多实例

      复制两份原tomcat

    cd /application/
    cp -a tomcat/ tomcat8_1
    cp -a tomcat/ tomcat8_2
    

      修改配置文件

      mkdir -p /data/www/www/ROOT
      cp /application/tomcat/webapps/memtest/meminfo.jsp /data/www/www/ROOT/
     sed -i '22s#8005#8011#;69s#8080#8081#;123s#appBase=".*"# appBase="/data/www/www"#' /application/tomcat8_1/conf/server.xml
     sed -i '22s#8005#8012#;69s#8080#8082#;123s#appBase=".*"# appBase="/data/www/www"#' /application/tomcat8_2/conf/server.xml
     diff /application/tomcat/conf/server.xml  /application/tomcat8_1/conf/server.xml   
    

      启动

    for i in {1..2};do /application/tomcat8_$i/bin/startup.sh;done
    

      查看

      web访问

       tomcat集群

      使用nginx反向代理tomcat即可(nginx反向代理配置不详述)

      tomcat安装JPress

      JPress,一个wordpress的java代替版本,使用JFinal开发。   需要maven支持

    tar -xf apache-maven-3.3.9-bin.tar.gz -C /application/
    ln -s /application/apache-maven-3.3.9/ /application/maven
    

      vim /etc/profile在尾部添加

    export MAVEN_HOME=/application/maven
    export PATH="$MAVEN_HOME/bin:$PATH"
    

      设置生效

     source /etc/profile
    

      验证

      上传jar包

      会自动解压

      在浏览器安装

       tomcat监控

      使用脚本找出前五个最忙的进程

      通用脚本,假如那台服务器CPU高直接执行把报错发给开发

    #!/bin/bash
    # @Function
    # Find out the highest cpu consumed threads of java, and print the stack of these threads.
    #
    # @Usage
    #   $ ./show-busy-java-threads
    #
    # @online-doc https://github.com/oldratlee/useful-scripts/blob/master/docs/java.md#beer-show-busy-java-threads
    # @author Jerry Lee (oldratlee at gmail dot com)
    # @author superhj1987 (superhj1987 at 126 dot com)
    
    readonly PROG="`basename $0`"
    readonly -a COMMAND_LINE=("$0" "$@")
    # Get current user name via whoami command
    #   See https://www.lifewire.com/current-linux-user-whoami-command-3867579
    # Because if run command by `sudo -u`, env var $USER is not rewritten/correct, just inherited from outside!
    readonly USER="`whoami`"
    
    ################################################################################
    # util funtions
    ################################################################################
    
    # NOTE: $'foo' is the escape sequence syntax of bash
    readonly ec=$'33' # escape char
    readonly eend=$'33[0m' # escape end
    
    colorPrint() {
        local color=$1
        shift
    
        # if stdout is console, turn on color output.
        [ -t 1 ] && echo "$ec[1;${color}m$@$eend" || echo "$@"
    
        [ -n "$append_file" ] && echo "$@" >> "$append_file"
    }
    
    redPrint() {
        colorPrint 31 "$@"
    }
    
    greenPrint() {
        colorPrint 32 "$@"
    }
    
    yellowPrint() {
        colorPrint 33 "$@"
    }
    
    bluePrint() {
        colorPrint 36 "$@"
    }
    
    normalPrint() {
        echo "$@"
        [ -n "$append_file" ] && echo "$@" >> "$append_file"
    }
    
    fatal() {
        redPrint "$@" 1>&2
        exit 1
    }
    
    usage() {
        [ -n "$1" -a "$1" != 0 ] && local out=/dev/stderr || local out=/dev/stdout
    
        > $out cat <<EOF
    Usage: ${PROG} [OPTION]... [delay [count]]
    Find out the highest cpu consumed threads of java, and print the stack of these threads.
    
    Example:
      ${PROG}       # show busy java threads info
      ${PROG} 1     # update every 1 second, (stop by eg: CTRL+C)
      ${PROG} 3 10  # update every 3 seconds, update 10 times
    
    Options:
      -p, --pid <java pid>      find out the highest cpu consumed threads from the specifed java process,
                                default from all java process.
      -c, --count <num>         set the thread count to show, default is 5
      -a, --append-file <file>  specify the file to append output as log
      -s, --jstack-path <path>  specify the path of jstack command
      -F, --force               set jstack to force a thread dump
                                use when jstack <pid> does not respond (process is hung)
      -m, --mix-native-frames   set jstack to print both java and native frames (mixed mode)
      -l, --lock-info           set jstack with long listing. Prints additional information about locks
      -h, --help                display this help and exit
      delay                     the delay between updates in seconds
      count                     the number of updates
                                delay/count arguments imitates the style of vmstat command
    EOF
    
        exit $1
    }
    
    ################################################################################
    # Check os support
    ################################################################################
    
    uname | grep '^Linux' -q || fatal "Error: $PROG only support Linux, not support `uname` yet!"
    
    ################################################################################
    # parse options
    ################################################################################
    
    readonly ARGS=`getopt -n "$PROG" -a -o p:c:a:s:Fmlh -l count:,pid:,append-file:,jstack-path:,force,mix-native-frames,lock-info,help -- "$@"`
    [ $? -ne 0 ] && usage 1
    eval set -- "${ARGS}"
    
    while true; do
        case "$1" in
        -c|--count)
            count="$2"
            shift 2
            ;;
        -p|--pid)
            pid="$2"
            shift 2
            ;;
        -a|--append-file)
            append_file="$2"
            shift 2
            ;;
        -s|--jstack-path)
            jstack_path="$2"
            shift 2
            ;;
        -F|--force)
            force=-F
            shift 1
            ;;
        -m|--mix-native-frames)
            mix_native_frames=-m
            shift 1
            ;;
        -l|--lock-info)
            more_lock_info=-l
            shift 1
            ;;
        -h|--help)
            usage
            ;;
        --)
            shift
            break
            ;;
        esac
    done
    count=${count:-5}
    
    update_delay=${1:-0}
    [ -z "$1" ] && update_count=1 || update_count=${2:-0}
    [ $update_count -lt 0 ] && update_count=0
    
    ################################################################################
    # check the existence of jstack command
    ################################################################################
    
    if [ -n "$jstack_path" ]; then
        [ -f "$jstack_path" ] || fatal "Error: $jstack_path is NOT found!"
        [ -x "$jstack_path" ] || fatal "Error: $jstack_path is NOT executalbe!"
    elif which jstack &> /dev/null; then
        jstack_path="`which jstack`"
    else
        [ -z "$JAVA_HOME" ] && fatal "Error: jstack not found on PATH and No JAVA_HOME setting! Use -s option set jstack path manually."
        [ -f "$JAVA_HOME/bin/jstack" ] || fatal "Error: jstack not found on PATH and $JAVA_HOME/bin/jstack($JAVA_HOME/bin/jstack) file does NOT exists! Use -s option set jstack path manually."
        [ -x "$JAVA_HOME/bin/jstack" ] || fatal "Error: jstack not found on PATH and $JAVA_HOME/bin/jstack($JAVA_HOME/bin/jstack) is NOT executalbe! Use -s option set jstack path manually."
        jstack_path="$JAVA_HOME/bin/jstack"
    fi
    
    ################################################################################
    # biz logic
    ################################################################################
    
    readonly uuid=`date +%s`_${RANDOM}_$$
    
    cleanupWhenExit() {
        rm /tmp/${uuid}_* &> /dev/null
    }
    trap "cleanupWhenExit" EXIT
    
    printStackOfThreads() {
        local line
        local counter=0
        while IFS=" " read -a line ; do
            local pid=${line[0]}
            local threadId=${line[1]}
            local threadId0x="0x`printf %x ${threadId}`"
            local pcpu=${line[3]}
            local user=${line[4]}
    
            ((counter++))
            local jstackFile=/tmp/${uuid}_${pid}
            [ -f "${jstackFile}" ] || {
                if [ "${user}" == "${USER}" ]; then
                    # run without sudo, when java process user is current user
                    "$jstack_path" ${force} $mix_native_frames $more_lock_info ${pid} > ${jstackFile}
                elif [ $UID == 0 ]; then
                    # if java process user is not current user, must run jstack with sudo
                    sudo -u "${user}" "$jstack_path" ${force} $mix_native_frames $more_lock_info ${pid} > ${jstackFile}
                else
                    # current user is not root user, so can not run with sudo; print error message and rerun suggestion
                    redPrint "[$counter] Fail to jstack busy(${pcpu}%) thread(${threadId}/${threadId0x}) stack of java process(${pid}) under user(${user})."
                    redPrint "User of java process($user) is not current user($USER), need sudo to rerun:"
                    yellowPrint "    sudo ${COMMAND_LINE[@]}"
                    normalPrint
                    continue
                fi || {
                    redPrint "[$counter] Fail to jstack busy(${pcpu}%) thread(${threadId}/${threadId0x}) stack of java process(${pid}) under user(${user})."
                    normalPrint
                    rm ${jstackFile}
                    continue
                }
            }
    
            bluePrint "[$counter] Busy(${pcpu}%) thread(${threadId}/${threadId0x}) stack of java process(${pid}) under user(${user}):"
    
            if [ -n "$mix_native_frames" ]; then
                local sed_script="/--------------- $threadId ---------------/,/^---------------/ {
                    /--------------- $threadId ---------------/b # skip first seperator line
                    /^---------------/s/.*// # replace sencond seperator line to empty line
                    p
                }"
            elif [ -n "$force" ]; then
                local sed_script="/^Thread ${threadId}:/,/^$/p"
            else
                local sed_script="/nid=${threadId0x} /,/^$/p"
            fi
            sed "$sed_script" -n ${jstackFile} | tee ${append_file:+-a "$append_file"}
        done
    }
    
    headInfo() {
        echo ================================================================================
        echo "$(date "+%Y-%m-%d %H:%M:%S.%N") [$((i+1))/$update_count]: ${COMMAND_LINE[@]}"
        echo ================================================================================
        echo
    }
    
    # if update_count <= 0, infinite loop till user interupted (eg: CTRL+C)
    for ((i = 0; update_count <= 0 || i < update_count; ++i)); do
        [ "$i" -gt 0 ] && sleep "$update_delay"
    
        [ -n "$append_file" ] && headInfo >> "$append_file"
        [ "$update_count" -ne 1 ] && headInfo
    
        # use wide output(unlimited width), avoid trunk user column to username_fo+ or $uid alike
        ps -wwLeo pid,lwp,comm,pcpu,user --no-headers | {
            [ -z "${pid}" ] &&
            awk '$3=="java"{print $0}' ||
            awk -v "pid=${pid}" '$1==pid,$3=="java"{print $0}'
        } | sort -k4,4 -r -n | head -n "${count}" | printStackOfThreads
    done

       

      zabbix监控tomcat

      开启tomcat远程监控的功能

      /application/tomcat/bin/catalina.sh

    CATALINA_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=12345"
    

      zabbix server的java支持

      编译加上--enable-jave参数,或者yum安装zabbix-java-gateway

       启动zabbix-java-gateway

    systemctl start zabbix-java-gateway
    

      验证

      修改配置文件/etc/zabbix/zabbix_server.conf

      重启zabbix-server

    systemctl restart zabbix-server
    

      验证(有这五个进程代表正常)

      在zabbix页面添加jvm监控

      tomcat调优

      安全优化

      降权启动

      复制tomcat文件夹至普通用户文件夹并且授权给普通用户然后切换到普通用户即可使用普通用户启动tomcat

      telnet管理端口保护

      把默认的8005端口改成其他端口,关闭命令默认是SHUTDOWN可以修改成其他的

      ajp连接端口保护

      注释8009端口哪行

      禁用管理端

      删除默认的doc,managed目录

      其他优化

       性能优化

      屏蔽dns查询 enableLookup=“false”

        <Connector  port="8081" protocol="HTTP/1.1"
                   connectionTimeout="6000" enableLookups="false" acceptCount="800"
                   redirectPort="8443" />
    

     

      jvm调优

      tomcat最吃内存,只要内存够,就跑的很快

      如果系统资源有限,那就需要进行调优,提高资源利用率

    优化catalina.sh配置文件。在catalina.sh配置文件中添加以下代码:
    JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1024m -Xmx1024m -XX:NewSize=512m -XX:MaxNewSize=512m -XX:PermSize=512m -XX:MaxPermSize=512m"
    server:一定要作为第一个参数,在多个CPU时性能佳
    -Xms:初始堆内存Heap大小,使用的最小内存,cpu性能高时此值应设的大一些
    -Xmx:初始堆内存heap最大值,使用的最大内存
    上面两个值是分配JVM的最小和最大内存,取决于硬件物理内存的大小,建议均设为物理内存的一半。
    -XX:PermSize:设定内存的永久保存区域
    -XX:MaxPermSize:设定最大内存的永久保存区域
    -XX:MaxNewSize:
    -Xss 15120 这使得JBoss每增加一个线程(thread)就会立即消耗15M内存,而最佳值应该是128K,默认值好像是512k.
    +XX:AggressiveHeap 会使得 Xms没有意义。这个参数让jvm忽略Xmx参数,疯狂地吃完一个G物理内存,再吃尽一个G的swap。
    -Xss:每个线程的Stack大小
    -verbose:gc 现实垃圾收集信息
    -Xloggc:gc.log 指定垃圾收集日志文件
    -Xmn:young generation的heap大小,一般设置为Xmx的3、4分之一
    -XX:+UseParNewGC :缩短minor收集的时间
    -XX:+UseConcMarkSweepGC :缩短major收集的时间
    

      

      

      

      

  • 相关阅读:
    如何通過編程獲取列表項目的附件以及多行文本中的文件內容
    小技巧:如何管理保存在本地的用户凭据
    WF 4.0中如何实现xaml工作流的动态加载
    使用jquery构造自己的多级菜单
    和安蕾尔的合影
    360太tmd脑残了
    3D 打印机技术设想
    再放2张数字油画
    解决问题的艺术:半小时编程实现照片的反转负冲特效
    承接数字油画图稿/线条图定制(出图)业务
  • 原文地址:https://www.cnblogs.com/minseo/p/8964936.html
Copyright © 2020-2023  润新知