Nginx: Tomcat deployment and optimization (2)

1. Tomcat optimization

  • The default configuration under the default installation of Tomcat is not suitable for the production environment. It will frequently experience suspended animation and need to be restarted. Only through continuous stress testing and optimization can it run at the highest efficiency and stably. Optimization mainly includes three aspects, namely, operating system optimization (kernel parameter optimization) , Tomcat configuration file parameter optimization , and Java virtual machine (JVM) tuning . One of the hardest to understand is JVM tuning.

1.1 Kernel parameter optimization

  • The kernel parameter optimization of Tomcat is similar to that of Nginx, and it is carried out in the /etc/security/limits.conf/ file and /etc/sysctl.conf/.
vim /etc/security/limits.conf
tomcat soft nofile 65536
tomcat hard nofile 65536
tomcat soft nproc 2048
tomcat hard nproc 2048

vim /etc/sysctl.conf/
# 开启 TCP/IP 高级拥塞控制
net.ipv4.tcp_congestion_control = cubic

# 开启 TCP 快速打开
net.ipv4.tcp_fastopen = 3

# 开启 TCP KeepAlive
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3

# 开启 TCP/IP 端口范围动态分配
net.ipv4.ip_local_port_range = 1024 65535

# 开启 TCP SYN Cookie
net.ipv4.tcp_syncookies = 1

# 增加系统内存页缓存
vm.min_free_kbytes = 65536
vm.swappiness = 10
#注意:修改以上参数前请仔细了解每个参数的作用和风险,以免出现系统不稳定或安全问题。

1.2 Tomcat configuration file parameter optimization

  • vim /usr/local/tomcat/conf/server.xml
name illustrate
maxThreads Tomcat uses threads to process each request it receives. This value represents the maximum number of threads that Tomcat can create. The default value is 200
minSpareThreads The minimum number of idle threads, the number of initialization threads when Tomcat starts, means that so many idle threads are waiting even if no one is using it, the default value is 10
maxSpareThreads The maximum number of spare threads. Once the created threads exceed this value, Tomcat will close the socket threads that are no longer needed. The default value is -1 (unlimited), generally do not need to specify
connnectionTimeout Network connection timeout, unit: millisecond, setting it to 0 means never timeout, this setting has hidden dangers. Usually the default is 20000 milliseconds
enableLookups Whether to check the domain name to return the host name of the remote host, the value is: true or false, if it is set to false, it will return the IP address directly, in order to improve the processing capacity, it should be set to false
disableUploadTimeout Whether to use a timeout mechanism when uploading. should be set to true
connectionUploadTimeout Upload timeout time. After all, file upload may take more time. This parameter needs to be adjusted according to your own business needs, so that the Servlet has a longer time to complete its execution. It needs to be used together with the previous parameter. take effect
acceptCount Specifies the maximum queue length of incoming connection requests when all available threads for processing requests are used. Requests exceeding this number will not be processed. The default is 100
compression Whether to perform GZIP compression on the response data, off means to prohibit compression, on means to allow compression (text will be compressed), force means to compress in all cases, the default value is off. After compressing the data, the page size can be effectively reduced, generally by about 1/3, thus saving bandwidth
compressionMinSize Indicates the minimum value of the compressed response. Only when the size of the response message is greater than this value, the message will be compressed. If the compression function is enabled, the default value is 2048
compressableMimeType Compression type, specify which types of files are compressed
noCompressionUserAgents=“gozilla, traviata” Compression is not enabled for the following browsers

如果已经对代码进行了动静分离,静态页面和图片等数据就不需要 Tomcat 处理了,那么也就不需要在 Tomcat 中配置压缩了。因为这里只有一台 Tomcat 服务器,而且压测的是Tomcat 首页,会有图片和静态资源文件,所以这里启用压缩。

1.3 Java Virtual Machine (JVM) Tuning

环境规格以 2C4G 为例

配置添加在 Tomcat 的 bin 目录下 catalina.sh 里,位置在 cygwin=false 前。

vim /usr/local/tomcat/bin/catalina.sh
......
JAVA_OPTS="$JAVA_OPTS -server -Xms2048m -Xmx2048m -Xmn768m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/tomcat/temp/oom.hprof -XX:ParallelGCThreads=2 -XX:PermSize=1024m -XX:MaxPermSize=1024m -Djava.awt.headless=true -XX:+DisableExplicitGC" 

cygwin=false

insert image description here


参数说明:
-server:一定要作为第一个参数,在多个CPU时性能佳

-Xms:堆内存的初始大小,是分配JVM的初始内存,默认为物理内存的1/64。一般来讲,此值设的大点,程序会启动的快一点。

-Xmx:堆内存的最大大小,是分配JVM的最大内存,默认为物理内存的1/4。如果程序运行需要占用更多的内存,超出了这个设置值,就会抛出OutOfMemory异常。
----------------------------------------------------
默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。
因此建议-Xms与-Xmx设成一样的值,均设为物理内存的一半。其目的是为了避免在java每次GC(垃圾回收机制清理堆区)后需要重新调整堆的大小而浪费资源。
----------------------------------------------------

-Xmn:堆内新生代的大小,通过这个值也可以得到老生代的大小:-Xmx减去-Xmn。官方推荐配置为整个堆的 3/8。
----------------------------------------------------
●堆区进一步细化分为:新生代、中生代、老生代。
●java中每新new一个对象所占用的内存空间就是新生代的空间,当java垃圾回收机制对堆区进行资源回收后,那些新生代中没有被回收的资源将被转移到中生代,中生代的被转移到老生代。
●整个JVM堆大小 = 新生代大小 + 老生代大小 + 永久代大小
----------------------------------------------------

-Xss:设置每个线程可使用的内存大小,即栈的大小。一般情况下,设置256k就足够了,此配置将会影响此进程中并发线程数的大小。

-XX:ParallelGCThreads:配置并行收集器的线程数,即:同时有多少个线程一起进行垃圾回收。当 CPU 数量小于8,此值建议配置等于 CPU 数量。

-XX:PermSize:设置非堆内存初始值,即持久代内存大小,默认是物理内存的1/4

-XX:MaxPermSize:最大非堆内存的大小,即最大持久代内存大小,默认是物理内存的1/4
----------------------------------------------------
●非堆区内存是不会被java垃圾回收机制进行处理的,且最大堆内存与最大非堆内存的和不能超出操作系统的可用内存。
●XMX和XMS设置一样大,MaxPermSize和MinPermSize设置一样大,这样可以减轻伸缩堆大小带来的压力。
----------------------------------------------------

-XX:+HeapDumpOnOutOfMemoryError:表示当JVM发生OOM时,自动生成DUMP文件

-XX:HeapDumpPath:表示生成DUMP文件的路径

-XX:+UseParNewGC:对新生代采用多线程并行回收,缩短垃圾收集的时间

-XX:+UseConcMarkSweepGC:并发标记清除收集器,它是老年代的收集算法,缩短垃圾收集的时间

-XX:+DisableExplicitGC:禁止调用System.gc(),防止误调用gc方法导致系统的 JVM 大起大落而使系统响应时间严重降低。

-Djava.awt.headless=true:免避在 Linux/Unix 环境下 Web 网页不能正常显示图片

-XX:+CMSParallelRemarkEnabled:启用并行标记,降低标记停顿

-XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0:这两个参数默认值就是这样的,表示触发FullGC时压缩堆,优化内存碎片

-XX:CMSInitiatingOccupancyFraction=70:在应用程序使用70%完内存后开始CMS垃圾收集

2. Nginx+Tomcat load balancing, dynamic and static separation

insert image description here

Nginx 服务器:192.168.119.10:80
Tomcat服务器1:192.168.119.3:80
Tomcat服务器2:192.168.119.4:8080  192.168.119.4:8081

1.部署Nginx 负载均衡器
systemctl stop firewalld
setenforce 0

yum -y install pcre-devel zlib-devel openssl-devel gcc gcc-c++ make

useradd -M -s /sbin/nologin nginx

cd /opt
tar zxvf nginx-1.12.0.tar.gz -C /opt/

cd nginx-1.12.0/
./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-file-aio \									#启用文件修改支持
--with-http_stub_status_module \					#启用状态统计
--with-http_gzip_static_module \					#启用 gzip静态压缩
--with-http_flv_module \							#启用 flv模块,提供对 flv 视频的伪流支持
--with-http_ssl_module								#启用 SSL模块,提供SSL加密功能
--with-stream										#启用 stream模块,提供4层调度
make && make install

ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/

vim /lib/systemd/system/nginx.service
[Unit]
Description=nginx
After=network.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStart=/usr/local/nginx/sbin/nginx
ExecrReload=/bin/kill -s HUP $MAINPID
ExecrStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target

chmod 754 /lib/systemd/system/nginx.service
systemctl start nginx.service
systemctl enable nginx.service


2.部署2台Tomcat 应用服务器
systemctl stop firewalld
setenforce 0

tar zxvf jdk-8u91-linux-x64.tar.gz -C /usr/local/

vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.8.0_91
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:${JRE_HOME}/bin:$PATH

source /etc/profile

tar zxvf apache-tomcat-8.5.16.tar.gz

mv /opt/apache-tomcat-8.5.16/ /usr/local/tomcat

/usr/local/tomcat/bin/shutdown.sh 
/usr/local/tomcat/bin/startup.sh

netstat -ntap | grep 8080

3.动静分离配置
(1)Tomcat1 server 配置
mkdir /usr/local/tomcat/webapps/test
vim /usr/local/tomcat/webapps/test/index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>JSP test1 page</title>   #指定为 test1 页面
</head>
<body>
<% out.println("动态页面 1,http://www.test1.com");%>
</body>
</html>


vim /usr/local/tomcat/conf/server.xml
#由于主机名 name 配置都为 localhost,需要删除前面的 HOST 配置
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
	<Context docBase="/usr/local/tomcat/webapps/test" path="" reloadable="true">
	</Context>
</Host>

/usr/local/tomcat/bin/shutdown.sh 
/usr/local/tomcat/bin/startup.sh 

insert image description here
insert image description here

(2)Tomcat2 server 配置
mkdir /usr/local/tomcat/tomcat1/webapps/test /usr/local/tomcat/tomcat2/webapps/test

vim /usr/local/tomcat/tomcat1/webapps/test/index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>JSP test2 page</title>   #指定为 test2 页面
</head>
<body>
<% out.println("动态页面 2,http://www.test2.com");%>
</body>
</html>


vim /usr/local/tomcat/tomcat1/conf/server.xml
#删除前面的 HOST 配置
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
	<Context docBase="/usr/local/tomcat/tomcat1/webapps/test" path="" reloadable="true" />
</Host>

/usr/local/tomcat/tomcat1/bin/shutdown.sh 
/usr/local/tomcat/tomcat1/bin/startup.sh 


vim /usr/local/tomcat/tomcat2/webapps/test/index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>JSP test3 page</title>   #指定为 test3 页面
</head>
<body>
<% out.println("动态页面 3,http://www.test3.com");%>
</body>
</html>


vim /usr/local/tomcat/tomcat2/conf/server.xml
#删除前面的 HOST 配置
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
	<Context docBase="/usr/local/tomcat/tomcat2/webapps/test" path="" reloadable="true" />
</Host>

/usr/local/tomcat/tomcat2/bin/shutdown.sh 
/usr/local/tomcat/tomcat2/bin/startup.sh 


(3)Nginx server 配置
#准备静态页面和静态图片
echo '<html><body><h1>这是静态页面</h1></body></html>' > /usr/local/nginx/html/index.html
mkdir /usr/local/nginx/html/img
cp /root/game.jpg /usr/local/nginx/html/img

vim /usr/local/nginx/conf/nginx.conf
......
http {
......
	#gzip on;
	
	#配置负载均衡的服务器列表,weight参数表示权重,权重越高,被分配到的概率越大
	upstream tomcat_server {
		server 192.168.119.3:8080 weight=1;
		server 192.168.119.4:8080 weight=1;
		server 192.168.119.4:8081 weight=1;
	}
	
	server {
		listen 80;
		server_name www.kgc.com;
	
		charset utf-8;
	
		#access_log logs/host.access.log main;
		
		#配置Nginx处理动态页面请求,将 .jsp文件请求转发到Tomcat 服务器处理
		location ~ .*\.jsp$ {
			proxy_pass http://tomcat_server;
#设置后端的Web服务器可以获取远程客户端的真实IP
##设定后端的Web服务器接收到的请求访问的主机名(域名或IP、端口),默认HOST的值为proxy_pass指令设置的主机名。如果反向代理服务器不重写该请求头的话,那么后端真实服务器在处理时会认为所有的请求都来自反向代理服务器,如果后端有防攻击策略的话,那么机器就被封掉了。
			proxy_set_header HOST $host;
##把$remote_addr赋值给X-Real-IP,来获取源IP
			proxy_set_header X-Real-IP $remote_addr;
##在nginx 作为代理服务器时,设置的IP列表,会把经过的机器ip,代理机器ip都记录下来
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		}
		
		#配置Nginx处理静态图片请求
		location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css)$ {
			root /usr/local/nginx/html/img;
			expires 10d;
		}
		
		location / {
			root html;
			index index.html index.htm;
		}
......
	}
......
}

4.测试效果
测试静态页面效果
浏览器访问 http://192.168.119.3/
浏览器访问 http://192.168.119.3/game.jpg

测试负载均衡效果,不断刷新浏览器测试
浏览器访问 http://192.168.119.40/index.jsp

insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here

Guess you like

Origin blog.csdn.net/2301_76875445/article/details/131066896