1、安全优化

项目配置说明
tomcat shutdown端口的包含改为其他的特殊端口,暗号也要修改。例如:
<server port=”8115″ shutdown=”hahf8755″>
ajp连接端口禁用从tomcat8.5开始默认禁用8009端口,用于与Apache进行连接
禁用管理端把管理端相关配置、文件、目录清理掉。
webapps下面的docs、example、host-manager、manager目录
如果开启较为危险
降权启动(监牢模式)通过普通用户运行与管理服务端口大于1024。1024以内的端口为特权端口,只能root使用。
文件列表访问控制类似于nginx autoindex,是否默认开启列出站点目录的功能,默认关闭
tomcat版本信息隐藏遇到4xx、5xx错误的时候,显示指定页面,不包含服务器版本信息
tomcat web服务隐藏http响应头里面的信息,connector 8080部分增加头部信息,Server=信息
访问控制类似于nginx,使用allow、deny一般推荐使用nginx限制
启停脚本权限回收tomcat/bin目录,脚本,700/500,从8.5开始750权限最小化
访问日志格式规范tomcat server.xml文件中配置访问日志格式参考nginx
忽略一些暴露敏感信息的头部信息(响应头)lnmp\lnmt环境中程序代码会在响应头中加入服务版本的信息

案例1:用普通用户启动tomcat

默认。tomcat目录属主属组为root,需要改为普通用户,比如为tomcat

[root@web01 ~]#useradd tomcat
[root@web01 ~]#chown -R tomcat.tomcat /app/tools/tomcat

使用普通用户tomcat运行tomcat

[root@web01 ~]#su - tomcat -c "/app/tools/tomcat/bin/startup.sh"

把该命令写入/etc/rc.local文件,添加可执行权限,就可以开机执行。

案例2:tomcat web服务隐藏

在connecor 8080 部分增加Server信息,例如:

[root@web01 ~]#vim  /app/tools/tomcat/conf/server.xml
 <Connector port="8080" protocol="HTTP/1.1"
               Server="Nginx/1.24.1"   #增加Server
               connectionTimeout="20000"
               redirectPort="8443" />

重启tomcat,访问:

[root@web01 ~]#curl -I 192.168.10.7:8080
HTTP/1.1 200 
X-ZrLog: 2.2.1
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 09 Jul 2023 02:54:52 GMT
Server: Nginx/1.24.1

[root@web01 ~]#

显示:Nginx/1.24.1

案例3:屏蔽服务端软件或代码的版本信息

在nginx中配置proxy_hide_header XXX软件或代码名称

如果是php,则fastcgi_hide_header X-Powered-By;

可以在http{}、server{}、location{}区域设置

2、性能优化

io模型优化

线程数量

配置禁用DNS反向解析

压缩的配置(nginx)

2.1 io模型优化

类似于nginx的同步、异步模型

io模型说明
BIOBlocked IO,阻塞,同步模型。Tomcat7及之前版本默认是BIO
NIO(NIO1、NIO2)New IO,非阻塞,异步模型,tomcat8开始默认是nio
APR应对高并发

应用建议:使用默认即可

案例:设为nio2

Connector port="8080"
原始的:protocol=“HTTP/1.1"
修改后:protocol="org.apache.coyote.http11.http11Nio2Protocol"

设置apr模型:

1、安装依赖
apr-devel、tomcat-native
2、修改
protocol="org.apache.coyote.http11.http11AprProtocol"

2.2 线程数量

maxThreads="500":最大的线程数量,200-400之间,具体的数值需要进行压力测试
acceptCout="500":当达到最大线程数量的时候,队列长度多长。acceptCount一般与maxThreads一致
acceptorThreadCount="2":请求分成几个队伍进行,数值上与cpu核心数一致或2倍,默认是1
minSpareThreads="10":空闲时候最小的线程数量,不忙的时候,最少保留几个。

在server.xml的Connector中设置,例如:

[root@web01 ~]#vim /app/tools/tomcat/conf/server.xml
 <Connector port="8080" protocol="HTTP/1.1"
               maxThreads="200"
               minSpareThreads="2"
.....

登录管理端就可以查看到设置后的内容

相关值的建议,搭建好环境,部署应用,通过压力测试确定

测试软件:ab,loadrunner,jmter….

2.3 DNS、压缩

在<Connector port=”8080″ protocol=”HTTP/1.1″中配置

禁用dns反向解析功能,加速访问。
enableLookups="false"

#类型与nginx gzip压缩(推荐在nginx配置gzip  brotil(第三方模块))
compression="on" :开启toncat压缩功能,静态文本资源 html jss  css
compressionSize="2048" :大于2048字节的文件才会被压缩
compressableMimeType="text/html,text/plain,text/css,application/javascritp,application/json,application/x-font-ttf,application/s-font-otf"

3、jvm优化

在catalina.sh文件中配置:

设置jvm内存大小

配置gc日志(垃圾回收)

配置自动dump配置

a)配置jvm内存大小、gc日志

#设置jvm初始内存大小(默认:物理内存的1/64)jvm最大内存大小(默认:物理内存的1/4)
#修改catalina.sh文件
JAVA_OPTS='-Xms1024m Xmx1024m -Xloggc:/var/log/tomcat_gc.log'

选项解释:

-Xms:jvm初始内存大小
-Xmx:jvm最大内存
  方案1:一般,-Xmx是-Xms的2倍
  方案2:-Xms 与 -Xmx 一致,防止重复gc垃圾回收
gc:garbage collect,垃圾回收,定期清理jvm内存
-Xloggc:/var/log/tomcat_gc.log:垃圾回收的日志

b)配置自动dump

配置自动dump弄能(jvm发生异常,自动导出jvm内存镜像)

-XX:+HeapDumpOnOutOfMemoryError  #OOM故障,开启导出jvm镜像功能,用于java/tomcat加载应用故障,内存不足
-XX:HeapDumpPath=/app/tools/tomcat/temp/oom.hprof #指定输出到哪里

oom:out of memory,内存不足

最终:

JAVA_OPTS='-Xms1024m Xmx1024m -Xloggc:/var/log/tomcat_gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/app/tools/tomcat/temp/oom.hprof'

5、Java前后端分离项目

tomcat动静分离,提取出静态资源

静态资源:前端(html、css、js)
后端:Java、php、Python、golang....连接数据库

前后端分离:拆分前端部分和后端部分,一般前后端通过API接口的进行连接

API应用程序接口:开发人员写好的,可以直接调用的代码,使用的人员不需要关注功能如何实现,直接使用即可。

·调用天气预报API接口:

curl "https://v0.yiketianqi.com/api?unescape=1&version=v91&appid=43656176&appsecret=I42og6Lm&ext=&cityid=&city="

架构:

5.1 前端分离

5.2项目

1)概述
主机环境
web01前端(nginx)+后端(jdk)
db02数据库mysql8.0,二进制安装,/app/tools/mysql/,数据目录/app/data/3306/
2)数据库准备

数据库端:db02,ip:192.168.10.52、172.16.1.52

1、解压

提前下载好mysql8.0二进制包:mysql-8.0.28-linux-glibc2.12-x86_64.tar.xz

#1、创建相关目录
[root@db02 ~]#mkdir -p /app/tools/ /app/data/3306/
#2、解压并创建软连接
[root@db02 ~]#tar xf mysql-8.0.28-linux-glibc2.12-x86_64.tar.xz -C /app/tools/
[root@db02 ~]#ln -s /app/tools/mysql-8.0.28-linux-glibc2.12-x86_64/ /app/tools/mysql
#3、安装依赖
[root@db02 ~]#yum install -y ncurses ncurses-devel libaio-devel openssl openssl-devel

修改数据目录/app/data/3306/属主属组为:mysql

[root@db02 ~]#chown -R mysql.mysql /app/data/3306/
2、创建数据库用户

创建数据库虚拟用户mysql

[root@db02 ~]#useradd -s /sbin/nologin -M mysql
3、配置数据库

配置文件:/etc/my.cnf

[root@db02 ~]#vim /etc/my.cnf
[mysqld]
#用户
user=mysql
#安装目录
basedir=/app/tools/mysql/
#数据目录
datadir=/app/data/3306/
port=3306
socket=/tmp/mysql.sock

[client]
socket=/tmp/mysql.sock

修改该文件的属主属组为mysql

[root@db02 ~]#chown mysql.mysql /etc/my.cnf

4、配置环境变量

[root@db02 ~]#echo 'export PATH=/app/tools/mysql/bin:$PATH' >> /etc/profile
[root@db02 ~]#source /etc/profile
5、初始化数据库

注意:只执行一次即可

[root@db02 ~]#mysqld --initialize-insecure --user=mysql --basedir=/app/tools/mysql --datadir=/app/data/3306

2023-07-09T08:02:39.031799Z 0 [System] [MY-013169] [Server] /app/tools/mysql-8.0.28-linux-glibc2.12-x86_64/bin/mysqld (mysqld 8.0.28) initializing of server in progress as process 2367
2023-07-09T08:02:39.545516Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2023-07-09T08:02:40.940703Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2023-07-09T08:02:46.239780Z 6 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
6、启动

准备启动文件:

[root@db02 ~]#cp /app/tools/mysql/support-files/mysql.server /etc/init.d/mysqld
[root@db02 ~]#chmod +x /etc/init.d/mysqld

启动:

[root@db02 ~]#systemctl daemon-reload
[root@db02 ~]#systemctl start mysqld
[root@db02 ~]#systemctl enable mysqld
3)创建项目数据库

创建名为exam的数据库,指定字符集为:utf8mb4

授权用户为exam,密码为1

[root@db02 ~]#mysql
#创建数据库
mysql> create database exam charset utf8mb4;
#创建exam用户
mysql> create user exam@'172.16.1.%' identified with mysql_native_password by '1';
#授权
mysql> grant all on exam.* to exam@'172.16.1.%';

从mysql8.0开始,创建用户和授权要分开进行,identified设置密码要加上with mysql_native_password参数

导入数据(创建表、导入数据)

很多应用需要手动导入

[root@db02 ~]#mysql exam < xzs-mysql.sql
4)部署后端

1、创建项目目录

[root@web01 ~]#mkdir -p /app/code/exam/{front,backend}

2、解压项目代码

解压到backend目录

[root@web01 ~]#cd /app/code/exam/backend/
[root@web01 /app/code/exam/backend]#cp /root/xzs-3.9.0.jar .

配置文件内容:

[root@web01 ~]#vim /app/code/exam/backend/application-prod.yml
logging:
  path: /var/log/xzs
spring:
  datasource:
    url: jdbc:mysql://172.16.1.52:3306/exam?useSSL=false&useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true&allowMultiQueries=true
    username: exam
    password: 1
    driver-class-name: com.mysql.cj.jdbc.Driver

执行:

[root@web01 /app/code/exam/backend]#java -Duser.timezone=Asia/Shanghai -jar -Dspring.profiles.active=prod xzs-3.9.0.jar

说明:

-Dspring.profiles.active=prod: jar包目录同层的application-prod.yml application.yml

后台执行:

nohup java -Duser.timezone=Asia/Shanghai -jar -Dspring.profiles.active=prod xzs-3.9.0.jar > start.log 2>&1 &

浏览器打开:192.168.10.7:8000

如下:

学生端:192.168.10.7:8000/student,用户名,student,密码:123456

管理员:192.168.10.7:8000/admin,用户名:admin,密码:123456

其他可以加入的后端的配置

server:
  port:8000
  undertow:
    io-threads: 16
    worker-threads: 4000
    buffer-size: 1024
    direct-buffers: true
  compression:
    enabled: true
    min-response-size: 1
#loggin logback
logging:
  #config: classpath:logback-spring.xml
  #file: xzs
  path: /var/log/xzs
#mybatis
mybatis:
  mapper-locations: classpath:/mapper/*.xml
  configuration:
    log-prefix: repository
system:
  security-ignore-urls:
    - /api/wx/**
    - /api/admin/upload/configAndUpload
    - /api/admin/upload/auth
    - /api/student/user/register
  pwdkwy:
    publicKey:
    privateKey: 
  wx:
    appid: wxxxx444
    secret: 4d1gg44
    token-to-live: 12h
    security-ignore-urls:
      - /api/wx/student/auth/bind
      - /api/wx/student/auth/checkBind
      - /api/wx/student/user/register
 
 #连接对象存储,七牛
 qn:
    url: http://xzs.file.mindskip.net #域名要改为自己的
    bucket: mindskip
    access-key: adkidd455
    secret-key: ddikd4
    
#mybatis page helper
pagehelper:
  autoDialect: true
  closeConn: true
  reasonable: true
#mybatis datasource default HikariPool
spring:
#会话共享
  session:
    store-type: redis
    #配置数据库
    datasource:
    url: jdbc:mysql://172.16.1.52:3306/exam?useSSL=false&useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true&allowMultiQueries=true
    username: exam
    password: 1
    driver-class-name: com.mysql.cj.jdbc.Driver
 #Redis地址
  redis:
    url: 127.16.1.51
    timeout: 10000
    database: 0
    lettuce:
      pool:
        max-active: 8
        max-wait: -1
        max-idle: 8
        min-idle: 1
  cache:
    type: redis
    redis:
      time-to-live: 12h
#runningtime environment
profiles:
  active: dev
5)部署前端

nginx站点配置文件

[root@web01 ~]#vim /etc/nginx/conf.d/exam.conf
server {
  listen 80;
  server_name admin.exam.com;
  root /app/code/exam/front/admin;
  location / {
     index index.html;
  }
  location /api/ {
     proxy_pass http://localhost:8000;
  }
}

server {
  listen 80;
  server_name stu.exam.com;
  root /app/code/exam/front/student;
  location / {
     index index.html;
  }
  location /api/ {
     proxy_pass http://localhost:8000;
  }
}

解压前端代码到/app/code/exam/front目录

[root@web01 ~]#unzip exam-web-前端.zip
[root@web01 ~]#mv exam-web-前端/* /app/code/exam/front/
[root@web01 ~]#cd /app/code/exam/front/
[root@web01 /app/code/exam/front]#ls
admin  student

重启nginx,Windows本地做hosts解析:

浏览器打开:admin.exam.com

浏览器打开:stu.exam.com

如下: