Linux服务篇--tomcat

本章概要

  • 软件架构模式
  • Tomcat相关介绍
  • Tomcat安装部署
  • Tomcat配置文件介绍
  • Tomcat相关配置
  • Tomcat常用架构介绍和实现
  • Tomcat集群实现会话保持
  • Tomcat优化设置

1、软件架构模式

  • 软件架构模式
    分层架构:不适用于大规模应用程序
      表现层
      业务层
      持久层
      数据库层
    事件驱动架构:分布式异步架构模式
      可应用于大规模的应用程序
      高度解耦
    微内核架构:即插件式架构
      是提供操作系统核心功能的内核的精简版本,它设计成在很小的内存空间内增加移植性,提供模块化设计,以使用户安装不同的接口
      模块化设计,由两类组件组成
      核心系统
      插件模块
    微服务架构:
      架构方式:
        API REST-based 小规模自包含服务
        application REST-based 较大规模
        中心化消息
    基于空间的架构:
      云架构
      云原生应用程序

2、Tomcat相关介绍

  • tomcat特性
      提供了jsp程序运行时的运行环境
      能够实现对代码的部署和发布,其本身并不对外提供服务
      tomcat上运行的代码程序才是解析客户端请求并作出响应的主体
  • 如何实现代码可移植性,抹除底层的差异
      pvm(python virtual machine) python虚拟机
      jvm(java virtual machine) java虚拟机
  • webapp容器
      tomcat ASF
      jetty 较高的技术支撑能力
      resin 开源对象:教育类。用于商业类需要授权
      jboss 被红帽收购
      webshpere,weblogic IBM
  • tomcat
      java程序,java语言开发
      为了运行其他java程序(jsp)而编写
      jsp java server page
        java编程语言环境中专用于开发服务器页面的类库
  • 运行环境介绍
      c语言更接近底层环境,因此适合开发系统级程序
      java编程语言,应用编程语言,适合构建大型企业级程序
      java虚拟机与底层联系并不密切,因此适用于开发应用程序
        jdk:java dk java开发工具箱
        主要组成部分:开发工具,调试工具,运行环境
          运行环境的核心部分:JRE
            JRE的核心部分:JVM java虚拟机
        openjdk 开源,社区版jdk
    总结:
      jdk提供了开发工具,调试工具,运行环境;jre提供运行环境和运行java所需调用的库,即jvm和标准库组成;而jvm只负责提供底层运行环境。
      java代码在jvm底层环境中运行,运行时需要调用jre提供的各种类库才能实现各种功能,而jdk则可以通过开发工具和调试工具对java代码进行修改和调试。
  • java版本
      Java2SE java标准版
      Java2EE java企业版(增强版)
  • 版本命名
      JDK与java对应关系
        java SE8是指jdk1.8
      JDK命名:
        JDK 1.8.1 —> JDK 8U1
        JDK 1.8.2 —> JSK 8U2
  • 社区版本:
      OpenJDK 7 社区版
        衍生出三个版本:
        OpenJDK 6
        OpenJDK 7
        OpenJDK 8
  • java运行模式:
      服务端模式
      客户端模式
      混合模式
  • 常用架构
    AT:Apache+Tomcat
    NT:Nginx+Tocat
      客户端----反向代理(nginx,静态资源)----tomcat(动态资源)
      httpd本地处理静态资源请求,tomcat处理动态资源请求
      tomcat支持的协议:http,ajp

3、Tomcat安装部署

  • 由于tomcat是基于java开发的应用程序,因此安装部署tomcat需要先安装JDK
  • JDK版本
      Oracle JDK 1.8版本不再维护,后续版本需要付费
      OpenJDK 开源,免费
3.1 JDK安装

Oracle JDK的安装

  • 下载Oracle JDK
    下载Oracle JDK安装包,使用rpm -ivh命令安装即可
    默认安装目录:/usr/java/
    bin:各种配置工具
    lib:java类库,开发组件
    jre:提供运行时需要的基本类库环境
    tomcat运行时会通过环境变量JAVA_HOME和JAVA_BASE寻找java,因此需要声明java环境变量
  • 声明java环境变量
vim /etc/profile.d/java.sh  
JAVA_HOME=/usr/java/latest  
PATH=$JAVA_HOME/bin:$PATH  
export JAVA_HOME PATH  

openjdk的安装

  • 包名:java-1.8.0-openjdk-devel 开发版
  • 使用yum安装
      yum -y install java-1.8.0-openjdk-devel
  • alternatives是当centos系统中openjdk多版本共存时,设定默认使用的版本,即更改指定openjdk的版本软链接/etc/alternatives/java即可
[root@centos7 ~]# which java
/usr/bin/java
[root@centos7 ~]# ll /usr/bin/java         
lrwxrwxrwx 1 root root 22 Nov 21 09:42 /usr/bin/java -> /etc/alternatives/java
[root@centos7 ~]# ll /etc/alternatives/java
lrwxrwxrwx 1 root root 73 Nov 21 09:42 /etc/alternatives/java -> /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-0.el7_5.x86_64/jre/bin/java
3.2 Tomcat安装

二进制源码安装

  • 下载二进制源码包
    官网地址:tomcat.apahe.org
    二进制源码包:apache-tomcat-8.5.35.tar.gz
  • 解压并安装
    tar xf apache-tomcat-8.5.35.tar.gz -C /usr/local
    系统默认寻找tomcat目录,因此需要创建软链接,把解压后的软件包链接至tomcat
    cd /usr/local
    创建软链接
      ln -s apache-tomcat-8.5.35/ tomcat
  • tomcat的目录结构
      bin:脚本,及启动时用到的类;
        catalina.sh 统一的脚本
        bootstrap.jar:tomcat基于jvm运行,因此启动tomcat时需要先启动jvm
        startup.sh 启动tomcat脚本
        shutdown.sh 关闭tomcat脚本
        configtest.sh 配置文件语法测试脚本
        version.sh 查看tomcat版本的脚本
      conf:配置文件目录;
      lib:库文件,Java类库,jar;
      logs:日志文件目录;
      temp:临时文件目录;
      webapps:webapp的默认目录;web网页的存放目录,
        ROOT:主站目录固定存放位置
      work:工作目录;
  • 权限设置:
    创建普通用户tomcat
      useradd tomcat
        脚本启动时不推荐使用root用户启动,而是用普通用户如tomcat用户启动
    更改用户权限
      cd /usr/local/tomcat
      chown -R :tomcat ./*
        使用tomcat用户启动时,要更改普通用户tomcat对该目录所有文件的权限,即更改tomcat目录的属组
    tomcat用户对logs,temp,work目录还要写入数据,因此要使tomcat用户对logs,temp,work目录具有写权限
      方法1:可以使用acl设置访问控制权限
      方法2:更改logs,temp,work目录的属主
      chown -R tomcat logs/ temp/ work/
    另外,tomcat用户还需要读取配置文件,否则无法启动tomcat。因此要对conf/具有读权限,因此需要更改conf/的读权限
      chmod g+rx conf/ 对conf目录具有读和执行权限
      chmod g+r conf/* 对conf目录下的配置文件具有读权限
  • 配置环境变量,方便启动tomcat
      vim /etc/profile.d/tomcat.sh
      CATALINA_BASE=/usr/local/tomcat
      PATH= C A T A L I N A B A S E / b i n : CATALINA_BASE/bin: CATALINABASE/bin:PATH
      export CATALINA_BASE PATH
  • 启动tomcat
      su - tomcat 这种切换方式,tomcat用户会读取与自己的相关配置
      catalina.sh start 启动tomcat
        start 在当前终端运行
        run 剥离当前终端运行,类似于在后端运行
      startup.sh 启用该脚本也可以启动tomcat
  • 启动tomcat后,默认监听8080,8005,8009
  • 访问时,需要登录 ip地址:8080即可,如本机部署tomcat ip地址为192.168.32.133,则访问地址为:192.168.32.133:8080

YUM安装Tomcat

  • 查看tomcat相关程序包
    yum list tomcat* 查看与tomcat相关的软件包,根据需要安装
  • 使用yum安装相关程序报
    yum install tomcat tomcat-docs-webapp tomcat-webapps tomcat-admin-webapps
      tomcat-docs-webapp 说明文档相关软件包
      tomcat-webapps 提供网站默认主页
      tomcat-admin-webapps 提供管理应用程序
  • 启动tomcat服务
      systemctl start tomcat
  • 登录:
      当前主机为192.168.32.131
      登录:192.168.32.131:8080
  • CGI协议
      servlet,applet
      jsp --> jasper
    注意:真正负责运行的是servlet,而jsp只是运行过程中进行代码转换的一个环节
  • JSP
      是专用于页面显示的程序
      可以把java代码嵌入到html中,将java代码打上特殊标记,tomcat引擎能够自动识别标记,带有该标记的就是java代码,不带有该标记的自动转换为java语言的输出语句
      即jsp负责分析页面文件,自动识别带体验标记的内容,能把html语句(不带有标记的内容)转换为java代码
      jsp类似于httpd中的php程序,php能够自动识别php代码,输出执行后的结构,并将html语句自动转换为php语句输出出来,这样输出以后,浏览器能够识别html语句并显示出来
  • 文件转换过程:
    .jsp -> jasper -> java -> javac ->.class
    jasper jsp编译器
    javac java编译器
    .jsp到java的过程会被保存至work目录中,这就是work目录的作用
[root@centos7 tomcat]# tree work/
work/
└── Catalina
    └── localhost
        ├── docs
        ├── examples
        ├── host-manager
        ├── manager
        └── ROOT
            └── org
                └── apache
                    └── jsp
                        ├── index_jsp.class
                        └── index_jsp.java

注意:真正负责运行的是servlet,而jsp只是运行过程中进行代码转换的一个环节

tomcat内部关键的类

  • tomcat内部关键的类
server {
	service {
		connector{}
		engine {
			host {}
			host {
				context
			}
		}
	}
}
  • 类的详细介绍:
    server 一个实例,内部存在一个service
    service 使用一到多个connector连接至engine
    connector 用于连接egine,一个connector只属于一个engine,但一个engine可以有多个connector
      connector连接器监听和接收来自客户端或反代的请求
      http连接器
        监听8080端口,负责建立HTTP连接。在通过浏览器访问Tomcat服务器的Web应用时,使用的就是这个连接器。  
      ajp连接器
        监听8009端口,负责和其他的HTTP服务器建立连接。在把Tomcat与其他HTTP服务器集成时,就需要用到这个连接器
      注意:建议ajp连接器监听在8080端口,不建议监听8009管理端口,防止外部通过8009端口连接至内部
    engine 内部可以存在多个host(虚拟主机)
    host 通过主机名区分host,host内部可以有一到多个context
    context 定义location与本地文件系统路径的对应关系以及其访问权限等相关功能
  • tomcat三种端口8080,8005,8009
      8080 负责建立HTTP连接,通过浏览器访问tomcat服务器使用该端口
      8005 负责监听关闭tomcat请求
      8009 负责和其他的HTTP服务器建立连接。在把Tomcat与其他HTTP服务器集成时,就需要用到这个连接器

4、Tomcat配置文件介绍

配置文件介绍

  • server.xml 主配置文件,定义tomcat以何种结构运行
  • web.xml 用于定义webapp默认的配置文件。
      java程序部署时需要类加载器把程序所需的库文件加载到jvm上,然后才能运行;而有些程序没有此类配置文件定义加载哪些库文件,web.xml文件就是为这些程序提供的默认配置文件
  • context.xml 用于webapp的专用的配置文件
      每一个独立的应用程序在部署时,应该通过哪个url访问位于当前主机哪个磁盘文件路径下的哪些网页资源,context就是用于定义他们之间的映射关系
  • tomcat-users.xml 用户认证的账号和密码文件
  • catalina.policy 当使用-security选项启动tomcat时,用于为tomcat设置安全策略;
  • catalina.properties java属性的定义文件,用于设定类加载器路径,以及一些与JVM调优相关参数
  • logging.porperties 日志系统相关的配置
  • 常用文件
      server.xml
      tomcat-users.xml
      tomcat.conf
  • 组件类型:
      顶级组件:server
      服务类组件:service
      连接器组件:http,https.ajp
      容器类组件:engine,host,context
      被嵌套类组件:valve(过滤器),logger(日志相关),realm(认证相关),loader,manager
      集群类组件:listener(侦听器),cluster
  • webapp的组织结构
      /:webapp的根目录
        index.jsp,index.html:主页
        WEB-INF/:当前webapp的私有资源路径(目录),只要以WEB-INF命名,客户端将无法访问该目录下的所有文件
        META-INF/:类似于WEB-INF/
        classes/:类文件,当前webapp所提供的类
        lib/:类文件,当前webapp所提供的类,被打包为jar格式
  • 为了便于开发的项目文档便于复制下载,因此需要对文档或文件进行归档压缩
  • webapp的归档格式
      .war:webapp的ar文件,web应用程序归档文件
      .jar:EJB的类打包文件,企业级应用适配器
      .rar:资源适配器类打包文件
      .ear:企业级webapp
5、Tomcat相关配置

Tomcat部署方式

  • 部署(deploy)webapp的相关操作:
      deploy:将webapp的源文件放置于目标目录(网页程序文件存放目录),配置tomcat服务器能够基于web.xml和context.xml文件中定义的路径来访问此webapp;将其特有的类和依赖的类通过class loader装载至JVM;
        部署有两种方式:
          自动部署:auto deploy
          手动部署:
            冷部署:把webapp复制到指定的位置,而后才启动tomcat;即随tomcat的启动而部署
            热部署:在不停止tomcat的前提下进行部署;
        部署工具:manager、ant脚本、tcd(tomcat client deployer)等;
      undeploy:反部署,停止webapp,并从tomcat实例上卸载webapp;
      start:启动处于停止状态的webapp;
      stop:停止webapp,不再向用户提供服务;其类依然在jvm上;
      redeploy:重新部署;
  • 手动提供一测试类应用,并冷部署:
    创建网页文件
      mkidr -pv /usr/local/tomcat/webapps/test/{classes,lib,WEB-INF}
    创建文件/usr/local/tomcat/webapps/test/index.jsp
<%@ page language="java" %>
<%@ page import="java.util.*" %>
<html>
	<head>
		<title>Test Page</title>
	</head>
	<body>
		<% out.println("hello world");
		%>
	</body>
</html>		

注意:在部署时,推荐把网页文件复制到webapps目录下并创建软链接,把软链接为网站家目录,这样方便网站的发布和回滚

Tomcat认证相关配置

  • tomcat的两个管理应用:
      manager:管理webapps应用程序
      host-manager:管理虚拟主机
  • ManagerApp认证配置:
    示例:以rpm安装为例
	vim /etc/tomcat/tomcat-user.xml
	<role rolename="manager-gui"/>   #角色只能单独定义
	<role rolename="manager-script"/>
	<user username="tomcat" password="centos123456" roles="manager-gui,manager-script"/>  #用户可以多个定义
	重启服务
	systemctl  restart  tomcat

允许访问ManagerAPP的用户为以下四种:
  manager-gui - allows access to the HTML GUI and the status pages
  manager-script - allows access to the text interface and the status pages
  manager-jmx - allows access to the JMX proxy and the status pages
  manager-status - allows access to the status pages only
  注意:网页主站页面即/etc/tomcat/webapps/ROOT目录

  • Host-Manager认证配置:
    示例:以rpm安装为例
	vim /etc/tomcat/tomcat-user.xml
	<role rolename="admin-gui"/>   #角色只能单独定义
	<user username="tomcat" password="centos123456" roles="manager-gui,manager-script,admin-gui"/>  #用户可以多个定义
	重启服务
	systemctl  restart  tomcat

允许访问Host-Manager的用户为以下两种:
  admin-gui - allows access to the HTML GUI
  admin-script - allows access to the text interface

  • 一个主机上可以运行多个tomcat进程,每一个tomcat进程要有自己的server配置。
  • tomcat中有两个重要的环境变量:CATALINA_HOME,CATALINA_BASE,一个对每个实例作为根,一个对tomcat程序的安装作为根。tomcat只需安装一次,就可以运行多个server实例,每个实例要有自己专用的配置文件和启动方法

tomcat的常用组件配置

  • Server:代表tomcat instance,即表现出的一个java进程;监听在8005端口,只接收“SHUTDOWN”。各server监听的端口不能相同,因此,在同一物理主机启动多个实例时,需要修改其监听端口为不同的端口;
      server默认监听本机地址127.0.0.1,8005是管理接口,它只接收一个字串作为命令,即SHUTDOWN,用于关闭当前tomcat进程。因此可以通过连接127.0.0.1:8005发送SHUTDOWN指令关闭本机的tomcat进程
      为了安全起见,要么关闭监听端口,要么把SHUTDOWM指令更改为一个随机字串
    示例:
	[root@centos7 ~]# openssl rand -base64 16
	JvAYxww7H0JTuDZ07QEOCQ==
	vim /etc/tomcat/server.xml
	<Server port="8005" shutdown="JvAYxww7H0JTuDZ07QEOCQ">
重启tomcat服务
注意:为了确保server.xml中的“SHUTDOWN”指令不被其他用户看到,要更改server.xml文件的权限:即去除其他用户的读权限
	chmod o= server.xml 
  • Service:用于实现将一个或多个connector组件关联至一个engine组件;
  • Connector组件:端点
      用于定义tomcat监听的地址和端口,不属于任何host,而是属于整个tomcat,因此在tomcat中使用虚拟主机只能使用基于主机名的虚拟主机,因为任何端口和套接字都属于所有主机
      负责接收请求,常见的有三类http/https/ajp;
      进入tomcat的请求可分为两类:
        (1) standalone : 请求来自于客户端浏览器;
        (2) 由其它的web server反代:来自前端的反代服务器;
        nginx --> http connector --> tomcat
        httpd(proxy_http_module) --> http connector --> tomcat
        httpd(proxy_ajp_module) --> ajp connector --> tomcat
        httpd(mod_jk) --> ajp connector --> tomcat 非标准实现
      属性:
        port=“8080”
        protocol=“HTTP/1.1”
        connectionTimeout=“20000” 单位为ms,即20s
        address:监听的IP地址;默认为本机所有可用地址;
        maxThreads:最大并发连接数,默认为200;
        enableLookups:是否启用DNS查询功能;即关闭DNS反向解析
        acceptCount:等待队列的最大长度;即后援队列数量
        secure: 是否启动https协议
        sslProtocol: 指定https协议版本,证书,私钥文件
      配置文件server.xml中监听8080配置文件
         #默认重定向到8443,8443端口默认没有开启
        自定义添加监听端口10080
         #关闭DNS反向解析
        注意:属性之间使用空白字符隔开
        重启服务配置文件才会生效
  • Engine组件:Servlet实例,即servlet引擎,其内部可以一个或多个host组件来定义站点; 通常需要通过defaultHost属性来定义默认的虚拟主机;
      属性:
        name=
        defaultHost=“localhost”
        jvmRoute= #基于cookie会话绑定时赋予当前engine唯一的标识符,因此在同一集群中不同的engine,jvm也不一样。如果没有配置集群,也没有配置基于session sticky,jvmRoute就无需配置
  • Host组件:位于engine内部用于接收请求并进行相应处理的主机或虚拟主机
      基于主机名的虚拟主机
    示例:
 <Host name="localhost"  appBase="webapps"
	unpackWARs="true" autoDeploy="true">
</Host>

任何由连接器转给此engine的请求当中,engine会判断请求报文首部的host首部的值与哪个内部的host主机的hostname一致,用户的请求就会路由至哪个host;如果没有任何一致的地方,就默认转给默认的host主机
  对每一个虚拟主机来讲,还应该定义网页文件根目录,注意:这里要使用特殊的符号,即appBase为网站家目录
  如果用户部署的时候,扔进主机内部一个没有展开的war文件,要对其进行自动展开,即unpackWARs=true,
  autoDeploy="true"是指是否自动部署,注意:在生产环境中,为了安全起见,不建议启动自动部署
  注意:appBase="webapps"使用的是相对路径,相对于CATALINA_BASE,即/var/lib/tomcat或/usr/share/tomcat

  • Webapp ARchives
      常用属性说明:
        (1) appBase:此Host的webapps的默认存放目录,即存放网页文件的家目录,指存放非归档的web应用程序的目录或归档的WAR文件目录路径;可以使用基于$CATALINA_BASE变量所定义的路径的相对路径;
        (2) autoDeploy:在Tomcat处于运行状态时,将某webapp放置于appBase所定义的目录中时,是否自动将其部署至tomcat;
    示例:自定义虚拟主机
<Host name="test1.magedu.com" appBase="/data/webapps/myapp" unpackWARs="true" autoDeploy="true">
</Host>
注意:如果内部不再嵌套其他组件,可以进行自封装,即在语句最后直接机上斜线;否则,去掉结尾的斜线/,另起一行加上</Host>进行封装
此时,启用的web页面默认路径为/data/webapps/myapp,即访问test1.magedu.com相当于访问/data/webapps/myapp下的主页面
	# mkdir -pv /data/webapps
	# mkdir -pv /data/webapps/ROOT/{lib,classes,WEB-INF}
	vim /data/webapps/ROOT/index.jsp    #创建网页文件index.jsp
	<h1>This is TestPage!<h1>
	[root@centos7 myapp]# tree /data/webapps/myapp
	.
	├── ROOT
	│   ├── class
	│   ├── index.jsp
	│   ├── lib
	│   └── WEB-INF
	└── testapp
	    ├── class
	    ├── index.jsp
	    ├── lib
	    └── WEB-INF
注意:这里的ROOT属于网站主目录,访问时只需输入:test1.magedu.com:8080;而testapp属于非网站主目录,要想访问testapp目录下的网页,需要在访问的url中加上该目录,如:test1.magedu.com:8080/testapp
另外,网页文件index.jsp存放位置不同:配置文件中中没有定义context组件时,网站主目录中网页文件index.jsp必须存放在ROOT目录下,如:/data/webapps/myapp/ROOT/index.jsp;
非网站主目录中网页文件index.jsp只需存放在非网站主目录下即可,非网站主目录下不需要ROOT目录,如:/data/webapps/myapp/testapp/index.jsp。

示例:通过context组件,实现访问位于非网站主目录下的网页文件

创建hiapps目录
	mkdir -pv /hiapps/hiapp/{lib,classes,WEB-INF}      
创建网页文件index.jsp
	vim /hiapps/hiapp/index.jsp        
	<h1>hello tomcat!<h1>
定义context路径
	vim /etc/tomcat/server.xml     
		<Host name="test1.magedu.com" appBase="/data/webapps/myapp" unpackWARs="true" autoDeploy="true">
			<Context path="/hiapp" docBase="/hiapps/hiapp" reloadable=""/>
		</Host>
通过访问test1.magedu.com:8080/hiapp访问/hiapps/hiapp网页文件,即实现了访问不在appBase(/data/webapps/myapp)路径下的文件
注意:不在默认路径/data/webapps/myapp下的其他访问路径目录/hiapps/hiapp下也不需要ROOT目录
  • Context组件:
      类似于http中路径别名,通过定义context,可以访问位于非网站主目录下的网页文件
    示例:
<Context path="/PATH" docBase="/PATH/TO/SOMEDIR" reloadable=""/>
	Context url路径
	docBase 网页文件路径	
	reloadable  是否支持自动重载
  • 综合示例:
<Host name="node1.magedu.com" appBase="/web/apps" unpackWARs="true" autoDeploy="true">
	<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
		prefix="node1_access" suffix=".log"
		pattern="%h %l %u %t "%r" %s %b" />
	<Context path="/test" docBase="test" reloadable="">
		<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
		prefix="node1_test_access_" suffix=".log"
		pattern="%h %l %u %t "%r" %s %b" />
	</Context>
</Host>		
  • Valve组件:
      <Valve className=“org.apache.catalina.valves.AccessLogValve” directory=“logs”
      prefix=“localhost_access_log” suffix=".txt"
      pattern="%h %l %u %t “%r” %s %b" /> #注意:"用来表示引号,在该文件中引号有特殊含义,因此使用"表示引号
    tomcat日志文件路径:/var/log/tomcat/
    官方日志格式说明:
      https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/valves/AccessLogValve.html
    Valve存在多种类型:
定义访问日志:org.apache.catalina.valves.AccessLogValve  
定义访问控制:org.apache.catalina.valves.RemoteAddrValve   
CIDR表示法,拒绝172.16.100.67  
<Valve className="org.apache.catalina.valves.RemoteAddrValve" deny="172.16.100.67/16"/>  
基于主机名进行控制,需要对.进行转义,即172\.16\.100\.67  
<Valve className="org.apache.catalina.valves.RemoteAddrValve" deny="172\.16\.100\.67"/>  

6、Tomcat常用架构介绍和实现

LNMT架构

  • LNMT:Linux Nginx MySQL Tomcat
      Client (http) --> nginx (reverse proxy)(http) --> tomcat (http connector)
      配置:
		location / {
			proxy_pass http://tc1.magedu.com:8080;
		}
		
		location ~* \.(jsp|do)$ {
			proxy_pass http://tc1.magedu.com:8080;
		}

示例:nginx反代tomcat

		location / {
                root /usr/share/tomcat/webapps/ROOT;
        }

        location ~* \.(jsp|do)$ {
                proxy_pass http://127.0.0.1:8080;
        }

LAMT架构

  • LAMT:Linux Apache(httpd) MySQL Tomcat
      httpd的代理模块:
        proxy_module
        proxy_http_module:适配http协议客户端;
        proxy_ajp_module:适配ajp协议客户端;
  • LAMT结构类型
        Client (http) --> httpd (proxy_http_module)(http) --> tomcat (http connector)
        Client (http) --> httpd (proxy_ajp_module)(ajp) --> tomcat (ajp connector)
        Client (http) --> httpd (mod_jk)(ajp) --> tomcat (ajp connector)
  • proxy_http_module代理配置:(把网站整体进行反向代理)
<VirtualHost *:80>
	ServerName      tc1.magedu.com
	ProxyRequests Off
	ProxyVia        On        #在响应报文中添加Via首部,指明是由谁代理发过去的
	ProxyPreserveHost On      #指是否保留客户端请求时的主机头,以根据主机头响应后端不同的虚拟主机
	<Proxy *>
		Require all granted
	</Proxy>
	ProxyPass / http://tc1.magedu.com:8080/
	ProxyPassReverse / http://tc1.magedu.com:8080/ 
	<Location />
		Require all granted
	</Location>
</VirtualHost>

<LocationMatch "\.(jsp|do)$>
    ProxyPass / http://tc1.magedu.com:8080/
</LocationMatch>
	当后端tomcat存在两个虚拟主机如node01.magedu.com和www.magedu.com,对后端反代时,一个proxypass只能反代给一个后端的虚拟主机,要想对后端两个虚拟主机进行反代,有两个方法:
		(1)前端反代服务器设置两个虚拟主机分别对不同虚拟主机进行反代
		(2)在反向代理服务器发送给后端虚拟主机的请求报文头部中添加不同的主机头,此时反代的路径不重要,重要的是报文首部中附加的主机头信息
		注意:实现第二种方法的指令就是ProxyPreserveHost,是指是否保留客户端请求时的主机头

本机实验示例:

[root@centos7 ~]# vim /etc/httpd/conf.d/http-tomcat.conf
<VirtualHost *:80>
        ServerName      test1.magedu.com
        ProxyRequests Off
        ProxyVia        On
        ProxyPreserveHost On
        <Proxy *>
                Require all granted
        </Proxy>
        ProxyPass / http://127.0.0.1:8080/
        ProxyPassReverse / http://127.0.0.1:8080/     
        <Location />
                Require all granted
        </Location>
</VirtualHost>
重启httpd服务
systemctl restart httpd
在客户端192.168.32.128进行测试:
	访问192.16.32.131时为主站目录
	访问test1.magedu.com时为另外一个虚拟主机
这就是ProxyPreserveHost指令开启后的作用,基于不同的主机名反代给后端不同虚拟主机
	注意:客户端配置dns解析
  • proxy_ajp_module代理配置:
<VirtualHost *:80>
	ServerName      tc1.magedu.com
	ProxyRequests Off
	ProxyVia        On
	ProxyPreserveHost On
	<Proxy *>
		Require all granted
	</Proxy>
		ProxyPass / ajp://tc1.magedu.com:8009/ 
		ProxyPassReverse / ajp://tc1.magedu.com:8009/ 
	<Location />
		Require all granted
	</Location>
</VirtualHost>

本机实验示例:

[root@centos7 conf.d]# vim ajp-tomcat.conf
Listen 9090
<VirtualHost *:9090>     #防止地址冲突,使用9090端口
        ServerName      test1.magedu.com
        ProxyRequests Off
        ProxyVia        On
        ProxyPreserveHost On
        <Proxy *>
                Require all granted
        </Proxy>
        ProxyPass / ajp://127.0.0.1:8009/
        ProxyPassReverse / ajp://127.0.0.1:8009/
        <Location />
                Require all granted
        </Location>
</VirtualHost>

7、实现Tomcat会话保持

会话保持

  • 会话保持
    (1) session sticky
      source_ip
        nginx: ip_hash
        haproxy: source
        lvs: sh
      cookie:
        nginx:hash
        haproxy: cookie
    (2) session cluster:delta session manager
      即session replication
      通过多播通信的信道,把session信息传递给同一集群的其他主机
      在大规模集群中,多播信道会充满多播信息,形成拥塞,造成延迟
    (3) session server:redis(store), memcached(cache)
      server是单点,需要做冗余
        存储设备具有主从复制机制
        依靠前端进行备份,在主备server上写两份session信息
          双写 double write
          对数据进行周期性备份

Tomcat集群

  • Tomcat Cluster(session)
      (1) session sticky
      (2) session cluster
        tomcat delta manager
      (3) session server
        memcached
  • Tomcat Cluster
      (1) httpd + tomcat cluster
        httpd: mod_proxy, mod_proxy_http, mod_proxy_balancer
        tomcat cluster:http connector
      (2) httpd + tomcat cluster
        httpd: mod_proxy, mod_proxy_ajp, mod_proxy_balancer
        tomcat cluster:ajp connector
      (3) httpd + tomcat cluster
        httpd: mod_jk
        tomcat cluster:ajp connector
      (4) nginx + tomcat cluster
  • 基于http的httpd + tomcat cluster实现
<proxy balancer://tcsrvs>
	BalancerMember http://172.18.100.67:8080
	BalancerMember http://172.18.100.68:8080
	ProxySet lbmethod=byrequests    #指定调度算法
</Proxy>

<VirtualHost *:80>
	ServerName lb.magedu.com
	ProxyVia On
	ProxyRequests Off
	ProxyPreserveHost On
	<Proxy *>
		Require all granted
	</Proxy>
	ProxyPass / balancer://tcsrvs/
	ProxyPassReverse / balancer://tcsrvs/
	<Location />
		Require all granted
	</Location>
</VirtualHost>

BalancerMember介绍

  • BalancerMember [balancerurl] url [key=value [key=value …]]
      status: #人为设定后端服务器处于什么状态
        D: Worker is disabled and will not accept any requests. #拒绝任何请求
        S: Worker is administratively stopped. #强制使其处于不可用状态
        I: Worker is in ignore-errors mode and will always be considered available. #强制使其处于可用状态
        H: Worker is in hot-standby mode and will only be used if no other viable workers are available. #热备状态,即sorry server
        E: Worker is in an error state. #强制使其处于错误状态,即使状态检测为成功
        N: Worker is in drain mode and will only accept existing sticky sessions destined for itself and ignore all other requests. #排干模式,不再处理新请求,但已有请求仍然会被处理
      loadfactor:
        负载因子,即权重;
      lbmethod:
        Balancer load-balance method. Select the load-balancing scheduler method to use. Either byrequests, to perform weighted request counting; bytraffic, to perform weighted traffic byte count balancing; or bybusyness, to perform pending request balancing. The default is byrequests.
      stickysession #要不要做坏话粘滞,即要不要基于cookie绑定会话
        Balancer sticky session name. The value is usually set to something like JSESSIONID or PHPSESSIONID, and it depends on the backend application server that support sessions. If the backend application server uses different name for cookies and url encoded id (like servlet containers) use | to separate them. The first part is for the cookie the second for the path.
        Available in Apache HTTP Server 2.4.4 and later.
        基于balancer模块使用会话粘滞
7.1 基于session sticky的tomcat集群
  • 基于BalancerMember的会话粘性实现(http协议)
      Header add Set-Cookie “ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/” env=BALANCER_ROUTE_CHANGED
<proxy balancer://tcsrvs>
	BalancerMember http://172.18.100.67:8080 route=TomcatA loadfactor=1
	BalancerMember http://172.18.100.68:8080 route=TomcatB loadfactor=2
	ProxySet lbmethod=byrequests
	ProxySet stickysession=ROUTEID
</Proxy>

<VirtualHost *:80>
	ServerName lb.magedu.com
	ProxyVia On
	ProxyRequests Off
	ProxyPreserveHost On
	<Proxy *>
		Require all granted
	</Proxy>
	ProxyPass / balancer://tcsrvs/
	ProxyPassReverse / balancer://tcsrvs/
	<Location />
		Require all granted
	</Location>
</VirtualHost>
	
启用管理接口:
	<Location /balancer-manager>
		SetHandler balancer-manager
		ProxyPass !
		Require all granted
	</Location>

示例程序:

演示效果,在TomcatA上某context中(如/test),提供如下页面
<%@ page language="java" %>
<html>
	<head><title>TomcatA</title></head>
	<body>
		<h1><font color="red">TomcatA.magedu.com</font></h1>
		<table align="centre" border="1">
			<tr>
				<td>Session ID</td>
			<% session.setAttribute("magedu.com","magedu.com"); %>
				<td><%= session.getId() %></td>
			</tr>
			<tr>
				<td>Created on</td>
				<td><%= session.getCreationTime() %></td>
			</tr>
		</table>
	</body>
</html>

演示效果,在TomcatB上某context中(如/test),提供如下页面
<%@ page language="java" %>
<html>
	<head><title>TomcatB</title></head>
		<body>
		<h1><font color="blue">TomcatB.magedu.com</font></h1>
		<table align="centre" border="1">
			<tr>
				<td>Session ID</td>
			<% session.setAttribute("magedu.com","magedu.com"); %>
				<td><%= session.getId() %></td>
			</tr>
			<tr>
				<td>Created on</td>
				<td><%= session.getCreationTime() %></td>
			</tr>
		</table>
		</body>
</html>
  • 基于BalancerMember的会话粘性实现(ajp协议)
<proxy balancer://tcsrvs>
	BalancerMember ajp://172.18.100.67:8009
	BalancerMember ajp://172.18.100.68:8009
	ProxySet lbmethod=byrequests
</Proxy>

<VirtualHost *:80>
	ServerName lb.magedu.com
	ProxyVia On
	ProxyRequests Off
	ProxyPreserveHost On
	<Proxy *>
		Require all granted
	</Proxy>
	ProxyPass / balancer://tcsrvs/
	ProxyPassReverse / balancer://tcsrvs/
	<Location />
		Require all granted
	</Location>
	<Location /balancer-manager>
		SetHandler balancer-manager
		ProxyPass !
		Require all granted
	</Location>
</VirtualHost>
	保持会话的方式参考前一种方式。
  • LNMT示例:使用nginx实现tomcat反向代理,调用balancer模块
使用docker启用两个tomcat容器,使用nginx作为反向代理服务器
    docker run --name tc1 --hostname tc1.magedu.com -d --network bridge -v /data/tc1:/usr/local/tomcat/webapps/myapp tomcat:8.5-slim  #启用存储卷,把宿主机/data/tc1挂载到docker容器的网站子目录myapp下
    docker run --name tc2 --hostname tc2.magedu.com -d --network bridge -v /data/tc2:/usr/local/tomcat/webapps/myapp tomcat:8.5-slim  #启用存储卷,把宿主机/data/tc1挂载到docker容器的网站子目录myapp下
为t1制作网页文件
	mkdir /data/tc{1,2}
	cd /data/tc1
	mkdir -p lib class WEB-INF
	vim index.jsp
	<html>
	        <head><title>TomcatA</title></head>
	        <body>
	                <h1><font color="red">TomcatA.magedu.com</font></h1>
	                <table align="centre" border="1">
	                        <tr>
	                                <td>Session ID</td>
	                        <% session.setAttribute("magedu.com","magedu.com"); %>
	                                <td><%= session.getId() %></td>
	                        </tr>
	                        <tr>
	                                <td>Created on</td>
	                                <td><%= session.getCreationTime() %></td>
	                        </tr>
	                </table>
	        </body>
	</html>

为t2制作网页文件
	cd /data/tc2
	mkdir -p lib class WEB-INF
	vim index.jsp
	<html>
	        <head><title>TomcatA</title></head>
	        <body>
	                <h1><font color="red">TomcatB.magedu.com</font></h1>
	                <table align="centre" border="1">
	                        <tr>
	                                <td>Session ID</td>
	                        <% session.setAttribute("magedu.com","magedu.com"); %>
	                                <td><%= session.getId() %></td>
	                        </tr>
	                        <tr>
	                                <td>Created on</td>
	                                <td><%= session.getCreationTime() %></td>
	                        </tr>
	                </table>
	        </body>
	</html>

测试:
使用curl命令访问 
	curl http://172.17.0.2:8080/myapps     #自动连接docker0获取172.17.0.2
	curl http://172.17.0.3:8080/myapps
使用elinks访问
	elinks -dump http://172.17.0.2:8080/myapp/

配置nginx反向代理:
把某个目录反向代理到后端服务器
主配置文件中:
http {
    upstream tcsrvs {
        server 172.17.0.2:8080;
        server 172.17.0.3:8080;
    }

    server {
        listen       80 default_server;
        include /etc/nginx/default.d/\*.conf;

        location / {
                root /usr/share/html;
        }
        location /myapp/ {
                proxy_pass http://tcsrvs/myapp/;
        }

        location ~* \.(jsp|do)$ {
                proxy_pass http://127.0.0.1:8080;
        }
    ......
}
重启nginx服务
测试:在浏览器访问test1.magedu.com/myapp/

把整个网站代理向后端服务器
http {
    upstream tcsrvs {
        server 172.17.0.2:8080;
        server 172.17.0.3:8080;
    }

    server {
        listen       80 default_server;
        include /etc/nginx/default.d/\*.conf;

        location / {
                root /usr/share/html;
                proxy_pass http://tcsrvs/;
        }

        location ~* \.(jsp|do)$ {
                proxy_pass http://127.0.0.1:8080;
        }
    ......
}
重启nginx服务
测试:在浏览器访问主页:http://test1.magedu.com  
	访问myapp网页  http://test1.magedu.com/myapp/
  • LAMT示例:使用httpd实现tomcat反向代理,调用balancer模块
      balancer模块调用以下算法模块
        lbmethod_bybusyness_module (shared) 相当于lastconnection
        lbmethod_byrequests_module (shared) 相当于roundrobin
        lbmethod_bytraffic_module (shared) 根据后端服务器链接流量(链接繁忙程度)判断调度给哪个服务器
    (1)配置httpd作为反向代理服务器,使用http连接器,连接engine
	vim /etc/httpd/conf.d/http-tomcat.conf
		<proxy balancer://tcsrvs>
		        BalancerMember http://172.17.0.2:8080
		        BalancerMember http://172.17.0.3:8080
		        ProxySet lbmethod=byrequests    #调用算法模块
		</Proxy>

		<VirtualHost *:80>
		        ServerName      test1.magedu.com
		        ProxyRequests Off
		        ProxyVia        On
		        ProxyPreserveHost On
		        <Proxy *>
		                Require all granted
		        </Proxy>
		        ProxyPass / balancer://tcsrvs/       #使用balancer格式指定代理服务器
		        ProxyPassReverse / balancer://tcsrvs/    #使用balancer格式指定代理服务器
		        <Location /> 
		                Require all granted
		        </Location>
		</VirtualHost> 		
	status 设置后端服务器状态
	loadfactor  设置权重
	如:BalancerMember http://172.17.0.2:8080 status=D    #设置为拒绝状态
	重启httpd服务
	测试访问:http://test1.magedu.com/myapp/

(2)配置httpd作为反向代理服务器,使用ajp连接器连接engine
  配置ajp连接器连接engine,监听9090端口

	[root@centos7 conf.d]# vim ajp-tomcat.conf 
	<proxy balancer://tomcatservers>
	        BalancerMember ajp://172.17.0.2:8009
	        BalancerMember ajp://172.17.0.3:8009
	        ProxySet lbmethod=byrequests
	</Proxy>

	Listen 9090
	<VirtualHost *:9090>
	        ServerName      test1.magedu.com
	        ProxyRequests Off
	        ProxyVia        On
	        ProxyPreserveHost On
	        <Proxy *>
	                Require all granted
	        </Proxy>
	        ProxyPass / balancer://tomcatservers/
	        ProxyPassReverse / balancer://tomcatservers/
	        <Location />
	                Require all granted
	        </Location>
	</VirtualHost>
重启httpd服务
测试访问:http://test1.magedu.com:9090/myapp/

启用管理接口:

	<Location /balancer-manager>
		SetHandler balancer-manager
		ProxyPass !
		Require all granted
	</Location>	

示例:

 vim /etc/httpd/conf.d/http-tomcat.conf
	<proxy balancer://tcsrvs>
	        BalancerMember http://172.17.0.2:8080
	        BalancerMember http://172.17.0.3:8080
	        ProxySet lbmethod=byrequests    #调用算法模块
	</Proxy>

	<VirtualHost *:80>
	        ServerName      test1.magedu.com
	        ProxyRequests Off
	        ProxyVia        On
	        ProxyPreserveHost On
	        <Proxy *>
	                Require all granted
	        </Proxy>
	        ProxyPass / balancer://tcsrvs/       #使用balancer格式指定代理服务器
	        ProxyPassReverse / balancer://tcsrvs/    #使用balancer格式指定代理服务器
	        <Location /> 
	                Require all granted
	        </Location>
	</VirtualHost> 

		<Location /balancer-manager>
			SetHandler balancer-manager
			ProxyPass !
			Require all granted
		</Location>

	重启httpd服务
	测试访问管理页面:http://test1.magedu.com/balancer-manager
	可以对后端虚拟主机进行管理
  • 基于balancer模块做负载均衡时也能做基于cookie的会话粘性
      使用stickysession启用JSESSIONID或PHPSESSIONID
      如果后端是tomcat使用JSESSIONID,如果后端是fpm使用PHPSESSIONID
      会话粘性的实现:
		[root@centos7 conf.d]# vim http-tomcat.conf 
		Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/"env=BALANCER_ROUTE_CHANGED   

		<proxy balancer://tcsrvs>
		        BalancerMember http://172.17.0.2:8080 route=tcA   #将会在session中的cookie添加上.tcA的字串
		        BalancerMember http://172.17.0.3:8080 route=tcB   #将会在session中的cookie添加上.tcB的字串
		        ProxySet lbmethod=byrequests
		        ProxySet stickysession=ROUTEID
		</Proxy>

		<VirtualHost *:80>
		        ServerName      test1.magedu.com
		        ProxyRequests Off
		        ProxyVia        On
		        ProxyPreserveHost On
		        <Proxy *>
		                Require all granted
		        </Proxy>
		        ProxyPass / balancer://tcsrvs/
		        ProxyPassReverse / balancer://tcsrvs/
		        <Location />
		                Require all granted
		        </Location>
		</VirtualHost>
重启httpd服务
测试访问http://test1.magedu.com/myapp/
使用curl命令测试:
curl命令不带有cookie信息,因此curl访问时不会被绑定到固定的后端虚拟主机上
	curl -I http://test1.magedu.com/myapp/
    Set-Cookie: ROUTEID=.tcB; path=/   这里只贴出显示结果行
使用curl命令指定ROUTEID
	curl -b ROUTEID=tcA http://test1.magedu.com/myapp/
7.2 基于session replication的tomcat集群
  • tomcat集群配置:基于session replication的tomcat集群
      在engine或host配置中添加以下配置:
    <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
    另外,配置tomcat集群还需要注意:
      多播地址为228.0.0.4
      多播端口为45564
      侦听器
        由于每一个节点都要接收其他节点发来的会话,因此每一个节点都应监听在一个套接字上,来接收其他节点传过来的数据,同时自己也应该有一个发送器把自己的会话信息基于多播信道发送给同一集群中其他节点
      校验会话信息完整性
        探测tcp信息中的错误,验证报文的完整性,即TcpFailureDetector和MessageDispatch15Interceptor
  • 自定义tomcat session replicationcluster(tomcat会话复制集群):
      链接:http://tomcat.apache.org/tomcat-7.0-doc/cluster-howto.html
      内容如下:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
         channelSendOptions="8">

  <Manager className="org.apache.catalina.ha.session.DeltaManager"
           expireSessionsOnShutdown="false"  #关闭会话不会超时
           notifyListenersOnReplication="true"/>  #资源变动时是否通知侦听器,true表示要通知

  <Channel className="org.apache.catalina.tribes.group.GroupChannel">   #Channel是指定义多播会话通信信道
    <Membership className="org.apache.catalina.tribes.membership.McastService"     #集群多播成员关系判定
                address="228.0.0.4"
                port="45564"
                frequency="500"   #成员节点每隔多久发一次心跳,单位为ms
                dropTime="3000"/>  #集群成员多久没有发送心跳就会被丢弃
    <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"   #Receiver是指接收器,接受其他成员发来的信息
              address="auto"  #多播会话传递过程中使用的地址
              port="4000"
              autoBind="100"  #多长时间自动绑定一次
              selectorTimeout="5000"  #挑选出来的地址的超时时间是多长
              maxThreads="6"/>  #集群最大线程数

    <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">   #Sender是指发送器,如何把自己的信息发送给其他成员
      <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.MessageDispatch15Interceptor"/>  #探测器,确保报文的完整性
  </Channel>

  <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
         filter=""/>  #过滤器,对特定报文进行过滤,ReplicationValve只处理session复制相关的报文
  <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>  #JvmRouteBinderValve是指JVM路由绑定器

  <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"   #部署器
            tempDir="/tmp/war-temp/"  #部署时的临时目录
            deployDir="/tmp/war-deploy/"  #部署的目标目录
            watchDir="/tmp/war-listen/"  #监控哪个目录下的内容发生变化
            watchEnabled="false"/>   #false指监控未启用

  <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>  #注意:原内容中该行最后没有添加闭合标签/,因此需要添加上该闭合标签/
  <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>   #注意:原内容中该行最后没有添加闭合标签/,因此需要添加上该闭合标签/
</Cluster>

还需以下配置:
	把以上配置复制到server.xml中
	要确保ReplicationValve中的Receiver.port要设置正确,不要与其他端口冲突,默认端口范围为4000-4100
	要确保打算使用分布式会话的应用程序的web.xml配置文件中存在<distributable/>元素,
	还要编辑每个成员的engine中的jvmRoute有唯一的标识符,即<Engine name="Catalina" jvmRoute="node01" >
注意:配置基于session replication的集群后,前端调度器可以配置调度算法,如wrr调度算法,但并不推荐这种做法,而是应该基于cookie做会话绑定,
这是因为把客端的会话请求调度到其他集群节点时,有可能会话信息还未同步到其他成员节点上,导致客户端无法获取会话信息造成访问失败

实验:实现基于会话复制的tomcat集群

实验环境
	反向代理服务器:192.168.32.129
	集群成员节点1: 192.168.32.130
	集群成员节点2: 192.168.32.131

tomcat两个成员节点配置如下:
在两个成员节点上安装软件包
	yum -y install java-1.8.0-openjdk-devel tomcat tomcat-admin-webapps tomcat-webapps tomcat-docs-webapp

成员节点1:192.168.32.130
	创建主站目录下所需的子目录
		mkdir /webapps/myapp/{lib,class,WEB-INF}
	创建网页文件
		[root@centos7 ~]# vi /webapps/myapp/index.jsp
		<html>
		  <head><title>TomcatA</title></head>
		    <body>
		       <h1><font color="red">TomcatA.magedu.com</font></h1>
		         <table align="centre" border="1">
		           <tr>
		             <td>Session ID</td>
		               <% session.setAttribute("magedu.com","magedu.com"); %>
		             <td><%= session.getId() %></td>
		          </tr>
		          <tr>
		             <td>Created on</td>
		             <td><%= session.getCreationTime() %></td>
		          </tr>
		        </table>
		     </body>
		</html>
	更改tomcat配置文件
		vim  server.xml
		<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatA">   #在engine中添加标识tomcatA
	        <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.45.4"   #指定多播地址,注意地址冲突问题,这里为了防止实验冲突,更改228.0.45.4,注意多播地址与另一主机保持一致
	                        port="45564"
	                        frequency="500"
	                        dropTime="3000"/>
	            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
	                      address="192.168.32.130"   #自动绑定地址,为了防止绑定地址错误,更改本地ip地址
	                      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.MessageDispatch15Interceptor"/>
	          </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.JvmRouteSessionIDBinderListener"/>  #注意,官方文档中该行默认没有闭合标签/
	          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>   #注意,官方文档中该行默认没有闭合标签/
	        </Cluster> 
	    <Context path="/myapp" docBase="/webapps/myapp" reloadable=""/>   #在host内部配置context指定自定义网页文件路径
	注意:还要确保每一个集群节点成员的web.xml文件中配置<distributable/>元素,由于我们所配置的应用程序在/webapps/myapp目录下没有web.xml文件,
	如果没有web.xml文件,将会自动使用默认配置文件,而默认配置文件中没有<distributable/>元素,并且如果在默认配置文件中添加此元素,将会对所有虚拟主机生效。
	因此推荐把系统默认的web.xml复制一份到/webapps/myapp目录下并添加<distributable/>元素
		cp /etc/tomcat/web.xml /webapps/myapp/WEB-INF/    #复制默认的web.xml文件到自定义的应用程序目录下
		vim /webapps/myapp/WEB-INF/web.xml
		  <!--   showServerInfo      Should server information be presented in th
		  <!--                       response sent to clients when directory        -->
		  <!--                       listings is enabled? [true]                    -->
		    <distributable/>        #在注释行结束,默认代码起始行的位置添加<distributable/>元素
		    <servlet>
		        <servlet-name>default</servlet-name>
		        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
	使用浏览器测试访问应用网页文件
		192.168.32.130:8080/myapp/


成员节点2 192.168.32.131
	创建主站目录下所需的子目录
		mkdir /webapps/myapp/{lib,class,WEB-INF}
	创建网页文件
		[root@centos7 ~]# vi /webapps/myapp/index.jsp
		<html>
		  <head><title>TomcatB</title></head>
		    <body>
		       <h1><font color="green">TomcatB.magedu.com</font></h1>
		         <table align="centre" border="1">
		           <tr>
		             <td>Session ID</td>
		               <% session.setAttribute("magedu.com","magedu.com"); %>
		             <td><%= session.getId() %></td>
		          </tr>
		          <tr>
		             <td>Created on</td>
		             <td><%= session.getCreationTime() %></td>
		          </tr>
		        </table>
		     </body>
		</html>
	更改tomcat配置文件
		vim  server.xml
		<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatB">   #在engine中添加标识tomcatA
	        <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.45.4"   #指定多播地址,注意地址冲突问题,多播地址与另一主机保持一致
	                        port="45564"
	                        frequency="500"
	                        dropTime="3000"/>
	            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
	                      address="192.168.32.131"   #自动绑定地址,为了防止绑定地址错误,更改本地ip地址
	                      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.MessageDispatch15Interceptor"/>
	          </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.JvmRouteSessionIDBinderListener"/>  #注意,官方文档中该行默认没有闭合标签/
	          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>   #注意,官方文档中该行默认没有闭合标签/
	        </Cluster> 
	    <Context path="/myapp" docBase="/webapps/myapp" reloadable=""/>   #在host内部配置context指定自定义网页文件路径
	注意:还要确保每一个集群节点成员的web.xml文件中配置<distributable/>元素,由于我们所配置的应用程序在/wenapps/myapp目录下没有web.xml文件,
	如果没有web.xml文件,将会自动使用默认配置文件,而默认配置文件中没有<distributable/>元素,并且如果在默认配置文件中添加此元素,将会对所有虚拟主机生效。
	因此推荐把系统默认的web.xml复制一份到/webapps/myapp目录下并添加<distributable/>元素
		cp /etc/tomcat/web.xml /webapps/myapp/WEB-INF/    #复制默认的web.xml文件到自定义的应用程序目录下
		vim /webapps/myapp/WEB-INF/web.xml
		  <!--   showServerInfo      Should server information be presented in th
		  <!--                       response sent to clients when directory        -->
		  <!--                       listings is enabled? [true]                    -->
		    <distributable/>        #在注释行结束,默认代码起始行的位置添加<distributable/>元素
		    <servlet>
		        <servlet-name>default</servlet-name>
		        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
	使用浏览器测试访问应用网页文件
		192.168.32.130:8080/myapp/

反向代理服务器:192.168.32.129
配置如下:
	安装nginx软件
		yum -y install nginx		
	更改nginx配置文件
		vim /etc/nginx/nginx.conf
		http {
			upstream tcsrvs {
	        	server 192.168.32.130:8080
	        	server 192.168.32.131:8080
			}
			server {
				location / {
                	proxy_pass http://tcsrvs/;  #调用服务器组               	
        		}
			}
		}
	启动nginx服务
	在浏览器测试访问:http://192.168.32.129/myapp/
	注意:反向代理服务器配置问价中,使用proxy_pass进行路径映射时要与访问路径一致,即只能映射根目录,不能映射子目录,否则会有问题。
	当映射根目录时,访问子目录只需要在url后添加子目录路径即可

使用haproxy作为反向代理服务器:
配置如下:
	vim /etc/haproxy/haproxy.cfg
	listen web *:80
		server tc1 192.168.32.130:8080 check
		server tc2 192.168.32.131:8080 check
	启动haproxy服务
	使用浏览器测试访问:http://192.168.32.129/myapp/
7.3 基于session server的tomcat集群配置

memcached介绍

  • 对事物没有要求,约束关系不委托给数据库
  • 只提供K/V类型格式的数据
      K是索引,基于hash算法实现,也是唯一的
  • 牺牲对事物多维度的描述来换取读取数据性能
  • 属于缓存,数据存放在内存中,如果服务器宕机,则数据会丢失,但由于数据存放在内存中,读取速度较快,是对数据读取的一种加速机制
  • memcached是为mysql提供缓存,以提升用户在web服务并发访问量较大而导致大量数据请求压在mysql数据库,但又可以容许数据不精确时提供的一个公共缓存层
  • 两级存储结构,即使用mysql存储数据,使用memcached缓存数据,但前提是数据不需要精确呈现
  • 缓存结构:
      tomcat(php)----缓存memcached----mysql
  • mysql自己也有缓存,但mysql单机缓存只对当前节点生效,而我们无法确保访问会被一直调用到当前节点上,因此要提供一个公共缓存
  • 缓存类型:
      代理式缓存:属于专用缓存,专用于某种协议
      旁路(旁挂)式缓存
  • memcached属于旁路式缓存,由应用程序驱动,但需要一个“智能客户端”
      要求客户端:
        会用缓存
        知道缓存在何处
  • 如果memcached存储数据超出存储上线
      拒绝存储
        缺点:只能存储有限的数据量
      LRU 近期最少使用算法
        缺点:形成频繁淘汰,降低命中率
  • memcached功能:做存储的负载均衡
    调度算法:
      取模法
        对key值取模,根据权重进行调度
        缺陷:一旦服务器某一台出现故障,权重发生变化,缓存将无法命中
      一致性hash算法
        缓存前端需要使用该算法进行负载均衡调度的主机
  • memcached和redis存储的都是K/V格式的数据,二者的区别在"V"上,redis的"v"必须是流式化数据
  • memcached内存分配机制
  • slab allocator 内存分配器
      先把内存空间分配为固定大小的块,当存储数据时,使用离数据大小最接近的块来存储数据。如:把内存空间分配为若干1K,2K,4K的块,当需要存储1.5K的数据时,就把拿出2K的块来存储该数据,但是这样一来就会形成内存碎片,造成空间的浪费
      以固定大小存储数据,以空间换取时间,因此一旦使用时间过长,面临内存碎片问题
  • growth factor 增长因子
      是memcached内存容量增长方式
  • memcached监听端口
      11211/tcp
      11211/udp
  • 传输协议:memcached协议
      编码格式:
        文本编码
        二进制编码

memcached配置相关介绍

  • 安装 base仓库
    yum -y install memcached
  • 配置文件
    /etc/sysconfig/memcached 环境变量配置文件
    /usr/bin/memcached 主程序
    /usr/bin/memcached-tool 命令行客户端工具
    /usr/lib/systemd/system/memcached.service unitfile文件
  • 常用选项
    -u 指定用户
    -U 指定监听的udp端口,0为关闭,不监听udp端口
    -l 监听的地址
    -s 监听的套接字文件
    -d 以守护进程方式进行
    -m 指定最大空间缓存数据,默认为64M
    -M 是指存满了之后,会拒绝存储
      注意:如果数据存满了,会有两种方式:拒绝存储,LRU算法
      -m选项默认为LRU算法
      -M选项是指拒绝存储
    -c 最大并发连接数,默认为1024
    -f 增长因子,默认为1.25
    -n 最小存储空间,默认为48字节
    -t 线程数量,默认为4
      注意:一般情况下,线程数要小于等于cpu核心数
    -S 对memcached进行认证
    Sasl simple authentication secure layer 简单认证安全层
      用于实现memcached的安全认证
      Sasl只提供了认证框架,还需要自己使用认证工具提供认证机制,类似于为房屋提供了院墙,但院墙存在一个门,还需要自己提供出入门的安全机制来保证房屋的安全
  • 配置环境变量
[root@centos7 ~]# vim /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="128"
OPTIONS="-t 8 -f 1.1 -U 0"
  • memcached协议说明文档
      /usr/share/doc/memcached-1.4.15/protocol.txt
  • 存储数据命令:
      stats 查看状态数据
      set 更改已有键值
      add 增加数据
      replace 替换
      append 追加一个字串
      prepend 插入一个字串
      delete 删除命令
      flush_all 清空数据
      memcached惰性清理机制
        数据过期后并不会删除,而是将数据标记为过期状态
    命令语法:
<command name> <key> <flags> <exptime> <bytes> [noreply]\r\n
  命令         键值  标志位  过期时间  指定存储字节数量

示例:

add mykey 0 30 10    增加数据
magedu.com
STORED
get mykey       查看存储的数据
VALUE mykey 0 10
magedu.com
END
  • memcached-tool 命令行客户端工具,相当于一个监控工具
      给定一个ip地址,会自动连接该ip地址+11211端口,显示memcached数据
    示例:
[root@centos7 ~]# memcached-tool 127.0.0.1
  #  Item_Size  Max_age   Pages   Count   Full?  Evicted Evict_Time OOM
  • c语言客户端库:
      libmemcached 客户端工具
      yum -y install libmemcached
      memstat --servers=127.0.0.1:11211 获取memcached状态
  • php语言客户端库:
      php-pecl-memcache.x86_64
      php-pecl-memcached.x86_64
      注意:这两个软件包并不是同一个客户端库

基于memcached实现session server

  • 使用memcached充当存储会话的session server,由于memcached特性(需要一个"智能客户端",要求其会用缓存,知道缓存在何处),需要tomcat自身能够驱动memcached来存储数据
  • 如果memcached存储出现故障,将丢失会话信息,因此需要对memcached存储做冗余备份,而memcached自身没有冗余能力,因此需要前端实现冗余
  • 解决方法:
      客户端在存储数据时,写入两份到存储中,即使用双写方式,实现冗余
  • tomcat自身不存在把数据写入memcached存储中的功能,因此需要第三方解决方案
  • 依赖于第三方软件:msm(memcached session manager)
      github项目:https://github.com/magro/memcached-session-manager
  • 支持的session server类型:
      memcached
      couchbase
      redis
  • 要想存储数据,tomcat要扩展两项功能:
      能够驱动存储
      session manager
        能够调用后端存储系统增删改查等接口的访问能力
  • 除此之外,还需要流式化工具完成数据(session信息)的流式化

基于session server的tomcat集群

  • 基于session server的tomcat集群配置
  • Github官方站点(Tomcat7):https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration#configure-tomcat
memcached实验规划:
为了方便实验,把memcached安装在tomcat主机上,在生产环境中,需要把memcached配置在其他服务器上才有意义
tomcat1主机安装memcached1,简称为m1
tomcat2主机安装memcached2,简称为m2

memcached配置:
    分别在tomcat1主机和tomcat2主机安装memcached并更改环境变量文件
    	yum -y install memcached 
    	vim /etc/sysconfig/memcached 
    	PORT="11211"
    	USER="memcached"
    	MAXCONN="1024"
    	CACHESIZE="128"
    	OPTIONS="-t 8 -f 1.1 -U 0"
    	systemctl start memcached.service

Tomcat配置:
对tomcat1主机配置文件进行修改:
	vim /etc/tomcat/server.xml
	   <Engine name="Catalina" defaultHost="localhost" jvmRoute="TomcatA">      #为tomcat1主机增加TomcatA标识

      <!--For clustering, please take a look at documentation at:
          /docs/cluster-howto.html  (simple how to)
          /docs/config/cluster.html (reference documentation) -->
      <!--
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
      -->

      <!-- Use the LockOutRealm to prevent attempts to guess user passwords
           via a brute-force attack -->
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

        <!-- SingleSignOn valve, share authentication between web applications
             Documentation at: /docs/config/valve.html -->
        <!--
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
        -->
        <Context path="myapp" docBase="/webapps/myapp" reloadable="">               
		#配置context,只对当前context配置文件生效,如果不配置context则会对当前主机生效,会影响到主机下的其他context配置
           <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"      #sticky session+kryo配置
    memcachedNodes="m1:192.168.32.130:11211,n2:192.168.32.131:11211"     #指定memcached存储节点
    failoverNodes="m1"                                                  #指定故障转移节点
    requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
        </Context>
        <!-- Access log processes all example.
             Documentation at: /docs/config/valve.html
             Note: The pattern used is equivalent to using pattern="common" -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />

对tomcat2主机配置文件进行修改:
	vim /etc/tomcat/server.xml
	   <Engine name="Catalina" defaultHost="localhost" jvmRoute="TomcatB">      #为tomcat2主机增加TomcatB标识

      <!--For clustering, please take a look at documentation at:
          /docs/cluster-howto.html  (simple how to)
          /docs/config/cluster.html (reference documentation) -->
      <!--
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
      -->

      <!-- Use the LockOutRealm to prevent attempts to guess user passwords
           via a brute-force attack -->
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

        <!-- SingleSignOn valve, share authentication between web applications
             Documentation at: /docs/config/valve.html -->
        <!--
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
        -->
        <Context path="myapp" docBase="/webapps/myapp" reloadable="">               
		#配置context,只对当前context配置文件生效,如果不配置context则会对当前主机生效,会影响到主机下的其他context配置
           <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"      #sticky session+kryo配置
    memcachedNodes="m1:192.168.32.130:11211,n2:192.168.32.131:11211"     #指定memcached存储节点
    failoverNodes="m1"                                                  #指定故障转移节点
    requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
        </Context>
        <!-- Access log processes all example.
             Documentation at: /docs/config/valve.html
             Note: The pattern used is equivalent to using pattern="common" -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />

在tomcat1和tomcat2主机上准备相关类库
github项目站点:
	https://github.com/magro/memcached-session-manager
    注意:找到与当前tomcat版本一致的文件(当前以tomcat7为例),下载需要的jar包,然后把下载的jar包存放在/usr/share/java/tomcat目录下
下载地址如下:
msm会话管理器
	核心类库:适用于tomcat7版本的jar包要求必须是tomcat7.0.23版本以上
		下载地址:http://repo1.maven.org/maven2/de/javakaffee/msm/memcached-session-manager/2.3.2/memcached-session-manager-2.3.0.jar
	适用于tomcat7版本的jar包
		下载地址:http://repo1.maven.org/maven2/de/javakaffee/msm/memcached-session-manager-tc7/2.3.0/memcached-session-manager-tc7-2.3.0.jar
驱动存储系统的jar包
	下载地址:http://repo1.maven.org/maven2/net/spy/spymemcached/2.12.3/spymemcached-2.12.3.jar
序列化工具组件:
	kryo-serializer包含以下jar包组件
	msm-kryo-serializer下载地址:http://repo1.maven.org/maven2/de/javakaffee/msm/msm-kryo-serializer/2.3.0/msm-kryo-serializer-2.3.0.jar
	kryo-serializers-0.34+下载地址:http://repo1.maven.org/maven2/de/javakaffee/kryo-serializers/0.42/kryo-serializers-0.42.jar
	kryo-3.x下载地址:http://repo1.maven.org/maven2/com/esotericsoftware/kryo/4.0.2/kryo-4.0.2.jar
	minlog下载地址:http://repo1.maven.org/maven2/com/esotericsoftware/minlog/1.3.0/minlog-1.3.0.jar
	reflectasm下载地址:http://repo1.maven.org/maven2/com/esotericsoftware/reflectasm/1.11.7/reflectasm-1.11.7.jar
	asm-5.x下载地址:http://repo1.maven.org/maven2/org/ow2/asm/asm/6.2/asm-6.2.jar
	objenesis-2.x下载地址:http://repo1.maven.org/maven2/org/objenesis/objenesis/2.6/objenesis-2.6.jar
注意:把相关jar分别存放在tomcat1和tomcat2主机上/usr/share/java/tomcat目录下

在tomcat1和tomcat2主机上启动tomcat服务
	systemctl start tomcat

在tomcat1上再开启一个窗口并使用tail命令追踪日志信息查看memcached是否启动
tail -f /var/log/tomcat/catalina.2019-01-22.log 
Jan 22, 2019 3:23:28 PM de.javakaffee.web.msm.MemcachedSessionService startInternal    #memcached会话服务启动
INFO: --------               #具体信息如下
-  finished initialization:     #完成初始化
- sticky: true                #启用粘性会话
- operation timeout: 1000     #超时时长
- node ids: [m2]             #活动节点为m2
- failover node ids: [m1]     #故障转移节点为m1
- storage key prefix: null
- locking mode: null (expiration: 5s)
--------

在tomcat2上再开启一个窗口并使用tail命令追踪日志信息查看memcached是否启动
tail -f /var/log/tomcat/catalina.2019-01-22.log 
Jan 22, 2019 3:23:28 PM de.javakaffee.web.msm.MemcachedSessionService startInternal    #memcached会话服务启动
INFO: --------               #具体信息如下
-  finished initialization:     #完成初始化
- sticky: true                #启用粘性会话
- operation timeout: 1000     #超时时长
- node ids: [m2]             #活动节点为m2
- failover node ids: [m1]     #故障转移节点为m1
- storage key prefix: null
- locking mode: null (expiration: 5s)
--------

测试:
	访问tomcat1主机:192.168.32.130:8080/myapp/
	访问tomcat2主机:192.168.32.131:8080/myapp/

访问显示如下:
    Session ID 9AC02838C484FBC548BE53B905352796-m2.TomcatB 
    注意:显示结果中,会发现tomcat标识TomcatB在变化,但Session ID:9AC02838C484FBC548BE53B905352796-m2并不会发生改变,说明memcached缓存发生作用

关闭主节点m2,会发现session信息会变为m1节点,这是因为配置了故障转移节点(fialover)为m1,一旦主节点m2发生故障,将会切换到故障转移节点m1上
如果再次开启主节点m2,会发现session信息将会从m1上转移为m2,这是因为主节点一旦修复,将会继续其工作,m1继续作为故障转移节点,这也就是所谓的故障移回(failback)

注意:如果在生产环境,推荐使用redis作为后端存储session信息的session server

知识扩展:Tomcat配置文件中memcached配置示例说明

做sticky session+kryo的配置
<Context>
  ...
  <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="n1:host1.yourdomain.com:11211,n2:host2.yourdomain.com:11211"
    failoverNodes="n1"
    requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
</Context>
className   指定存储会话的类
memcachedNodes   指存储节点
failoverNodes   指故障转移节点
	failover  故障转移
		当主节点出现故障,自动转移到备用节点上,实现冗余或高可用
	failback  故障移回
	 	当主节点修复完毕,主节点代替备用节点夺回主节点位置
requestUriIgnorePattern   忽略模式,即凡是以.ico|png|gif|jpg|css|js结尾的将会被忽略掉
transcoderFactoryClass  指定用什么流式化类执行流式化
	de.javakaffee.web.msm.serializer是固定前缀

做non-sticky session+kryo的配置
<Context>
  ...
  <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="n1:host1.yourdomain.com:11211,n2:host2.yourdomain.com:11211"
    sticky="false"     
    sessionBackupAsync="false"
    lockingMode="uriPattern:/path1|/path2"
    requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
</Context>
该配置不存在failoverNodes,是指不做主从复制,而是双主模式
sticky="false"    是指不做会话粘性
sessionBackupAsync="false"  是指不进行异步同步,否则可能会导致数据访问不一致
lockingMode   锁定的模式

做non-sticky sessions + kryo + Redis配置
<Context>
  ...
  <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="redis://redis.example.com"
    sticky="false"
    sessionBackupAsync="false"
    lockingMode="uriPattern:/path1|/path2"
    requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
</Context>
该配置没有做主从复制,redis支持主从复制功能,支持集群

8、Tomcat的常用优化配置:

  • Tomcat的常用优化配置:
(1) 内存空间:
	/etc/sysconfig/tomcat, /etc/tomcat/tomcat.conf
		JAVA_OPTS="-server -Xms32g -Xmx32g -XX:NewSize= -XX:MaxNewSize= "
			-server:服务器模式
			-Xms:堆内存初始化大小;
			-Xmx:堆内存空间上限;
			-XX:NewSize=:新生代空间初始化大小;					
			-XX:MaxNewSize=:新生代空间最大值;
(2) 线程池设置:
	在tomcat配置文件server.xml中连接器配置中
	<Connector port="8080" protocol="HTTP/1.1"  connectionTimeout="20000" redirectPort="8443" />
	常用属性:
		maxThreads:最大线程数;
		minSpareThreads:最小空闲线程数;
		maxSpareThreads:最大空闲线程数;
		acceptCount:等待队列的最大长度;
		URIEncoding:URI地址编码格式,建议使用UTF-8;
		enableLookups:是否启用dns解析,建议禁用; 
		compression:是否启用传输压缩机制,建议“on";
		compressionMinSize:启用压缩传输的数据流最小值,单位是字节;
		compressableMimeType:定义启用压缩功能的MIME类型;
			text/html, text/xml, text/css, text/javascript
(3) 禁用8005端口;
	<Server port="-1" shutdown="SHUTDOWN">
(4) 隐藏版本信息:
	<Connector port="8080" protocol="HTTP/1.1"  connectionTimeout="20000" redirectPort="8443" />
	Server="SOME STRING"
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值