十一周
一、总结 tomcat实现多虚拟机
#准备数据目录
[root@tomcat ~]#mkdir /data/website{1,2,3}/ROOT -pv
[root@tomcat ~]#vim /data/website1/ROOT/index.html
www.a.com
/data/website1/ROOT/index.html
[root@tomcat ~]#vim /data/website2/ROOT/index.html
www.b.com
/data/website2/ROOT/index.html
[root@tomcat ~]#vim /data/website3/ROOT/index.html
www.c.com
/data/website3/ROOT/index.html
#设置权限
[root@tomcat ~]#chown -R tomcat.tomcat /data/website{1,2,3}/
#修改配置
[root@tomcat ~]#cd /usr/local/tomcat/
[root@tomcat tomcat]#vim conf/server.xml
</Host>
<Host name="www.a.com" appBase="/data/website1/"
unpackWARs="true" autoDeploy="true">
</Host>
<Host name="www.b.com" appBase="/data/website2/"
unpackWARs="true" autoDeploy="true">
</Host>
<Host name="www.c.com" appBase="/data/website3/"
unpackWARs="true" autoDeploy="true">
</Host>
</Engine>
</Service>
</Server>
#重启Tomcat服务
[root@tomcat tomcat]#systemctl restart tomcat.service
#测试访问
[root@client ~]#vim /etc/hosts
10.0.0.7 www.a.com www.b.com www.c.com
[root@client ~]#curl www.a.com:8080
www.a.com
/data/website1/ROOT/index.html
[root@client ~]#curl www.b.com:8080
www.b.com
/data/website2/ROOT/index.html
[root@client ~]#curl www.c.com:8080
www.c.com
/data/website3/ROOT/index.html
二、总结 tomcat定制访问日志格式和反向代理tomcat
日志格式: https://tomcat.apache.org/tomcat-9.0-doc/config/valve.html#Access_Logging
%a - Remote IP address
%A - Local IP address
%b - Bytes sent, excluding HTTP headers, or '-' if zero
%B - Bytes sent, excluding HTTP headers
%h - Remote host name (or IP address if enableLookups for the connector is
false)
%H - Request protocol
%l - Remote logical username from identd (always returns '-')
%m - Request method (GET, POST, etc.)
%p - Local port on which this request was received. See also %{xxx}p below.
%q - Query string (prepended with a '?' if it exists)
%r - First line of the request (method and request URI)
%s - HTTP status code of the response
%S - User session ID
%t - Date and time, in Common Log Format
%u - Remote user that was authenticated (if any), else '-'
%U - Requested URL path
%v - Local server name
%D - Time taken to process the request in millis. Note: In httpd %D is
microseconds. Behaviour will be aligned to httpd in Tomcat 10 onwards.
%T - Time taken to process the request, in seconds. Note: This value has
millisecond resolution whereas in httpd it has second resolution. Behaviour will
be align to httpd in Tomcat 10 onwards.
%F - Time taken to commit the response, in millis
%I - Current request thread name (can compare later with stacktraces)
%X - Connection status when response is completed:
X = Connection aborted before the response completed.
+ = Connection may be kept alive after the response is sent.
- = Connection will be closed after the response is sent.
There is also support to write information incoming or outgoing headers, cookies,
session or request attributes and special timestamp formats. It is modeled after
the Apache HTTP Server log configuration syntax. Each of them can be used
multiple times with different xxx keys:
%{xxx}i write value of incoming header with name xxx
%{xxx}o write value of outgoing header with name xxx
%{xxx}c write value of cookie with name xxx
%{xxx}r write value of ServletRequest attribute with name xxx
%{xxx}s write value of HttpSession attribute with name xxx
%{xxx}p write local (server) port (xxx==local) or remote (client) port
(xxx=remote)
%{xxx}t write timestamp at the end of the request formatted using the enhanced
SimpleDateFormat pattern xxx
#查看访问日志格式
[root@centos8 ~]#tail /usr/local/tomcat/conf/server.xml
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" /> #说明: "在html
中表示双引号"符号
</Host>
</Engine>
</Service>
</Server>
#查看访问日志
[root@centos8 ~]#tail /usr/local/tomcat/logs/localhost_access_log.2020-07-14.txt
10.0.0.1 - - [14/Jul/2020:09:08:46 +0800] "GET / HTTP/1.1" 200 11215
10.0.0.1 - - [14/Jul/2020:09:08:46 +0800] "GET /tomcat.css HTTP/1.1" 200 5581
10.0.0.1 - - [14/Jul/2020:09:08:46 +0800] "GET /tomcat.png HTTP/1.1" 200 5103
10.0.0.1 - - [14/Jul/2020:09:08:46 +0800] "GET /bg-nav.png HTTP/1.1" 200 1401
10.0.0.1 - - [14/Jul/2020:09:08:46 +0800] "GET /bg-upper.png HTTP/1.1" 200 3103
10.0.0.1 - - [14/Jul/2020:09:08:46 +0800] "GET /asf-logo-wide.svg HTTP/1.1" 200
27235
10.0.0.1 - - [14/Jul/2020:09:08:46 +0800] "GET /bg-middle.png HTTP/1.1" 200 1918
10.0.0.1 - - [14/Jul/2020:09:08:46 +0800] "GET /bg-button.png HTTP/1.1" 200 713
10.0.0.1 - - [14/Jul/2020:09:08:46 +0800] "GET /favicon.ico HTTP/1.1" 200 21630
编辑此部分修改日志格式
pattern="%h %l %u %t "%r" %s %b"
反向代理tomcat
通过nginx在HTTP块中的upstream模块实现反向代理 并用ip_hash 或者cookie实现session保持
通过前端的nginx主机访问后端的两台tomcat主机
#修改/etc/hosts文件,实现名称解析
[root@centos8 ~]#vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
centos8.localdomain
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.100 node1.wang.org node2.wang.org
#在http块中加以下内容
#注意名称不要用下划线
upstream tomcat-server {
#ip_hash; # 只根据客户端IP的前三位十进制数字
#hash $remote_addr consistent; # 根据客户端IP的全部位
#hash $cookie_jsessionid consistent; # 先禁用看看轮询,之后开启开黏性,JSESSIONID要小写
server t1.wang.org:8080;
server t2.wang.org:8080;
}
server {
location ~* \.(jsp|do)$ {
proxy_pass http://tomcat-server;
#proxy_set_header Host $http_host; #转发主机头至后端服务器
}
}
测试 http://proxy.wang.org/index.jsp,可以看到轮询调度效果,每次刷新后端主机和SessionID都会变化
三、完成 tomcat实现MSM集群
MSM(memcached session manager)提供将Tomcat的session保持到memcached或Redis的程序,可以实现高可用
sticky 模式即前端tomcat和后端memcached有关联(粘性)关系
Tomcat-1 (t1) will primarily store it's sessions in memcached-2 (m2) which is
running on another machine (m2 is a regular node for t1). Only if m2 is not
available, t1 will store it's sessions in memcached-1 (m1, m1 is the failoverNode
for t1). With this configuration, sessions won't be lost when machine 1 (serving
t1 and m1) crashes. The following really nice ASCII art shows this setup.
Tomcat-1(t1)主要将其会话存储在另一台计算机上运行的memcached-2(m2)中(m2是t1的常规节
点)。 仅当m2不可用时,t1才会将其会话存储在memcached-1中(m1,m1是t1的failoverNode)。 使
用此配置,当计算机1(服务于t1和m1)崩溃时,会话不会丢失。 以下非常好的ASCII艺术显示了此设置。
<t1> <t2>
. \ / .
. X .
. / \ .
<m1> <m2>
t1和m1部署可以在一台主机上,t2和m2部署也可以在同一台。
当新用户发请求到Tomcat1时, Tomcat1生成session返回给用户的同时,也会同时发给memcached2备
份。即Tomcat1 session为主session,memcached2 session为备用session,使用memcached相当
于备份了一份Session
如果Tomcat1发现memcached2 失败,无法备份Session到memcached2,则将Sessoin备份存放在
memcached1中
配置:
修改tomcat配置
修改 $CATALINA_HOME/conf/context.xml
特别注意,t1配置中为failoverNodes="n1", t2配置为failoverNodes="n2"
配置中追加如下
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:10.0.0.101:11211,n2:10.0.0.102:11211"
failoverNodes="n1"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFac
tory"
/>
配置成功,可以在logs/catalina.out中看到
12-APR-2020 16:24:08.975 INFO [t1.wang.org-startStop-1]
de.javakaffee.web.msm.MemcachedSessionService.startInternal --------
- finished initialization:
- sticky: true
- operation timeout: 1000
- node ids: [n2]
- failover node ids: [n1]
- storage key prefix: null
- locking mode: null (expiration: 5s)
测试msm的python脚本
[root@t1 ~]#dnf -y install python3 python3-memcached
#或者下面方式也可以安装
[root@t1 ~]#dnf -y install python3
[root@t1 ~]#pip3 install python-memcached
[root@t1 ~]#chmod +x showmemcached.py
#脚本内容
[root@centos8 ~]#cat showmemcached.py
#!/usr/bin/python3
import memcache
mc = memcache.Client(['10.0.0.101:11211'], debug=True)
stats = mc.get_stats()[0]
print(stats)
for k,v in stats[1].items():
print(k, v)
print('-' * 30)
# 查看全部key
print(mc.get_stats('items')) # stats items 返回 items:5:number 1
print('-' * 30)
print(mc.get_stats('cachedump 5 0')) # stats cachedump 5 0 # 5和上面的items返回的值
有关;0表示全部
通过脚本验证session内容和网页验证,可以看到浏览器端被调度到不同Tomcat上,但是都获得了同样的SessionID。
Nginx 充当 Proxy负责将访问调度到后端tomcat,由memcached保存session信息,sticky模式。
nginx配置文件:
[root@proxy ~]#cat /etc/nginx/nginx.conf
http {
......
upstream tomcat-server {
#ip_hash;
server t1.wang.org:8080;
server t2.wang.org:8080;
}
server {
......
location / {
}
location ~* \.(jsp|do)$ {
proxy_pass http://tomcat-server;
#proxy_set_header Host $http_host; #转发主机头至后端服务器
}
本地主机解析
[root@proxy ~]#cat /etc/hosts
10.0.0.100 proxy.wang.org proxy
10.0.0.101 t1.wang.org t1
10.0.0.102 t2.wang.org t2
安装memcached:
[root@t1 ~]#cat /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
#注释下面行
#OPTIONS="-l 127.0.0.1,::1"
配置中追加:
conf/server.xml
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:10.0.0.101:11211,n2:10.0.0.102:11211"
failoverNodes="n1"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFac
tory"
/>
#将相关包传到lib/目录下,共10个文件
asm-5.2.jar
kryo-3.0.3.jar
kryo-serializers-0.45.jar
memcached-session-manager-2.3.2.jar
memcached-session-manager-tc8-2.3.2.jar
minlog-1.3.1.jar
msm-kryo-serializer-2.3.2.jar
objenesis-2.6.jar
reflectasm-1.11.9.jar
spymemcached-2.12.3.jar
[root@t1 tomcat]#cat /data/webapps/ROOT/index.jsp
<%@ page import="java.util.*" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>tomcat test</title>
</head>
<body>
<h1> tomcat website </h1>
<div>On <%=request.getServerName() %></div>
<div><%=request.getLocalAddr() + ":" + request.getLocalPort() %></div>
<div>SessionID = <span style="color:blue"><%=session.getId() %></span></div>
<%=new Date()%>
</body>
</html>
同样方法配置tomcat2: 配置文件稍有不同
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:10.0.0.101:11211,n2:10.0.0.102:11211"
failoverNodes="n2" #只修改此行,和t1不同,其它都一样
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFact
tory"
/>
与之相对的Non-Sticky 模式
相当于session信息都交付给memcached,本地不存储session;
Tomcat session为中转Session,对每一个SessionID随机选中后端的memcached节点n1(或者n2)为主
session,而另一个memcached节点n2(或者是n1)为备session。产生的新的Session会发送给主、备
memcached,并清除本地Session。
对应配置文件修改如下:sticky值为false
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:10.0.0.101:11211,n2:10.0.0.102:11211"
sticky="false" #下面三行和sticky模式不同
sessionBackupAsync="false"
lockingMode="uriPattern:/path1|/path2"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFact
ory"
/>
总结 JVM垃圾回收算法和分代
垃圾收集方式
按工作模式不同:指的是GC线程和工作线程是否一起运行
独占垃圾回收器:只有GC在工作,STW 一直进行到回收完毕,工作线程才能继续执行
并发垃圾回收器:让GC线程垃圾回收某些阶段可以和工作线程一起进行,如:标记阶段并行,回收阶段
仍然串行
按回收线程数:指的是GC线程是否串行或并行执行
串行垃圾回收器:一个GC线程完成回收工作
并行垃圾回收器:多个GC线程同时一起完成回收工作,充分利用CPU资源