爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      WebAPP服务器TomCat及优化

      首页 知识中心 服务器 文章详情页

      WebAPP服务器TomCat及优化

      2023-06-27 10:00:13 阅读次数:91

      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-.tar.gz"

      JDK_FILE="jdk--linux-x64.tar.gz"

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

      color () {
      RES_COL=60
      MOVE_TO_COL="echo -en \\033[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

      echo -n $" OK "
      elif [ $1 = "failure" -o $1 = "1" ] ;then

      echo -n $"FAILED"
      else

      echo -n $"WARNING"
      fi

      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 .key -subj $SUBJECT -out .csr

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

      chmod 600 .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>/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 ><%=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,最近阳性转阴,大家也要注意身体,一起加油!

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.51cto.com/mooreyxia/5938269,作者:mooreyxia,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:网络协议与管理配置

      下一篇:Linux下自动分割Nginx日志文件(一)-----自定义脚本和定时任务

      相关文章

      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5224821

      查看更多

      热门标签

      服务器 linux 虚拟机 Linux 数据库 运维 网络 日志 数据恢复 java python 配置 nginx centos mysql
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号