31-WebAPP服务器TomCat及优化

时间:2022-12-14 19:00:15

Tomcat基础功能

Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,Tomcat 具有处理HTML静态资源页面的功能,它还是一个Servlet和JSP容器

#Servlet 本质就是一段Java程序

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorld extends HttpServlet {
private String message;
public void init() throws ServletException
{
message = "Hello World";
}
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("text/html"); //响应报文内容类型
PrintWriter out = response.getWriter(); //构建响应报文内容
out.println("<h1>" + message + "</h1>");
out.println("<p><a href=http://www.moore.com>世界</a>欢迎你</p>");
}
public void destroy()
{
}
}

在Servlet中最大的问题是,HTML输出和Java代码混在一起,如果网页布局要调整,Java源代码就需要随之进行调整,对于开发人员来说就是个噩梦。

#jsp(Java Server Pages)
JSP本质是提供一个HTML模板,也就是在网页中预留以后填充的空,后续将Java程序运行生成的数据对HTML进行填空就可以了。如果网页布局需要调整,JAVA源代码不需要很大的调整

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jsp例子</title>
</head>
<body>
本行后面的内容是服务器端动态生成字符串,最后拼接在一起
<%
out.println("你的 IP 地址 " + request.getRemoteAddr());
%>
</body>
</html>

JSP是基于Servlet实现,JSP将表现和逻辑分离,这样页面开发人员更好的注重页面表现力更好服务客户。
Tomcat处理方式:
浏览器第一次请求test.jsp时, Tomcat服务器会自动将test.jsp转化成test.jsp.java这么一个类,并将该文件编译成class文件。编译完毕后再运行class文件来响应浏览器的请求。如果以后访问test.jsp就不再重新编译jsp文件了,直接调用class文件来响应浏览器。后续如果Tomcat检测到JSP页面改动了的话,会重新编译

Tomcat脚本安装

二进制安装 Tomcat
*安装tomcat 前必须先部署JDK

#!/bin/bash

TOMCAT_VERSION=xxx
JDK_VERSION=xxx

TOMCAT_FILE="apache-tomcat-${TOMCAT_VERSION}.tar.gz"

JDK_FILE="jdk-${JDK_VERSION}-linux-x64.tar.gz"

JDK_DIR="/usr/local"
TOMCAT_DIR="/usr/local"
DIR=`pwd`

color () {
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \E[0m"
echo -n "$2" && $MOVE_TO_COL
echo -n "["
if [ $1 = "success" -o $1 = "0" ] ;then
${SETCOLOR_SUCCESS}
echo -n $" OK "
elif [ $1 = "failure" -o $1 = "1" ] ;then
${SETCOLOR_FAILURE}
echo -n $"FAILED"
else
${SETCOLOR_WARNING}
echo -n $"WARNING"
fi
${SETCOLOR_NORMAL}
echo -n "]"
echo
}



install_jdk(){
if [ ! -f "$DIR/$JDK_FILE" ];then
color 1 "$JDK_FILE 文件不存在"
exit;
elif [ -d $JDK_DIR/jdk ];then
color 1 "JDK 已经安装"
exit
else
[ -d "$JDK_DIR" ] || mkdir -pv $JDK_DIR
fi
tar xvf $DIR/$JDK_FILE -C $JDK_DIR
cd $JDK_DIR && ln -s jdk* jdk

cat > /etc/profile.d/jdk.sh <<EOF
export JAVA_HOME=$JDK_DIR/jdk
export PATH=\$PATH:\$JAVA_HOME/bin
#export JRE_HOME=\$JAVA_HOME/jre
#export CLASSPATH=.:\$JAVA_HOME/lib/:\$JRE_HOME/lib/
EOF
. /etc/profile.d/jdk.sh
java -version && color 0 "JDK 安装完成" || { color 1 "JDK 安装失败" ; exit; }

}

install_tomcat(){
if ! [ -f "$DIR/$TOMCAT_FILE" ];then
color 1 "$TOMCAT_FILE 文件不存在"
exit;
elif [ -d $TOMCAT_DIR/tomcat ];then
color 1 "TOMCAT 已经安装"
exit
else
[ -d "$TOMCAT_DIR" ] || mkdir -pv $TOMCAT_DIR
fi
tar xf $DIR/$TOMCAT_FILE -C $TOMCAT_DIR
cd $TOMCAT_DIR && ln -s apache-tomcat-*/ tomcat
echo "PATH=$TOMCAT_DIR/tomcat/bin:"'$PATH' > /etc/profile.d/tomcat.sh
id tomcat &> /dev/null || useradd -r -s /sbin/nologin tomcat

cat > $TOMCAT_DIR/tomcat/conf/tomcat.conf <<EOF
JAVA_HOME=$JDK_DIR/jdk
EOF

chown -R tomcat.tomcat $TOMCAT_DIR/tomcat/

cat > /lib/systemd/system/tomcat.service <<EOF
[Unit]
Description=Tomcat
#After=syslog.target network.target remote-fs.target nss-lookup.target
After=syslog.target network.target

[Service]
Type=forking
EnvironmentFile=$TOMCAT_DIR/tomcat/conf/tomcat.conf
ExecStart=$TOMCAT_DIR/tomcat/bin/startup.sh
ExecStop=$TOMCAT_DIR/tomcat/bin/shutdown.sh
RestartSec=3
PrivateTmp=true
User=tomcat
Group=tomcat

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now tomcat.service &> /dev/null
systemctl is-active tomcat.service &> /dev/null && color 0 "TOMCAT 安装完成" || { color 1 "TOMCAT 安装失败" ; exit; }

}

install_jdk

install_tomcat

*访问8080端口即可出现Tomcat页面

Tomcat 文件结构和组成

目录

说明

bin

服务启动、停止等相关程序和文件

conf

配置文件

lib

库目录

logs

日志目录

webapps

应用程序,应用部署目录

work

jsp编译后的结果文件,建议提前预热访问,升级应用后,删除此目录数据才能更新

范例:查看tomcat相关目录和文件

[root@ubuntu2204 ~]#cd /usr/local/tomcat
[root@ubuntu2204 tomcat]#ls
bin BUILDING.txt conf CONTRIBUTING.md lib LICENSE logs NOTICE README.md RELEASE-NOTES RUNNING.txt temp webapps work
[root@ubuntu2204 tomcat]#ls bin/
bootstrap.jar catalina-tasks.xml commons-daemon.jar configtest.sh digest.sh shutdown.bat startup.sh tool-wrapper.bat version.sh
catalina.bat ciphers.bat commons-daemon-native.tar.gz daemon.sh setclasspath.bat shutdown.sh tomcat-juli.jar tool-wrapper.sh
catalina.sh ciphers.sh configtest.bat digest.bat setclasspath.sh startup.bat tomcat-native.tar.gz version.bat
[root@ubuntu2204 tomcat]#ls conf/
Catalina catalina.properties jaspic-providers.xml logging.properties tomcat.conf tomcat-users.xsd
catalina.policy context.xml jaspic-providers.xsd server.xml tomcat-users.xml web.xml
[root@ubuntu2204 tomcat]#ls lib/
annotations-api.jar catalina-storeconfig.jar jasper-el.jar servlet-api.jar tomcat-i18n-de.jar tomcat-i18n-ko.jar tomcat-jni.jar websocket-api.jar
catalina-ant.jar catalina-tribes.jar jasper.jar tomcat-api.jar tomcat-i18n-es.jar tomcat-i18n-ru.jar tomcat-util.jar
catalina-ha.jar ecj-4.6.3.jar jaspic-api.jar tomcat-coyote.jar tomcat-i18n-fr.jar tomcat-i18n-zh-CN.jar tomcat-util-scan.jar
catalina.jar el-api.jar jsp-api.jar tomcat-dbcp.jar tomcat-i18n-ja.jar tomcat-jdbc.jar tomcat-websocket.jar
[root@ubuntu2204 tomcat]#ls logs/
catalina.2022-12-06.log host-manager.2022-12-06.log localhost.2022-12-07.log manager.2022-12-06.log
catalina.2022-12-07.log host-manager.2022-12-07.log localhost_access_log.2022-12-06.txt manager.2022-12-07.log
catalina.out localhost.2022-12-06.log localhost_access_log.2022-12-07.txt
[root@ubuntu2204 tomcat]#ls webapps/
docs examples host-manager manager ROOT
[root@ubuntu2204 tomcat]#ls work/
Catalina

Nginx实现Tomcat的负载均衡和会话保持解决方案

会话保持解决方案

指定浏览器请求发送到固定服务器 --> 由于http属于无状态访问,所以借助cookie技术实现信息绑定
1. SH源地址哈希
2. Cookie绑定
*缺点:当服务器宕机时,该服务器存储的session会丢失,不推荐

服务器间进行session共享复制
*缺点:多服务器时造成的存储空间浪费严重,不推荐

设立单独session服务器
*在解决单点问题的情况下推荐

案例1.1 基于源地址哈希做会话绑定 :

#基于源地址哈希做会话绑定 
1.0.0.8 - nginx服务器
[root@rocky8 ~]#cat /apps/nginx/conf/conf.d/tomcat.conf
upstream tomcat {
ip_hash; --> 只要是ip前三位相同,就调度向同一服务器 不合理
server 10.0.0.200:8080;
server 10.0.0.202:8080;
}

server{
listen 80;
server_name tomcat.mooreyxia.org;
location / {
proxy_pass http://tomcat;
}

error_page 404 @error_404;
location @error_404 {
default_type text/html;
charset utf8;
return 200 '你访问的页面可能走丢了!';
}
}

10.0.0.200 Tomcat1 和 201 Tomcat2
[root@ubuntu2204 ROOT]#cat index.jsp
<%@ page language="java" %>
<html>
<head><title>Tomcat1</title></head>
<body>
<h1><font color="red">Tomcat1</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("mooreyxia.org","mooreyxia.org"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>

浏览访问测试 http://tomcat.mooreyxia.org/ sessionID固定

实现命令行cookie 绑定
1. 保存coookie
[root@rocky8 ~]#curl -Lk -c cookie.txt http://tomcat.mooreyxia.org/

<html>
<head><title>Tomcat2</title></head>
<body>
<h1><font color="red">Tomcat2</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>

<td>26A09B2E817975E55955366E988FF834</td>
</tr>
<tr>
<td>Created on</td>
<td>1670658073439</td>
</tr>
</table>
</body>
</html>

[root@rocky8 ~]#cat cookie.txt
# Netscape HTTP Cookie File
# https://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.

#HttpOnly_tomcat.mooreyxia.org FALSE / FALSE 0 JSESSIONID 26A09B2E817975E55955366E988FF834

2. 访问时携带cookie即可
[root@rocky8 ~]#curl -Lk -b cookie.txt http://tomcat.mooreyxia.org/

<html>
<head><title>Tomcat2</title></head>
<body>
<h1><font color="red">Tomcat2</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>

<td>26A09B2E817975E55955366E988FF834</td>
</tr>
<tr>
<td>Created on</td>
<td>1670658073439</td>
</tr>
</table>
</body>
</html>

案例1.2 基于客户端哈希+定向算法做会话绑定 :

[root@rocky8 ~]#cat /apps/nginx/conf/conf.d/tomcat.conf
upstream tomcat {
#ip_hash;
hash $remote_addr consistent; --> 客户端哈希+定向
server 10.0.0.200:8080;
server 10.0.0.202:8080;
}

server{
listen 80;
server_name tomcat.mooreyxia.org;
location / {
proxy_pass http://tomcat;
}

error_page 404 @error_404;
location @error_404 {
default_type text/html;
charset utf8;
return 200 '你访问的页面可能走丢了!';
}
}

测试
[root@rocky8 ~]#curl http://tomcat.mooreyxia.org/

<html>
<head><title>Tomcat2</title></head>
<body>
<h1><font color="red">Tomcat2</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>

<td>628C2546637D4727D637DEBCD812F67A</td>
</tr>
<tr>
<td>Created on</td>
<td>1670658574452</td>
</tr>
</table>
</body>
</html>

浏览器访问Tomcat1

sessionID 没有变化

局限性:由于互联网都是基于SNAT访问 上述方案会造成单个服务器访问量负载过大,所以优化为基于cookie绑定会话

案例1.3 基于服务器cookie哈希做会话绑定 :

[root@rocky8 ~]#cat /apps/nginx/conf/conf.d/tomcat.conf
upstream tomcat {
#ip_hash;
#hash $remote_addr consistent; --> 服务器cookie哈希
hash $cookie_JSESSIONID consistent;
server 10.0.0.200:8080;
server 10.0.0.202:8080;
}

server{
listen 80;
server_name tomcat.mooreyxia.org;
location / {
proxy_pass http://tomcat;
}

error_page 404 @error_404;
location @error_404 {
default_type text/html;
charset utf8;
return 200 '你访问的页面可能走丢了!';
}
}

测试 基于命令行或是浏览器 都实现绘画绑定 且优化单个服务器负载问题

实现https访问Nginx,代理http转发到Tomcat

ssl证书脚本
CA_SUBJECT="/O=mooreyxia/CN=ca.mooreyxia.org"
SUBJECT="/C=CN/ST=beijing/L=beijing/O=mooreyxia/CN=www.mooreyxia.org"
SERIAL=34
EXPIRE=202002
FILE=mooreyxia.org

openssl req -x509 -newkey rsa:2048 -subj $CA_SUBJECT -keyout ca.key -nodes -days 202002 -out ca.crt

openssl req -newkey rsa:2048 -nodes -keyout ${FILE}.key -subj $SUBJECT -out ${FILE}.csr

openssl x509 -req -in ${FILE}.csr -CA ca.crt -CAkey ca.key -set_serial $SERIAL -days $EXPIRE -out ${FILE}.crt

chmod 600 ${FILE}.key ca.key

[root@rocky8 conf.d]#mv ca* mooreyxia* /apps/nginx/certification/
[root@rocky8 conf.d]#cd /apps/nginx/certification/
[root@rocky8 certification]#ll
total 20
-rw-r--r-- 1 root root 1188 Dec 10 20:40 ca.crt
-rw------- 1 root root 1704 Dec 10 20:40 ca.key
-rw-r--r-- 1 root root 1111 Dec 10 20:40 mooreyxia.org.crt
-rw-r--r-- 1 root root 997 Dec 10 20:40 mooreyxia.org.csr
-rw------- 1 root root 1708 Dec 10 20:40 mooreyxia.org.key
[root@rocky8 certification]#cat mooreyxia.org.crt ca.crt > www.mooreyxia.org.pem
[root@rocky8 certification]#ls
ca.crt ca.key mooreyxia.org.crt mooreyxia.org.csr mooreyxia.org.key www.mooreyxia.org.pem
[root@rocky8 certification]#mv mooreyxia.org.key www.mooreyxia.org.key
[root@rocky8 certification]#ls
ca.crt ca.key mooreyxia.org.crt mooreyxia.org.csr www.mooreyxia.org.key www.mooreyxia.org.pem
[root@rocky8 certification]#pwd
/apps/nginx/certification
[root@rocky8 certification]#ll /apps/nginx/certification/www.mooreyxia.org.key
-rw------- 1 root root 1708 Dec 10 20:40 /apps/nginx/certification/www.mooreyxia.org.key

#nginx 设置转发策略
[root@rocky8 ~]#cat /apps/nginx/conf/conf.d/tomcat.conf
upstream tomcat {
#ip_hash;
#hash $remote_addr consistent;
hash $cookie_JSESSIONID consistent;
server 10.0.0.200:8080;
server 10.0.0.202:8080;
}

server {
listen 80;
server_name tomcat.mooreyxia.org;
# location / {
# proxy_pass http://tomcat;
# }

return 302 https://$host$request_uri;
}

server {
listen 443 ssl;
server_name tomcat.mooreyxia.org;
ssl_certificate /apps/nginx/certification/www.mooreyxia.org.pem;
ssl_certificate_key /apps/nginx/certification/www.mooreyxia.org.key;
location / {
#proxy_pass http://127.0.0.1:8080;
proxy_pass http://tomcat;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

error_page 404 @error_404;
location @error_404 {
default_type text/html;
charset utf8;
return 200 '你访问的页面可能走丢了!';
}

}

10.0.0.200 Tomcat1 和 201 Tomcat2
[root@ubuntu2204 ROOT]#cat index.jsp
<%@ page language="java" %>
<html>
<head><title>Tomcat1</title></head>
<body>
<h1><font color="red">Tomcat1</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("mooreyxia.org","mooreyxia.org"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>

浏览器访问测试 http://tomcat.mooreyxia.org/ sessionID固定

实现多主机的负载均衡的动静分离

#cat proxy.www.mooreyxia.org.conf
upstream static {
server 10.0.0.8:80;
}
upstream tomcat {
server 10.0.0.18:8080;
}
server {
listen 80;
server_name www.mooreyxia.org;
location / {
proxy_pass http://tomcat;
proxy_set_header Host $http_host;
}
location ~* .*\.(png|jpg|jpeg|gif)$ {
proxy_pass http://static;
proxy_set_header Host $http_host;
}
}

案例2.1 session集群复制 :

复制tomcat主页下的集群配置字段到主配置文件即可

31-WebAPP服务器TomCat及优化

<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" #45564/UDP
frequency="500" #间隔500ms发送
dropTime="3000"/> #故障阈值3s
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto" #监听地址,此项建议修改为当前主机的IP
port="4000" #监听端口
autoBind="100" #如果端口冲突,自动绑定其它端口,范围是4000-
4100
selectorTimeout="5000" #自动绑定超时时长5s
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>

修改 WEB-INF/web.xml

</description>
<distributable/> #添加此行
</web-app>

实验:在 proxy 主机设置 httpd (或nginx)实现后端tomcat主机轮询

[root@proxy ~]#cat /etc/httpd/conf.d/tomcat.conf
<Proxy balancer://tomcat-server>
BalancerMember http://t1.mooreyxia.org:8080 loadfactor=1
BalancerMember http://t2.mooreyxia.org:8080 loadfactor=1
</Proxy>
<VirtualHost *:80>
ServerName proxy.mooreyxia.org
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
ProxyPass / balancer://tomcat-server/
ProxyPassReverse / balancer://tomcat-server/
</VirtualHost>
[root@proxy ~]#systemctl restart httpd

#修改 t1 主机的 conf/server.xml
<Host name="t1.mooreyxia.com" appBase="/data/webapps" autoDeploy="true" >
#其他略去
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="10.0.0.101" #只改此行
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
...

#修改 t2 主机的 conf/server.xml
<Host name="t2.mooreyxia.com" appBase="/data/webapps" autoDeploy="true" >
其他略去
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="10.0.0.102" #只改此行
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
...

#修改t1主机的应用的web.xml文件
[root@t1 ~]#ll /usr/local/tomcat/webapps/ROOT/WEB-INF/
total 4
-rw-r----- 1 tomcat tomcat 1227 Jul 1 05:53 web.xml
[root@t1 ~]#cp -a /usr/local/tomcat/webapps/ROOT/WEB-INF/ /data/webapps/ROOT/
[root@t1 ~]#tree /data/webapps/ROOT/
/data/webapps/ROOT/
├── index.jsp
└── WEB-INF
└── web.xml
1 directory, 2 files
#在倒数第二行加一行
[root@t1 ~]##vim /data/webapps/ROOT/WEB-INF/web.xml
[root@t1 ~]#tail -n3 /data/webapps/ROOT/WEB-INF/web.xml
</description>
<distributable/> #添加此行
</web-app>
#注意权限
[root@t1 ~]#ll /data/webapps/ROOT/WEB-INF/
total 4
-rw-r----- 1 tomcat tomcat 1243 Jan 17 09:37 web.xml
[root@t1 ~]#systemctl restart tomcat

#修改t2主机的应用的web.xml文件
[root@t2 ~]#cp -a /usr/local/tomcat/webapps/ROOT/WEB-INF/ /data/webapps/ROOT/
[root@t2 ~]#vim /data/webapps/ROOT/WEB-INF/web.xml
[root@t2 ~]#tail -n3 /data/webapps/ROOT/WEB-INF/web.xml
</description>
<distributable/> #添加此行
</web-app>
#注意权限
[root@t2 ~]#ll /data/webapps/ROOT/WEB-INF/
total 4
-rw-r----- 1 tomcat tomcat 1243 Jan 17 09:38 web.xml
[root@t2 ~]#systemctl restart tomcat

测试访问 proxy.mooreyxia.org,轮询服务器时sessionID会话保持同一个,宕机一个服务器也正常运作

memcache 编译安装与使用

----------------------------------------------------------------
修改memcached 运行参数,可以使用下面的选项修改/etc/sysconfig/memcached文件
memcached 常见选项
-u username memcached运行的用户身份,必须普通用户
-p 绑定的端口,默认11211
-m num 最大内存,单位MB,默认64MB
-c num 最大连接数,缺省1024
-d 守护进程方式运行
-f 增长因子Growth Factor,默认1.25
-v 详细信息,-vv能看到详细信息
-M 使用内存直到耗尽,不许LRU
-U 设置UDP监听端口,0表示禁用UDP

范例: 非交互式取信息
[root@ubuntu2204 ~]#echo -e "stats\nquit" | nc 10.0.0.202 11211 |awk '/curr_connections/{print $NF}'
2
---------------------------------------------------------------
# Ubuntu 编译安装 memcache
[root@ubuntu2204 opt]#wget http://memcached.org/files/memcached-1.6.17.tar.gz
--2022-12-10 23:49:17-- http://memcached.org/files/memcached-1.6.17.tar.gz
正在解析主机 memcached.org (memcached.org)... 107.170.231.145
正在连接 memcached.org (memcached.org)|107.170.231.145|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度: 1713186 (1.6M) [application/octet-stream]
正在保存至: ‘memcached-1.6.17.tar.gz’

memcached-1.6.17.tar.gz 100%[==========================================================================================>] 1.63M 15.5KB/s 用时 90s

2022-12-10 23:50:47 (18.5 KB/s) - 已保存 ‘memcached-1.6.17.tar.gz’ [1713186/1713186])

[root@ubuntu2204 opt]#ll
总用量 1688
drwxr-xr-x 2 root root 4096 12月 10 23:49 ./
drwxr-xr-x 20 root root 4096 12月 10 00:33 ../
-rw-r--r-- 1 root root 1679 12月 8 02:30 1index.html
-rw-r--r-- 1 root root 1713186 8月 27 08:37 memcached-1.6.17.tar.gz
[root@ubuntu2204 opt]#tar -zxvf memcached-1.6.17.tar.gz
memcached-1.6.17/
memcached-1.6.17/README.md
memcached-1.6.17/memcached.spec
memcached-1.6.17/hash.c
memcached-1.6.17/proxy_xxhash.c
memcached-1.6.17/tls.c
memcached-1.6.17/slab_automove.h
memcached-1.6.17/aclocal.m4
....

[root@ubuntu2204 opt]#ll
总用量 1692
drwxr-xr-x 3 root root 4096 12月 10 23:53 ./
drwxr-xr-x 20 root root 4096 12月 10 00:33 ../
-rw-r--r-- 1 root root 1679 12月 8 02:30 1index.html
drwxrwxr-x 7 wang wang 4096 8月 27 08:37 memcached-1.6.17/
-rw-r--r-- 1 root root 1713186 8月 27 08:37 memcached-1.6.17.tar.gz
[root@ubuntu2204 opt]#cd memcached-1.6.17/
[root@ubuntu2204 memcached-1.6.17]#./configure --prefix=/apps/memcached
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a race-free mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
.....

[root@ubuntu2204 memcached-1.6.17]#make && make install
make all-recursive
make[1]: 进入目录“/opt/memcached-1.6.17”
Making all in doc
make[2]: 进入目录“/opt/memcached-1.6.17/doc”
make all-am
make[3]: 进入目录“/opt/memcached-1.6.17/doc”
make[3]: 对“all-am”无需做任何事。
make[3]: 离开目录“/opt/memcached-1.6.17/doc”
make[2]: 离开目录“/opt/memcached-1.6.17/doc”
make[2]: 进入目录“/opt/memcached-1.6.17”
gcc -DHAVE_CONFIG_H -I. -DNDEBUG -g -O2 -pthread -pthread -Wall -Werror -pedantic -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -MT memcached-memcached.o -MD -MP -MF .deps/memcached-memcached.Tpo -c -o memcached-memcached.o `test -f 'memcached.c' || echo './'`memcached.c
mv -f .deps/memcached-memcached.Tpo .deps/memcached-memcached.Po
......

[root@ubuntu2204 memcached-1.6.17]#cd
[root@ubuntu2204 ~]#tree /apps/memcached/
/apps/memcached/
├── bin
│ └── memcached
├── include
│ └── memcached
│ ├── protocol_binary.h
│ └── xxhash.h
└── share
└── man
└── man1
└── memcached.1

6 directories, 4 files
[root@ubuntu2204 ~]#ln -s /apps/memcached/bin/memcached /usr/local/bin/
[root@ubuntu2204 ~]#memcached
can't run as root without the -u switch
[root@ubuntu2204 ~]#useradd -r -s /sbin/nologin memcached
[root@ubuntu2204 ~]#memcached -u memcached -m 2048 -c 65536 -d --> 默认是前台执行
[root@ubuntu2204 ~]#ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 127.0.0.1:6010 0.0.0.0:*
LISTEN 0 128 127.0.0.1:6011 0.0.0.0:*
LISTEN 0 1024 0.0.0.0:11211 0.0.0.0:*
LISTEN 0 100 *:8080 *:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 128 [::1]:6010 [::]:*
LISTEN 0 128 [::1]:6011 [::]:*
LISTEN 0 1 [::ffff:127.0.0.1]:8005 *:*
LISTEN 0 1024 [::]:11211 [::]:*

#测试
[root@rocky8 ~]#telnet 10.0.0.200 11211
Trying 10.0.0.200...
Connected to 10.0.0.200.
Escape character is '^]'.
stats
STAT pid 10955
STAT uptime 100
STAT time 1670688211
STAT version 1.6.17
....

案例3.1 tomcat和memcached集成在一台主机实现session共享

IP

服务

软件

10.0.0.8

调度器

centos8 Nginx Httpd

10.0.0.200

tomcat

ubuntu2204 JDK8 Tomcat8 memcached

10.0.0.202

tomcat

ubuntu2204 JDK8 Tomcat8 memcached

-------------------------------------------------------------------------------
#10.0.0.200 202 配置
[root@ubuntu2204 ~]#memcached -u memcached -m 2048 -c 65536 -d
[root@ubuntu2204 ~]#ss -nltp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=4317,fd=6),("nginx",pid=4316,fd=6))
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=629,fd=14))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=759,fd=3))
LISTEN 0 128 127.0.0.1:6010 0.0.0.0:* users:(("sshd",pid=11448,fd=7))
LISTEN 0 1024 0.0.0.0:11211 0.0.0.0:* users:(("memcached",pid=11679,fd=22))
LISTEN 0 100 *:8080 *:* users:(("java",pid=758,fd=56))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=759,fd=4))
LISTEN 0 128 [::1]:6010 [::]:* users:(("sshd",pid=11448,fd=5))
LISTEN 0 1 [::ffff:127.0.0.1]:8005 *:* users:(("java",pid=758,fd=65))
LISTEN 0 1024 [::]:11211 [::]:* users:(("memcached",pid=11679,fd=23))
-------------------------------------------------------------------------------
#确认memcached 没有缓存session

python
[root@rocky8 ~]#cat showmemcached.py
#!/usr/bin/python3
import memcache # pip install python-memcached
mc = memcache.Client(['10.0.0.200:11211','10.0.0.202:11211'], debug=True)
#print('-' * 30)
# 查看全部key
for x in mc.get_stats('items'): # stats items 返回 items:5:number 1
print(x)
print('-' * 30)

for x in mc.get_stats('cachedump 5 0'):
print(x)

[root@rocky8 ~]#./showmemcached.py
('10.0.0.200:11211 (1)', {})
('10.0.0.202:11211 (1)', {})
------------------------------
('10.0.0.200:11211 (1)', {})
('10.0.0.202:11211 (1)', {})

-------------------------------------------------------------------------------
#配置nginx proxy策略
[root@rocky8 ~]#cat /apps/nginx/conf/conf.d/tomcat.conf
upstream tomcat {
#ip_hash;
#hash $remote_addr consistent;
# hash $cookie_JSESSIONID consistent;
server 10.0.0.200:8080;
server 10.0.0.202:8080;

}

server {
listen 80;
server_name tomcat.mooreyxia.org;
# location / {
# proxy_pass http://tomcat;
# }

return 302 https://$host$request_uri;
}

server {
listen 443 ssl;
server_name tomcat.mooreyxia.org;
ssl_certificate /apps/nginx/certification/www.mooreyxia.org.pem;
ssl_certificate_key /apps/nginx/certification/www.mooreyxia.org.key;
location / {
#proxy_pass http://127.0.0.1:8080;
proxy_pass http://tomcat;
# proxy_set_header Host $http_host;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

error_page 404 @error_404;
location @error_404 {
default_type text/html;
charset utf8;
return 200 '你访问的页面可能走丢了!';
}

}
-------------------------------------------------------------------------------

配置 tomcat 10.0.0.200 和 202 配置相同
[root@ubuntu2204 ~]#cat /usr/local/tomcat/conf/context.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- The contents of this file will be loaded for each web application -->
<Context>

<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>

<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
-------------------------------------------------

<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:10.0.0.200:11211,n2:10.0.0.202:11211"
failoverNodes="n1"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>

------------------------------------------------
</Context>

#将相关包传到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@ubuntu2204 ~]#ll /usr/local/tomcat/bin/ -t
总用量 2748
drwxr-x--- 2 tomcat tomcat 4096 12月 11 15:39 ./
drwxr-xr-x 9 tomcat tomcat 4096 12月 7 23:50 ../
-rw-r--r-- 1 root root 53259 12月 7 20:57 asm-5.2.jar
-rw-r--r-- 1 root root 586620 12月 7 20:57 jedis-3.0.0.jar
-rw-r--r-- 1 root root 285211 12月 7 20:57 kryo-3.0.3.jar
-rw-r--r-- 1 root root 126366 12月 7 20:57 kryo-serializers-0.45.jar
-rw-r--r-- 1 root root 167294 12月 7 20:57 memcached-session-manager-2.3.2.jar
-rw-r--r-- 1 root root 10967 12月 7 20:57 memcached-session-manager-tc9-2.3.2.jar
-rw-r--r-- 1 root root 5923 12月 7 20:57 minlog-1.3.1.jar
-rw-r--r-- 1 root root 38372 12月 7 20:57 msm-kryo-serializer-2.3.2.jar
-rw-r--r-- 1 root root 55684 12月 7 20:57 objenesis-2.6.jar
-rw-r--r-- 1 root root 72265 12月 7 20:57 reflectasm-1.11.9.jar
-rw-r--r-- 1 root root 473774 12月 7 20:57 spymemcached-2.12.3.jar

[root@ubuntu2204 ~]#systemctl restart tomcat
[root@rocky8 ~]#./showmemcached.py
------------------------------
('10.0.0.200:11211 (1)', {'items:5:number': '1', 'items:5:number_hot': '0',
'items:5:number_warm': '0', 'items:5:number_cold': '1', 'items:5:age_hot': '0',
'items:5:age_warm': '0', 'items:5:age': '1531', 'items:5:evicted': '0',
'items:5:evicted_nonzero': '0', 'items:5:evicted_time': '0',
'items:5:outofmemory': '0', 'items:5:tailrepairs': '0', 'items:5:reclaimed':
'0', 'items:5:expired_unfetched': '0', 'items:5:evicted_unfetched': '0',
'items:5:evicted_active': '0', 'items:5:crawler_reclaimed': '0',
'items:5:crawler_items_checked': '9', 'items:5:lrutail_reflocked': '0',
'items:5:moves_to_cold': '2', 'items:5:moves_to_warm': '0',
'items:5:moves_within_lru': '0', 'items:5:direct_reclaims': '0',
'items:5:hits_to_hot': '0', 'items:5:hits_to_warm': '0', 'items:5:hits_to_cold':
'1', 'items:5:hits_to_temp': '0'})
('10.0.0.202:11211 (1)', {})
------------------------------

3.2 利用 Tomcat Clustering Redis Session Manager 利用 redis 实现session共享

#下载相关文件并解压缩
wget https://github.com/ran-jit/tomcat-cluster-redis-sessionmanager/
releases/download/3.0.1.1/tomcat-cluster-redis-session-manager.zip
unzip /opt/tomcat-cluster-redis-session-manager.zip -d /opt
#复制jar包到tomcat/lib目录中
cp /opt/tomcat-cluster-redis-session-manager/lib/* /usr/local/tomcat/lib/
chown -R tomcat.tomcat /usr/local/tomcat/lib
#复制redis配置文件到tomcat/conf目录中
cp /opt/tomcat-cluster-redis-session-manager/conf/redis-data-cache.properties
/usr/local/tomcat/conf/
#修改redis配置信息
vim /usr/local/tomcat/conf/redis-data-cache.properties
#修改下面两行
redis.hosts=10.0.0.100:6379 #指向redis服务器地址
redis.password=123456
#添加两行配置文件在 tomcat/conf/context.xml
vim /usr/local/tomcat/conf/context.xml
#在最后一行前加下两行
<Valve className="tomcat.request.session.redis.SessionHandlerValve" />
<Manager className="tomcat.request.session.redis.SessionManager" />
</Context> #此是最后一行
#修改session过期时间为60m,默认30m,此步可选
vim /usr/local/tomcat/conf/web.xml
<session-config>
<session-timeout>60</session-timeout>
</session-config>
#重启服务
systemctl restart tomcat
#nginx配置反向代理和均衡负载
vim /etc/nginx/conf.d/session.conf
upstream tomcat-server {
server t1.mooreyxia.org:8080;
server t2.mooreyxia.org:8080;
}
server {
listen 80;
server_name www.mooreyxia.org;
location / {
proxy_pass http://tomcat-server;
proxy_set_header Host $http_host;
}
}
#tomcat测试页面
cat /data/webapps/ROOT/test.jsp
<%@ page import="java.util.*" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>tomcat test</title>
</head>
<body>
<h1> Tomcat1 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>

Tomcat 性能优化

由于Tomcat的运行依赖于JVM,从虚拟机的角度把Tomcat的调整分为外部环境调优 JVM 和 Tomcat 自身调优两部分

JVM优化主要针对的是堆空间的使用问题,RunTime Data Areas

分代堆内存GC策略

范例: 查看JVM内存分配情况
[root@centos8 ~]#cat Heap.java
public class Heap {
public static void main(String[] args){
//返回JVM试图使用的最大内存,字节单位
long max = Runtime.getRuntime().maxMemory();
//返回JVM初始化总内存
long total = Runtime.getRuntime().totalMemory();
System.out.println("max="+max+"字节\t"+(max/(double)1024/1024)+"MB");
System.out.println("total="+total+"字节\t"+(total/(double)1024/1024)+"MB");
}
}
[root@centos8 ~]#javac Heap.java
[root@centos8 ~]#java -classpath . Heap
max=243269632字节 232.0MB
total=16252928字节 15.5MB
[root@centos8 ~]#java -XX:+PrintGCDetails Heap
max=243269632字节 232.0MB
total=16252928字节 15.5MB
Heap
def new generation total 4928K, used 530K [0x00000000f1000000,0x00000000f1550000, 0x00000000f6000000)
eden space 4416K, 12% used [0x00000000f1000000, 0x00000000f1084a60,0x00000000f1450000)
from space 512K, 0% used [0x00000000f1450000, 0x00000000f1450000,0x00000000f14d0000)
to space 512K, 0% used [0x00000000f14d0000, 0x00000000f14d0000,0x00000000f1550000)
tenured generation total 10944K, used 0K [0x00000000f6000000,0x00000000f6ab0000, 0x0000000100000000)
the space 10944K, 0% used [0x00000000f6000000, 0x00000000f6000000,0x00000000f6000200, 0x00000000f6ab0000)
Metaspace used 2525K, capacity 4486K, committed 4864K, reserved 1056768K
class space used 269K, capacity 386K, committed 512K, reserved 1048576K
[root@centos8 ~]#echo "scale=2;(4928+10944)/1024" |bc
15.50
#说明年轻代+老年代占用了所有heap空间, Metaspace实际不占heap空间,逻辑上存在于Heap

Heap空间GC策略

#垃圾回收基本算法
1. 标记-清除 Mark-Sweep
分垃圾标记阶段和内存释放两个阶段
标记阶段,找到所有可访问对象打个标记。清理阶段,遍历整个堆
对未标记对象(即不再使用的对象)逐一进行清理。
优点:算法简单
缺点:标记-清除最大的问题会造成内存碎片,但是不浪费空间,效率较高(如果对象较多时,逐一删除效率也会受到影响)
2. 标记-压缩 (压实)Mark-Compact
分垃圾标记阶段和内存整理两个阶段
标记阶段,找到所有可访问对象打个标记。
内存清理阶段时,整理时将对象向内存一端移动,整理后存活对象连续的集中在内存一端。
标记-压缩算法好处是整理后内存空间连续分配,有大段的连续内存可分配,没有内存碎片。
缺点:是内存整理过程有消耗,效率相对低下
3. 复制 Copying
先将可用内存分为大小相同两块区域A和B,每次只用其中一块,比如A。当A用完后,则将A中存活的对象复制到B。复制到B的时候连续的使用内存,最后将A一次性清除干净。
好处是没有碎片,复制过程中保证对象使用连续空间,且一次性清除所有垃圾,所以即使对象很多,收回效率也很高
缺点:是比较浪费内存,只能使用原来一半内存,因为内存对半划分了,复制过程毕竟也是有代价。

#年轻代回收 Minor GC
1. 起始时,所有新建对象(特大对象直接进入老年代)都出生在eden,当eden满了,启动GC[Mark-Sweep]。这个称为Young GC 或者 Minor GC。
2. 先标记eden存活对象,然后将存活对象复制到s0(假设本次是s0,也可以是s1,它们可以调换),eden剩余所有空间都清空。GC[Copying]完成。
3. 继续新建对象,当eden再次满了,启动GC[Copying]。
4. 先同时标记eden和s0中存活对象,然后将存活对象复制到s1。将eden和s0清空,此次GC[Copying]完成
5. 继续新建对象,当eden满了,启动GC[Copying]。
6. 先标记eden和s1中存活对象,然后将存活对象复制到s0。将eden和s1清空,此次GC[Copying]完成以后就重复上面的步骤。
通常场景下,大多数对象都不会存活很久,而且创建活动非常多,新生代就需要频繁垃圾回收。但是,如果一个对象一直存活,它最后就在from、to来回复制,如果from区中对象复制次数达到阈值(默认15次,CMS为6次,可通过java的选项 -XX:MaxTenuringThreshold=N 指定),就直接复制到老年代。

#老年代回收 Major GC[Mark-Compact]
进入老年代的数据较少,所以老年代区被占满的速度较慢,所以垃圾回收也不频繁。
如果老年代也满了,会触发老年代GC,称为Old GC或者 Major GC。
由于老年代对象一般来说存活次数较长,所以较常采用标记-压缩算法。
当老年代满时,会触发 Full GC,即对所有"代"的内存进行垃圾回收,STW,GC线程工作时,停止所有工作的线程,称为Stop The World
Minor GC比较频繁,Major GC较少。但一般Major GC时,由于老年代对象也可以引用新生代对象,所以先进行一次Minor GC,然后在Major GC会提高效率。可以认为回收老年代的时候完成了一次FullGC。所以可以认为 MajorGC = FullGC

GC方式

按工作模式不同:指的是GC线程和工作线程是否一起运行

  • 独占垃圾回收器:只有GC在工作,STW 一直进行到回收完毕,工作线程才能继续执行
  • 并发垃圾回收器:让GC线程垃圾回收某些阶段可以和工作线程一起进行,如:标记阶段并行,回收阶段仍然串行

按回收线程数:指的是GC线程是否串行或并行执行

  • 串行垃圾回收器:一个GC线程完成回收工作
  • 并行垃圾回收器:多个GC线程同时一起完成回收工作,充分利用CPU资源

调整策略

对JVM调整策略应用极广

  • 在WEB领域中Tomcat等
  • 在大数据领域Hadoop生态各组件
  • 在消息中间件领域的Kafka等
  • 在搜索引擎领域的ElasticSearch、Solr等

注意: 在不同领域和场景对JVM需要不同的调整策略

  • 减少 STW 时长,串行变并行
  • 减少 GC 次数,要分配合适的内存大小

一般情况下,大概可以使用以下原则:

  • 客户端或较小程序,内存使用量不大,可以使用串行回收
  • 对于服务端大型计算,可以使用并行回收
  • 大型WEB应用,用户端不愿意等待,尽量少的STW,可以使用并发回收

垃圾收集器设置

优化调整Java 相关参数的目标: 尽量减少FullGC和STW
通过以下选项可以单独指定新生代、老年代的垃圾收集器
-server 指定为Server模式,也是默认值,一般使用此工作模式
-XX:+UseSerialGC
运行在Client模式下,新生代是Serial, 老年代使用SerialOld
-XX:+UseParNewGC
新生代使用ParNew,老年代使用SerialOld
-XX:+UseParallelGC
运行于server模式下,新生代使用Parallel Scavenge, 老年代使用 Parallel Old
-XX:+UseParallelOldGC
新生代使用Paralell Scavenge, 老年代使用Paralell Old,和上面-XX:+UseParallelGC 相同
-XX:ParallelGCThreads=N,在关注吞吐量的场景使用此选项增加并行线程数
-XX:+UseConcMarkSweepGC
新生代使用ParNew, 老年代优先使用CMS,备选方式为Serial Old
响应时间要短,停顿短使用这个垃圾收集器
-XX:CMSInitiatingOccupancyFraction=N,N为0-100整数表示达到老年代的大小的百分比多
少触发回收 默认68
-XX:+UseCMSCompactAtFullCollection 开启此值,在CMS收集后,进行内存碎片整理
-XX:CMSFullGCsBeforeCompaction=N 设定多少次CMS后,进行一次内存碎片整理
-XX:+CMSParallelRemarkEnabled 降低标记停顿

范例:查看默认垃圾回收器
[root@ubuntu2204 ~]#java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=48277824 -XX:MaxHeapSize=772445184 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
java version "1.8.0_351"
Java(TM) SE Runtime Environment (build 1.8.0_351-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.351-b10, mixed mode)

Tomcat 性能优化生产环境配置案例

#内存空间优化参数
JAVA_OPTS="-server -Xms4g -Xmx4g -XX:NewSize= -XX:MaxNewSize= "
-server:服务器模式
-Xms:堆内存初始化大小
-Xmx:堆内存空间上限
-XX:NewSize=:新生代空间初始化大小
-XX:MaxNewSize=:新生代空间最大值

实例:
[root@centos8 ~]#vim /usr/local/tomcat/bin/catalina.sh
JAVA_OPTS="-server -Xms4g -Xmx4g -Xss512k -Xmn1g -
XX:CMSInitiatingOccupancyFraction=65 -XX:+AggressiveOpts -XX:+UseBiasedLocking -
XX:+DisableExplicitGC -XX:MaxTenuringThreshold=10 -XX:NewRatio=2 -
XX:PermSize=128m -XX:MaxPermSize=512m -XX:CMSFullGCsBeforeCompaction=5 -
XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -
XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -
XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods"
#一台tomcat服务器并发连接数不高,生产建议分配物理内存通常4G到8G较多,如果需要更多连接,一般会利用虚拟化技术实现多台tomcat

线程池调整 默认连接最大数200 改2000
[root@centos8 ~]#vim /usr/local/tomcat/conf/server.xml
......
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000"
redirectPort="8443" maxThreads="2000"/>
......

常用属性:
connectionTimeout :连接超时时长,单位ms
maxThreads:最大线程数,默认200
minSpareThreads:最小空闲线程数
maxSpareThreads:最大空闲线程数
acceptCount:当启动线程满了之后,等待队列的最大长度,默认100
URIEncoding:URI 地址编码格式,建议使用 UTF-8
enableLookups:是否启用客户端主机名的DNS反向解析,缺省禁用,建议禁用,就使用客户端IP就行
compression:是否启用传输压缩机制,建议 "on",CPU和流量的平衡
compressionMinSize:启用压缩传输的数据流最小值,单位是字节
compressableMimeType:定义启用压缩功能的MIME类型text/html, text/xml, text/css,
text/javascript

我是moore,最近阳性转阴,大家也要注意身体,一起加油!