存档一月 2020

Tomcat 服务器



Tomcat 服务安装  是一个java虚拟机

    # yum install jdk-8u231-linux-x64.rpm   \\ rpm包安装 需先下载到当前目录
        # rpm -ivh jdk-8u231-linux-x64.rpm   \\ 或者使用rpm-ivh安装
    # rpm -ql jdk1.8
        /usr/java/jdk1.8.0_231-amd64/    \\ 安装路径
        /usr/java/latest                  \\ 链接到 安装路径 表示最新版
        /usr/java/default                  \\ 链接到 latest
    # vim /etc/profile.d/java.sh            \\ 把java的运行环径境输出给系统 能找到 需要配置环境变量 新建
        export JAVA_HOME=/usr/java/latest    \\ 定义变量指明安装路径 对于java而已所有内容都放在一个JAVA_HOME变量 
                                              \\ 很多应用程序都会去找这个变量 把这个变量对应的值当做java的查找路径
        export PATH=$JAVA_HOME/bin:$PATH       \\ 把java自己bin路径 定义成变量PATH
    # . /etc/profile.d/java.sh       \\ 重读此文件
    # java -version                   \\ 可以看到版本等信息 如果看到与之版本相同说明JDK环境配置成功 默认会有1.8其他版本的安装
    # tar zxf apache-tomcat-8.5.50.tar.gz -C /usr/local    \\ 二进制包安装
    # cd /usr/local
    # mv apache-tomcat-8.5.50/ tomcat
    # vim /etc/profile.d/tomcat.sh            \\ 创建环境变量
        export CATALINA_HOME=/usr/local/tomcat \\ tomcat自己的运行需要一个CATALINA_BASE的环境变量来指明自己位于什么路径之下
        export PATH=$CATALINA_HOME/bin:$PATH    \\ 并且也要输入环境变量到搜索路径中去
    # . /etc/profile.d/tomcat.sh                 \\ 重读此脚本
    # version.sh                                  \\ 可以直接运行 /usr/local/tomcat/bin/ 下的脚本 可看到tomcat版本号
    # catalina.sh version                          \\ 亦可以使用catalina调用 当做传递个参数即可
    # configtest.sh                                 \\ 检查有没有语法错误的
    # catalina.sh --help                             \\ 查询catalina怎么用
        run               在当前窗口中直接运行
        start             在另外的窗口中运行
        stop              停止服务
        stop n            等待多长时间停止 默认5秒
        stop -force       强制停止服务
        configtest        测试文件的语法
        version           显示当前tomcat的版本号
        start -security   使用安全管理器启动
    # catalina.sh start                      \\ 启动tomcat  http://192.168.10.15/8080 可以访问tomcat页面 同时监听8009
    # ss -tnlp                                \\ 监听8080端口 会发现是java监听8080端口 而不是tomcat
    # vim /usr/local/tomcat/conf/server.xml    \\ 主配置文件


  ① 在默认路径添加一个测试应用程序
    # cd /usr/local/tomcat/webapps          
    # mkdir -pv teo/{lib,classes,EB-INF,META-INF} \\ 如果自己没有创建web.xml context.lxml 会去conf/目录下继承默认配置
    # vim teo/index.jsp                            \\ 创建jsp测试页 浏览器访问 http://192.168.10.15:8080/teo/index.jsp
        <%@ page language="java" %>
        <%@ page import="java.util.*" %>
        <html>
            <head>
                <title>JSP Test Page</title>
            </head>
            <body>
                <% out.println("Hello,World."); %>
            </body>
        </html>
    # tree /usr/local/tomcat                             \\ 应用程序运行时 会到 work/的转为java文件最后编译成.class文件运行
    # vim work/Catalina/localhost/teo/org/apache/jsp/index_jsp.java           \\ 会把jsp文件转换为java代码


  ② 配置不同的路径 定义一个虚拟主机Host
    # mkdir -pv /data/www/webapps
    # cd /data/www/webapps
    # mkdir -pv teo15/{lib,classes,EB-INF,META-INF}
    # mkdir -pv janice/{lib,classes,EB-INF,META-INF}
    # vim teo/index.jsp                                  \\ 创建第一个主页面 访问路径 192.168.10.15:8080
        <%@ page language="java" %>
        <%@ page import="java.util.*" %>
        <html>
            <head>
                <title>JSP Test Page</title>
            </head>
            <body>
                <% out.println("Hello,World."); %>
            </body>
        </html>
    # vim janice/index.jsp     \\ 创建第二个jsp页面 可以到网上复制jsp代码测试 访问页面192.168.10.15:8080/janice
    # vim /usr/local/tomcat/conf/server.xml    \\ 主配置文件
        <Host name="www.teo15.com" appBase="/data/webapps" unpackWARs="true" autoDeploy="false"> \\ 详见注解04
            <Context path="" docBase="/data/webapps/teo15" reloadable="true" />
                <Valve className="org.apache.catalina.valves.RemoteAddrValve"
                    deny="192\.168\.10\.10" />
            <Context path="/janice" docBase="janice" reloadable="true" />
            <Valve className="org.apache.catalina.valves.AccessLogValve" directory="/data/logs"
                   prefix="teo15_access_log" suffix=".txt"
                   pattern="%h %l %u %t "%r" %s %b" />
        </Host>
    # catalina.sh stop
    # catalina.sh start
    # ss -tnlp                 \\ 8080被java监控 同时监听8009


  ③ tomcat自带的应用程序 使用web应用程序管理及web虚拟主机管理                  \\ 开启此功能需要修改配置文件
    # vim /usr/local/tomcat/webapps/manager/META-INF/context.xml
        <!--                                                             \\ 注释到此段代码 此为只有本机用户ip可以访问
            <Valve className="org.apache.catalina.valves.RemoteAddrValve"
                 allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
        -->
    # vim /usr/local/tomcat/webapps/host-manager/META-INF/context.xml 
        <!--                                                                 \\ 注释到此段代码 此为只有本机用户ip可以访问
            <Valve className="org.apache.catalina.valves.RemoteAddrValve"
                allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
        -->
    # vim /usr/local/tomcat/conf/tomcat-users.xml                 \\ 配置上用户名和密码
        <role rolename="manager-gui"/>                             \\ 开启 Manager App 应用程序管理
        <role rolename="admin-gui"/>                                \\ 开启 Host Manager 虚拟主机管理
        <user username="admin" password="123456" roles="manager-gui,admin-gui"/>
    # catalina.sh stop
    # catalina.sh start
    访问 http://192.168.10.15:8080   --> Manager App  Tomcat Web应用程序管理者   --> Host Manager 虚拟主机管理

  ④ 常用 组合
    ❶ LNMT:       使用nginx 反向代理到tomcat  可实现动静分离
        # yum install epel-release
        # yum install nginx
        # vim /etc/nginx/nginx.conf               \\ 反向代理给tomcat  可实现动静分离   java程序有的是jsp结尾有的是do结尾
            location ~* \.(jsp|do)$ {       \\ ~模式匹配 *不区分字符大小写 \.转意. jsp或者do结尾  $行尾牟定
                proxy_pass http://www.teo15.com:8080;           \\ 动态内容 反向代理到teo15     以teo15访问
            }
        # systemctl restart nginx

    ❷ LAMT:       使用httpd 反向代理到tomcat  动静分离一般不使用httpd
        # yum install httpd
        # httpd -M              \\ 显示所有模块
            proxy_module         \\ 反向代理 主模块
            proxy_module_http     \\ 子模块1   基于http协议 反向代理 使用此模块
            proxy_module_ajp       \\ 子模块2  基于ajp协议 反向代理 使用此模块
        # vim /etc/httpd/conf/httpd.conf       \\ 编辑httpd主配置文件  
            # DocumentRoot "/var/www/html"      \\ 注释掉  配置反向代理有可能会出错
            ServerName www.teo12.com             \\ 随便起个名字 否则语法会警告
        # vim /etc/httpd/conf.d/www.teo12.com     \\ 自己创建虚拟主机 实现反向代理功能
            <VirtualHost *:80>                     \\ 虚拟主机 监听在所有端口的80端口
                ServerName www.teo12.com            \\ 虚拟主机名字
                ProxyVia On                          \\ 加首部 说明由此主机反向代理过去的 可以不添加为Off
                ProxyRequests Off                     \\ 同时支持正想代理 使用反向 必须要显示关闭正向代理
                ProxyPreserveHost On                   \\ 基于主机名的虚拟主机 把主机名会带到后端
                <Proxy *>                               \\ 代理模块 允许哪些用户使用
                        Require all granted              \\ 允许所有人访问
                </proxy>
                ProxyPass /status !                         \\ 可以使status页面不代理到后端 由本机httpd响应 也可以去掉
                ProxyPass / http://192.168.10.15:8080/       \\ 反向代理 /根的所有请求 到 此代理为基于http协议
                    # ProxyPass / ajp://192.168.10.15:8009/   \\ 此代理为基于ajp协议 如果用此 注释掉上一条
                ProxyPassReverse / http://192.168.10.15:8080/  \\ 加不加无所谓
                <Location />                                    \\ 定义location 根 允许哪些人访问
                        Require all granted                      \\ 允许所有人访问
                </location>
            </virtualHost>
        # httpd -t                \\ 检查语法错误
        # systemctl restart httpd
        # ss -tnl

    ❸ LNAMT:   使用nginx做负载均衡 到后端http接收请求在反向代理到同一主机的tomcat  此用法比较多


  ⑤ Tomcat主配置文件详解                                  \\ 待补充
    # vim /usr/local/tomcat/conf/server.xml              \\ 主配置文件
        <Server port="8005" shutdown="SHUTDOWN">
            <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />
            <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
                <Engine name="Catalina" defaultHost="localhost">
          <Host name="localhost"  appBase="webapps"
                unpackWARs="true" autoDeploy="true">


  ⑥ Tomcat的主配置文件结构
    <server>                    \\ 整个tomcat容器 主要任务 提供一个接口管理接口 可以启动 停止等 可以包含多个service 
        <service>                \\ 可以有多个connector连接器 只能有一个engine
            <connector />         \\ 作用是从客户端接收请求 提供端口 被客户端访问tomcat 接收到的请求会给engine
            <connector />
            <engine >               \\ 从连接器接收来请求 并处理
                <host name="">       \\ 可以有多个 虚拟主机 
                    <contest />       \\ 可以有多个 应用程序 
                    <contest />        \\ 可以有多个 应用程序
                </host>
                <host name="">
                </host>
            </engine>
        </service>
    </server>
    ❶ Connector 连接器 
        HTTP连接器
        SSL连接器
        AJP 1.3连接器 一共三种协议连接器
        address 指定连接器监听的地址,默认为所有地址 即0.0.0.0
        maxThreads 支持的最大并发连接数 默认为 200
        port 监听的端口 默认为0
        protocol 连接器使用的协议默认为HTTP/1.1 定义AJP协议时通常为AJP/1.3
        redirectPort 如果某连接器支持的协议时HTTP 当接收客户端发来的HTTPS请求时 则转发至此属性定义的端口
        connectionTimeout 连接超时时间 单位毫秒 默认60000 即1秒
        enableLookups 反解ip地址 为主机名 默认开启 建议关闭 enableLookups="false"
        acceptCount 等待队列的最大长度
        minSpareThreads 最小空闲线程
        maxSpareThreads 最大空闲线程
        <Connector port="8443"
            maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
            enableLookups="false" acceptCount="100" debug="0" scheme="https" secure="true"
            clientAuth="false" sslProtocol="TLS" />
    ❷ Engine            引擎 
        defaultHost   默认引擎
        name          用于日志和错误信息记录时区别不同的引擎
    ❸ Host 位于Engine容器中
        appBase   此Host的webapps目录 存放web应用程序的目录或归档后的WAR文件的目录路径
        autoDeploy 

  注:
    ❶ tomcat官网 http://tomcat.apache.org                                                                需登录下载
    ❷ JDK官网    https://www.oracle.com/technetwork/java/javase/overview/index.html a09669461688@gmail.com Teo@1234
    ❸ host 各个参数详解
      host 虚拟主机 如果使用相对路径 是相对tomcat安装目录
      name 属性指定虚拟主机的主机名 一个Engine中有且仅有一个Host组件的name属性与Engine组件的defaultHost属性相匹配 
      unpackWARs 是否将代表Web应用的WAR文件解压 如为true 解压后的文件结构运行该Web应用 如为false 直接使用WAR文件运行Web应用
      appBase 属性指定Web应用所在的目录,默认值是webapps,这是一个相对路径,代表Tomcat根目录下webapps文件夹 这个里给出的绝对路径
      utoDeploy="false" 关闭自动部署
    ❹ Context 各个参数详解
        <Host name="www.teo15.com" appBase="/data/webapps" unpackWARs="true" autoDeploy="false"> 
            \\ 新增host主机 appBase设置网站根目录 注解03
            <Context path="" docBase="/data/webapps/teo15" reloadable="true" />  
               \\ 访问上面的根目录 自动会映射到docBase路径上   ""什么都没有代表与上路径相同 path给定的路径不能有以/结尾
                <Valve className="org.apache.catalina.valves.RemoteAddrValve"     
                  \\ 添加访问控制 \为转意符  context详解见 注解04
                    deny="192\.168\.10\.10" /> 
            <Context path="/janice" docBase="janice" reloadable="true" />            
                      \\ /janice 代表网站根目录appBase下的janice目录为访问路径  docBase为相对于appBase的路径为实际程序路径
            <Valve className="org.apache.catalina.valves.AccessLogValve" directory="/data/logs"            \\ 日志文件
                   prefix="teo15_access_log" suffix=".txt"
                   pattern="%h %l %u %t "%r" %s %b" />
        </Host>
      Context类似apache中的路径别名 如果使用相对路径 是相对host中的appBase而言
      path=""什么没有代表访问的根路径 docBase路径
      reloadable属性指示tomcat是否在运行时监控在WEB-INF/classes和WEB-INF/lib目录下class文件的改动.
      如果值为true,那么当class文件改动时,会触发Web应用的重新加载.在开发环境下,reloadable设置为true便于调试,
      但是在生产环境中设置为true会给服务器带来性能压力,因此reloadable参数的默认值为false.
    ❺ 各个配置文件说明
      server.xml  主配置文件
      contest.xml  每个webapp都可以有专用的配置文件,这些配置文件通常位于webapp应用程序目录下的web.inf目录中,
                   用于定义会话管理器/JDBC等 conf/context.xml是为各webapp提供默认配置
      web.xml  每个webapp部署之后才能被访问 此文件则用于为所有的webapp提供默认部署相关的配置
      tomcat-users.xml  用户认证的账号和密码配置文件
      catalina.policy  当使用-security选项启动tomcat实例时会读取此配置文件来实现其安全运行策略
      catalina.properties  Java属性的定义文件用于设定类加载器路径等 以及一些JVM性能相关的调优参数
      logging.properties  日志相关的配置信息
    ❻ tomcat应用程序目录用途
        # cd /usr/local/tomcat/webapps         \\ tomcat应用程序
        # yum install tree                      \\ 可以查看某一目录的树状结构
        # tree /usr/local/tomcat/webapps/manager \\ webapp 组织结构 包含有servlet代码文件 JSP页面文件 类文件部署描述符文件等
            WEB-INF:        当前webapp的私有资源目录通常存放当前webapp自用的web.xml;
            META-INF:       当前webapp的私有资源目录通常存放当前webapp自用的context.xml;
            classes:       此webapp的私有类
            lib:            此webapp的私有类 被打包为jar格式类
            index.jsp:      webapp的主页
            .war   webapp       war文件 war归档
            .jar   EJB的类
            .rar   资源适配器    
            .ear   企业级应用程序


实例 session cluster 会话 集群
    前端Nginx/Apache反代 + 负载均衡 到后端两台Tomcat服务器  + Memcached session id 保持 

  1 两台Tomcat服务器配置
    # tar zxf apache-tomcat-8.5.50.tar.gz  -C /usr/local              \\ 只安装了tomcat jdk使用了系统自带的
    # cd /usr/local/
    # mv apache-tomcat-8.5.50/ tomcat
    # vim /etc/profile.d/tomcat.sh
        export CATALINA_HOME=/usr/local/tomcat
        export PATH=$CATALINA_HOME/bin:$PATH
    # catalina.sh version
    # vim /etc/profile.d/tomcat.sh 
        export CATALINA_HOME=/usr/local/tomcat
        export PATH=$CATALINA_HOME/bin:$PATH
    # vim /usr/local/tomcat/conf/server.xml                       \\ 修改或添加 以下代码  ↓ 修改默认主机 jvmRoute 唯一标识 
        <Engine name="Catalina" defaultHost="teo13.com" jvmRoute="TomecatA"> \\ 前端是httpd服务器中可以用到 第二台TomecatB
            <Host name="teo13.com" appBase="/data/webapps" autoDeploy="true"> \\ 添加Host 主机
                <Context path="" docBase="ROOT">
                </Context>
                    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="/data/logs"    \\ 日志
                        prefix="teo13_access_log" suffix=".txt"
                        pattern="%h %l %u %t "%r" %s %b" />
            </Host>
    # catalina.sh configtest                                     \\ 检查语法
    # mkdir -p /data/logs
    # mkdir -pv /data/webapps/ROOT/{lib,classes,META-INF,WEB-INF}
    # vim /data/webapps/ROOT/index.jsp                \\ 新建 仅为测试页代码
        <%@ page language="java" %>
        <html>
            <head><title>TomcatA</title></head>
            <body>
                <h1><font color="blue">TomcatA.teo10.com</font></h1>
                <table align="center" border="1">
                  <tr>
                    <td>Session ID</td>
                <% session.setAttribute("teo10.com","teo10.com"); %>
                    <td><%= session.getId() %></td>
                  </tr>
                  <tr>
                    <td>Created on</td>
                    <td><%= session.getCreationTime() %></td>
                  </tr>
                </table>
            </body>
        </html>
    # catalina.sh start                  \\ 启动
    # ss -tnl                             \\ 8080 8009被监听  访问teo13.com.8080 需修改hosts文件

  2.1 ① 使用apache反向代理到后端tomcat服务器 使用负载均衡      \\ 实现为第一种方法基于http协议
    # yum install httpd
    # httpd -M                             \\ 可以看到 所有模块
        proxy_balancer_module (shared)      \\ 此模块能实现 负载均衡功能
    # vim /etc/httpd/conf/httpd.conf         \\ 主配置文件
        #DocumentRoot "/var/www/html"         \\ 注释掉 中心主机 选项
    # cd /etc/httpd/conf.d
    # vim vhosts.conf                           \\ 自定义虚拟主机  增加配置文件
        Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED \\ session绑定需加
        <proxy balancer://lbcluster1>
            BalancerMember http://192.168.10.12:8080 loadfactor=10 route=TomcatA  \\ 后端TomcatA特有的标识
            BalancerMember http://192.168.10.13:8080 loadfactor=10 route=TomcatB
            ProxySet stickysession=ROUTEID                                       \\ 基于session绑定需要加
        </proxy>
        <VirtualHost *:80>
            ServerName www.teo10.com
            ProxyVia On
            ProxyRequests Off
            ProxyPreserveHost On
            <Proxy *>
                    Require all granted
            </proxy>
            ProxyPass / balancer://lbcluster1/
            ProxyPassReverse / balancer://lbcluster1/
            <Location />
                    Require all granted
            </location>
        </virtualHost>
    # httpd -t
    # systemctl restart httpd
    # ss -tnl                                                \\ http://192.168.10.10/index.jsp 访问测试

  2.1 ② 使用apache反向代理到后端tomcat服务器 使用负载均衡         \\ 第二种方法 使用agp协议 需修改的代码如下  其余与httpd均相同
        BalancerMember agp://192.168.10.12:8009 loadfactor=10 route=TomcatA  
        BalancerMember agp://192.168.10.13:8009 loadfactor=10 route=TomcatB

  2.2 使用nginx反向代理到后端tomcat服务器 使用负载均衡
    # yum install nginx
    # vim /etc/nginx/nginx.conf
        upstream tomserver{
            ip_hash;
            server teo12.com:8080;
            server teo13.com:8080;
        }
        location ~* \.(jsp|do)$ {              \\ 只把动态页面反向代理到后端tomcat服务器
            proxy_pass http://tomserver;
        }
    # systemctl restart nginx
    # ss -tnl                        \\ http://192.168.10.10/index.jsp


  注:
    使用Apache反向代理到后端Tomcat  可以有以下三种方案
      ❶ apache
            mod_proxy
            mod_proxy_http
            mod_proxy_balancer   \\ 可以提供负载均衡功能
        tomcat
            http connector         \\ http连接器
      ❷ apache
            mod_proxy
            mod_proxy_ajp
            mod_proxy_balancer \\ 可以提供负载均衡功能
        tomcat
            ajp connector        \\ 前两种 只做反代 负载均衡需借助其他模块
      ❸ apache                    \\ 第三种很少使用   没做实验 在第38天视频01最后十分钟和视频02
            mod_jk                 \\ 又能做反代  又能负载均衡
        tomcat
            ajp connector   

  3 做 保持会话信息  两台Tomcat服务器配置     \\ 基于http协议   如果基于agp同上修改协议及端口即可
    # vim server.xml                        \\ 添加到Host里即可 详见注解 ❷
        <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
                 channelSendOptions="8">

          <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>

          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="auto"
                      port="4000"
                      autoBind="100"
                      selectorTimeout="5000"
                      maxThreads="6"/>

            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
          </Channel>

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=""/>
          <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/tmp/war-deploy/"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="false"/>

          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>
    # cp /usr/local/tomcat/conf/web.xml /data/webapps/ROOT/WEB-INF/ \\ 复制此配置文件到此程序下只有此程序生效 直接改全局生效
    # vim /data/webapps/ROOT/WEB-INF/web.xml   \\ 为需要使用session cluster的webaaps开启 session distribution功能
        <distributable/>                        \\ 倒数第二行添加即可
    # catalina.sh stop
    # catalina.sh configtest                      \\ 检测语法
    # catalina.sh start
    # ss -tnl                                       \\ http://192.168.10.10 刷新测试 可以保持会话
    # tail /usr/local/tomcat/logs/catalina.out       \\ 两点同时启动 可以查看日志此节点有另外一个节点的ip

  注
    ❶ 此为tomcat8.5的cluster文档 各个版本的配置不一样 需要注意 其他版本参考其他文档
      帮助文档地址 https://tomcat.apache.org/tomcat-8.5-doc/cluster-howto.html

    ❷ 详解
    <!-- 
        Cluster(集群,族) 节点,如果你要配置tomcat集群,则需要使用此节点.
        className 表示tomcat集群时,之间相互传递信息使用那个类来实现信息之间的传递.
        channelSendOptions可以设置为2、4、8、10,每个数字代表一种方式
        2 = Channel.SEND_OPTIONS_USE_ACK(确认发送)
        4 = Channel.SEND_OPTIONS_SYNCHRONIZED_ACK(同步发送) 
        8 = Channel.SEND_OPTIONS_ASYNCHRONOUS(异步发送)
        在异步模式下,可以通过加上确认发送(Acknowledge)来提高可靠性,此时channelSendOptions设为10
    -->
    <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8">
        <!--
            Manager决定如何管理集群的Session信息。Tomcat提供了两种Manager:BackupManager和DeltaManager
            BackupManager-集群下的所有Session,将放到一个备份节点。集群下的所有节点都可以访问此备份节点
            DeltaManager-集群下某一节点生成、改动的Session,将复制到其他节点。
            DeltaManager是Tomcat默认的集群Manager,能满足一般的开发需求
            使用DeltaManager,每个节点部署的应用要一样;使用BackupManager,每个节点部署的应用可以不一样.
            className-指定实现org.apache.catalina.ha.ClusterManager接口的类,信息之间的管理.
            expireSessionsOnShutdown-设置为true时,一个节点关闭,将导致集群下的所有Session失效
            notifyListenersOnReplication-集群下节点间的Session复制、删除操作,是否通知session listeners
            maxInactiveInterval-集群下Session的有效时间(单位:s)。
            maxInactiveInterval内未活动的Session,将被Tomcat回收。默认值为1800(30min)
        -->
        <Manager className="org.apache.catalina.ha.session.DeltaManager"
                 expireSessionsOnShutdown="false"
                 notifyListenersOnReplication="true"/>
        <!--
            Channel是Tomcat节点之间进行通讯的工具。
            Channel包括5个组件:Membership、Receiver、Sender、Transport、Interceptor
        -->
        <Channel className="org.apache.catalina.tribes.group.GroupChannel">
             <!--
                Membership维护集群的可用节点列表。它可以检查到新增的节点,也可以检查到没有心跳的节点
                className-指定Membership使用的类
                address-组播地址
                port-组播端口
                frequency-发送心跳(向组播地址发送UDP数据包)的时间间隔(单位:ms)。默认值为500
                dropTime-Membership在dropTime(单位:ms)内未收到某一节点的心跳,则将该节点从可用节点列表删除。默认值为3000

                注: 组播(Multicast):一个发送者和多个接收者之间实现一对多的网络连接。
                    一个发送者同时给多个接收者传输相同的数据,只需复制一份相同的数据包。
                    它提高了数据传送效率,减少了骨干网络出现拥塞的可能性
                    相同组播地址、端口的Tomcat节点,可以组成集群下的子集群
             -->
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <!--
                Receiver : 接收器,负责接收消息
                接收器分为两种:BioReceiver(阻塞式)、NioReceiver(非阻塞式)

                className-指定Receiver使用的类
                address-接收消息的地址
                port-接收消息的端口
                autoBind-端口的变化区间
                如果port为4000,autoBind为100,接收器将在4000-4099间取一个端口,进行监听
                selectorTimeout-NioReceiver内轮询的超时时间
                maxThreads-线程池的最大线程数
            -->
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="auto"
                      port="4000"
                      autoBind="100"
                      selectorTimeout="5000"
                      maxThreads="6"/>
            <!--
                Sender : 发送器,负责发送消息
                Sender内嵌了Transport组件,Transport真正负责发送消息
            -->
            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
                <!--
                    Transport分为两种:bio.PooledMultiSender(阻塞式)、nio.PooledParallelSender(非阻塞式) 
                -->
                <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>
            <!--
                Interceptor : Cluster的拦截器
                TcpFailureDetector-网络、系统比较繁忙时,Membership可能无法及时更新可用节点列表,
                此时TcpFailureDetector可以拦截到某个节点关闭的信息,
                并尝试通过TCP连接到此节点,以确保此节点真正关闭,从而更新集群可以用节点列表                 
            -->
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <!--
                MessageDispatch15Interceptor-查看Cluster组件发送消息的方式是否设置为
                Channel.SEND_OPTIONS_ASYNCHRONOUS(Cluster标签下的channelSendOptions为8时)。
                设置为Channel.SEND_OPTIONS_ASYNCHRONOUS时,
                MessageDispatch15Interceptor先将等待发送的消息进行排队,然后将排好队的消息转给Sender
            -->
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
        </Channel>
        <!--
            Valve : 可以理解为Tomcat的拦截器
            ReplicationValve-在处理请求前后打日志;过滤不涉及Session变化的请求                   
            vmRouteBinderValve-Apache的mod_jk发生错误时,保证同一客户端的请求发送到集群的同一个节点
        -->
        <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/>
        <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
        <!--
            Deployer : 同步集群下所有节点的一致性。Deployer没试验成功过。。。
         -->
         <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                       tempDir="/tmp/war-temp/"
                       deployDir="/tmp/war-deploy/"
                       watchDir="/tmp/war-listen/"
                       watchEnabled="false"/>
        <!--
            ClusterListener : 监听器,监听Cluster组件接收的消息
            使用DeltaManager时,Cluster接收的信息通过ClusterSessionListener传递给DeltaManager
        -->
        <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
    </Cluster>

  4 Tomcat节点 把会话保存在memcached上 已实现session server功能       \\ 基于1 2实验
    memcached 缓存 session id 实现 Tomcat session 保持

    ❶ 基于以上实验 一台 Nginx/Apache 做负载均衡 反代到后端 两台Apache服务器的80端口在反代到8080端口的Tomcat服务器
      暂时配置两台Memcached服务器与两台后端服务器为同一服务器 

    ❷ 两台Tomcat服务器配置 关键配置
      到此网站下载五个包
        https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration    代码托管站点
        https://repo1.maven.org/maven2/de/javakaffee/msm/
        https://repo1.maven.org/maven2/net/spy/spymemcached/
        https://repo1.maven.org/maven2/javolution/javolution/5.5.1/
            memcached-session-manager-2.3.2.jar
            memcached-session-manager-tc8-2.3.2.jar
            msm-javolution-serializer-2.1.1.jar
            spymemcached-2.12.3.jar
            javolution-5.5.1.jar
        # cd /usr/local/tomcat/lib
        # rz                      \\ 五个包 导入到此目录下   对于编译安装的Tomcat
        # vim /usr/local/tomcat/conf/server.xml
            <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"   \\ <Host 下 <Context 下 添加
                memcachedNodes="n1:192.168.10.10:11211,n2:192.168.10.13:11211"          \\ 两个memcached服务器
                failoverNodes="n1"                                                       \\ n1 n2 为memcached随便起的名字
                requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
                transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
            />
        # catalina.sh configtest
        # catalina.sh start          \\ 访问 192.168.10.10 测试

    ❸ 两台Memcached 服务器配置         \\ 仅仅为此实验使用 关于Memcached详细资料参见 相关章节
        # yum install memcached
        # systemctl restart memcached
        # netstat -tunlp                 \\ tcp udp 的11211端口都被监听
        # memcached-tool 127.0.0.1        \\ 显示 工作状态信息      配合 访问 192.168.10.10 测试



JVM java虚拟机
    ❶ 性能监控工具

        ❶ 垃圾回收器:
            新生代回收: Minor GC
            老年代回收: Major GC (FULL GC)

        ❷ 堆内存空间的调整参数
            -Xmx: 新生代和老年代总共可用的最大空间
            -Xms: 二者初始空间
            -XX:NewSize 新生代初始空间
            -XX:MaxNewSize 新生代最大空间
            -XX:MaxPermSize 持久代最大空间
            -XX:PermSize 持久代初始空间

        ❸ 调整tomcat虚拟机 java虚拟机 内存大小
            CATALINA_OPTS   仅对启动运行tomcat实例的java虚拟机有效
            JAVA_OPTS       对本机上的所有java虚拟机有效
            # export CATALINA_OPTS="-Xmx256m"                   \\ 待测试

        ❹ 问题
            OutOfMemoryError 内存不足
            内存泄漏
            线程死锁
            锁竞争(lock Contention)
            Java消耗过多的CPU

        ❺ 工具
            jps  (java virtual machine process status tool)   jps主要监控jvm进程状态信息
                # yum install java-1.8.0-openjdk-devel      \\ 此包有jps命令
                # jps                       \\ 显示当前主机 运行的所有java进程
                    101746 Bootstrap
                    36086 Jps
                # jps 101746               \\ 查看某一进程
                # jps -m -l -v              \\ 显示启动这一java虚拟机的类是什么  或 程序是什么
                    -m 输出传入main方法的函数
                    -l 类型 程序名 显示main类或jar的完全限定名称 
                    -v 显示启动此java虚拟机传递的参数

            jstack 查看某个java进程内的线程堆栈信息
                # jstack 101746              \\ 可以java进程 内存分配等情况 用于发现问题 可给程序员排错
                    -l 输出 完整的锁信息        \\ 到底是哪段代码产生了锁 导致了问题 做程序调优
                    -m 混合模式 即会输出java堆栈及C/C++堆栈信息
            jmap
                # jmap 101746         \\ 查看堆 内存  哪个堆占用哪段内存
                    -heap 详细堆内存空间使用状态信息
                    -histo:live 详细显示出每一个java堆的内存对象
            jhat
                # jhat 101746           \\ 堆内存 分析工具
            jstat
                # jstat -options        \\ 查看有哪些选项
                # jstat -gc 101746       \\ 查看垃圾回收器的相关内容 内存相关统计信息
                    S0C S1C S0U S1U
                    C 表示容量
                    U 表示已用量
                    S 表示 存活区
                    EC EU eden伊甸园 区域的容量和已用量
                    OC OU     O老年代区
                    PC PU     P持久代区
                    YGC YGT   Y新生代的GC次数和耗时
                    FGC FGCT  老年代的GC次数和耗时
                    GCT       GC总耗时
                    GC 主要做了清理对象,整理内存的工作。Java堆分为新生代和老年代,采用了不同的回收方式。
            jconsole
                # jconsole       \\ 图形化工具 需要windos安装相应程序 查看内存相关参数


网络工具
    tcpdump  网络嗅探器   嗅探网络报文
    nc       tcp和udp连接和监听的工具 可以扮演浏览器 扮演web服务器 扮演网络文件传输工具 功能强大 黑客工具 网络中的瑞士军刀
    nmap     端口扫描器 探测   
    ncat     由nmap包提供 山寨版nc
    混杂模式  promisc  无论它们传输的报文目标mac是不是本机都给它拿过来

    ① tcpdump
        -i   接口
        -w   保存至文件中
        -A   仅ASCII码格式显示
        -X   仅十六进制和ASCII码格式显示
        -XX  仅显示链路层的首部信息
        -v   显示详细信息
        -vv  更详细信息
        -r   读取文件 进行分析 配合-w使用

        # tcpdump -i ens33                   \\ 在ens33上的所有通信
        # tcpdump -i ens33 tcp dst port 80    \\ tcp协议目标端口是80 
        # tcpdump -i ens33 tcp port 80         \\ 源端口或目标端口是80
        # tcpdump -i ens33 host 192.168.10.13   \\ 抓取和主机192.168.10.1之间的通信
        # tcpdump -i ens33 host 192.168.10.10 and host 192.168.10.13  \\ 抓取两个主机之间的通信 使用and
        # tcpdump -i ens33 host 192.168.10.10 or host 192.168.10.13    \\ 抓取两个主机的通信 使用or
        # tcpdump -i ens33 host 192.168.10.12 and \(192.168.10.10 or 192.168.10.13\)  \\ 抓取 10.12 和 这两个主机任何一个通信的包
            host            主机
            dst             目标
            port            端口
            tcp             tcp协议
            src             源
            src and dst     目标和源

    ② tshark     抓包工具

    ③ wireshark  最好用的网络抓包工具 非常强大
        # yum install wireshark
        # yum install wireshark-gnome        \\ 图形化工具

    ④ nc/ncat
        # yum install nmap-ncat

        ❶ 传输文件 
            # nc -l 2233 > /data/soft/a.png           \\ 服务器 接收文件 临时端监听2233端口 等待a.png文件的传输   只执行一次传输
            # nc 192.168.10.12 2233 < /data/vpn.png    \\ 客户端 传递文件 传递给服务器端 vpn.png 文件 端口随便 无需加密解密
                # nc -l 2233 < /data/soft/a.png         \\ 服务器 传递文件  最好使用 上一种
                # nc 192.168.10.12 2233 > /data/b.png    \\ 客户端 接收文件

        ❷ 传输文件夹
            # nc -l 2233 | tar zxvf -             \\ 服务端 接收文件 在解打包 管道后面必须是 - 不能是其他文件名
            # tar cfz - * | nc 192.168.10.12 2233  \\ 客户端 发送文件 打包当前文件夹所有文件 发送

        ❸ nc扫描器   有问题 需要重新找资料

        ❹ 聊天
            # nc -l 2233             \\ 服务器端 监听端口
            # nc 192.168.10.12 2233   \\ 客户端  连接端口  打字即可

            -s 源ip

    ⑤ # ps -ef | grep java