柚子快報激活碼778899分享:java Tomcat
柚子快報激活碼778899分享:java Tomcat
Tomcat
1.JVM是啥2.Tomcattomcat啟動慢解決方案
3.tomcat目錄結(jié)構(gòu)介紹binconfliblogswebappsworktempRELEASE-NOTESRUNNING.txt
4.tomcat主配置文件5.tomcat部署java項目示例:zrlog6.配置tomcat basic認(rèn)證7.Nginx+Tomcat集群架構(gòu)8.tomcat+nfs實現(xiàn)文件共享安裝配置nfs服務(wù)端客戶端配置nfs
9.nginx做靜態(tài)資源緩存緩存服務(wù)器配置參數(shù)介紹緩存結(jié)果驗證
10.Nginx+Tomcat實現(xiàn)Https11.使用maven編譯java程序maven安裝配置編譯java程序配置tomcat站點
12.使用redisson實現(xiàn)session共享方法一:ip_hash 做會話保持方法二:使用redisson實現(xiàn)session共享redis部署配置redisson1.添加會話管理器2.將下載好的jar包放到指定目錄重啟tomcat
13.使用JConsole 監(jiān)控jvm在被監(jiān)控的tomcat服務(wù)器上開啟監(jiān)控接口使用JConsole 監(jiān)控環(huán)境變量配置啟動jconsole.exe
14.Tomcat性能優(yōu)化15.JVM內(nèi)存分代年輕代年輕代垃圾回收算法(復(fù)制算法)老年代老年代垃圾回收算法 (標(biāo)記清除算法)永久代垃圾回收何時進(jìn)行系統(tǒng)崩潰前的一些現(xiàn)象:dump文件Tomcat內(nèi)存調(diào)整(JVM內(nèi)存調(diào)整)年輕代和老年代設(shè)置多大才合理調(diào)優(yōu)方法
1.JVM是啥
JVM是Java Virtual Machine(Java虛擬機(jī))的縮寫
是運行Java程序的抽象計算機(jī),是Java語言的運行環(huán)境,Java虛擬機(jī)本質(zhì)是就是一個程序,當(dāng)它在命令行上啟動的時候,就開始執(zhí)行保存在某字節(jié)碼文件中的指令。Java語言的可移植性正是建立在Java虛擬機(jī)的基礎(chǔ)上。任何平臺只要裝有針對于該平臺的Java虛擬機(jī),字節(jié)碼文件(.class)就可以在該平臺上運行。實現(xiàn)“一次編譯,多次運行”。
jvm java虛擬機(jī) jre java運行環(huán)境 jdk java開發(fā)工具包 jdk包含jre,jre包含jvm虛擬機(jī)
常用的是jdk8
jdk下載地址:https://www.oracle.com/java/technologies/downloads/?er=221886#java8
其他版本jdk下載地址:https://www.oracle.com/java/technologies/downloads/archive/
2.Tomcat
Tomcat和 Nginx 類似,也是一個Web服務(wù)器。 tomcat是一個java編寫的web服務(wù)器,需要java運行環(huán)境,運行java。
Nginx默認(rèn)僅支持處理靜態(tài)資源,而Tomcat則支持Java開發(fā)的 jsp 動態(tài)資源和靜態(tài)資源。 Nginx適合做前端負(fù)載均衡,而Tomcat適合做后端應(yīng)用服務(wù)處理。 通常情況下會將 Nginx+tomcat 結(jié)合使用,由Nginx處理靜態(tài)資源,Tomcat處理動態(tài)資源。
tomcat下載地址:https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/
將下載好的jdk包傳到服務(wù)器上
安裝jdk rpm -ivh jdk-8u411-linux-x64.rpm
安裝啟動tomcat
mkdir app -p
tar xf apache-tomcat-9.0.90.tar.gz -C /app
/app/apache-tomcat-9.0.90/bin/startup.sh
安裝方法二:
#適合debian和ubuntu等其他linux發(fā)行版
tar xf jdk-8u60-linux-x64.tar.gz -C /app/
ln -s /app/jdk1.8.0_60 /app/jdk
sed -i.ori '$a export JAVA_HOME=/app/jdk\nexport PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH\nexport CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar' /etc/profile
source /etc/profile
mkdir /app/
tar xf apache-tomcat-8.0.27.tar.gz -C /app
/app/apache-tomcat-8.0.27/bin/startup.sh
tomcat啟動慢解決方案
可以在/apache-tomcat-9.0.90/logs/catalina.out中看到啟動用時
優(yōu)化方法: vim /usr/java/jdk1.8.0_102/jre/lib/security/java.security
將:securerandom.source=file:/dev/random
改為:securerandom.source=file:/dev/urandom
啟動后可以看到j(luò)ava常占用的端口
3.tomcat目錄結(jié)構(gòu)介紹
bin
主要包含啟動、關(guān)閉tomcat腳本和腳本依賴文件 非常重要
以啟動腳本為例 執(zhí)行腳本時,會先找到腳本本身的目錄,然后去執(zhí)行catalina.sh腳本,然后讓tomcat在后臺啟動。
在需要時,也可以讓tomcat在前臺啟動 先停掉tomcat,再執(zhí)行./catalina.sh run 讓它前臺啟動
conf
tomcat配置文件目錄,重要
tomcat的主配置文件server.xml
lib
tomcat運行需要加載的jar包,重要
jar包相當(dāng)于擴(kuò)展模塊,tomcat在運行過程中,會運行不同的組件,不同的組件對應(yīng)的就是不同的jar包。想實現(xiàn)某些功能,就將對應(yīng)的jar包放到lib目錄下。
logs
在運行過程中產(chǎn)生的日志文件,重要 catalina.out中主要記錄一些報錯輸出等內(nèi)容 access訪問日志中主要記錄訪問日志
webapps
站點目錄,重要 訪問tomcat時,默認(rèn)訪問的是ROOT目錄下的內(nèi)容 要訪問其他的目錄在url中加入/對應(yīng)的目錄名稱即可
work
tomcat運行時產(chǎn)生的緩存文件
temp
temp 存放臨時文件
RELEASE-NOTES
版本特性,不重要
RUNNING.txt
幫助文件,不重要
4.tomcat主配置文件
主配置文件: /app/apache-tomcat-8.x.xx/conf/server.xml
用戶訪問tomcat,會先訪問到proxy模塊,監(jiān)聽的8080端口。 proxy會將請求拋向server內(nèi)部, 請求拋給誰處理,就會找對應(yīng)的連接器, 例如是http請求,就會拋給http連接器,
一個tomcat實例一個server 一個server中包含多個連接器(Connector),Connector的主要功能是接受、響應(yīng)用戶請求。 service的作用是:將connector關(guān)聯(lián)至engine(catalina引擎),引擎下,對應(yīng)的就是站點 一個host就是一個站點,類似于nginx的多站點 context類似于nginx中l(wèi)ocation的概念
打開server.xml文件,可以看到8005端口可以用來遠(yuǎn)程關(guān)閉tomcat服務(wù)
server和service之間就是通過這些connector連接器連接的
tomcat核心的引擎是catalina 引擎下,對應(yīng)的就是站點,一個Host就對應(yīng)一個站點,類似于nginx的多站點 nginx支持多域名多站點,同樣tomcat (host)也支持多域名多站點
默認(rèn)配置的站點是localhost站點,站點目錄是webapps,
訪問日志格式:
className="org.apache.catalina.valves.AccessLogValve" 日志的方法
directory="logs" 日志所在目錄
prefix="localhost_access_log" 日志前綴
suffix=".txt" 日志后綴
中間加上時間戳
5.tomcat部署java項目示例:zrlog
修改主配置文件server.xml,添加一個站點,就是添加一個Host
例:
www.tct.com 為站點名 記得做域名解析
/html 為站點目錄
將下載好的項目war包放到站點目錄/html下會自動解壓,自動部署。
修改后,需要重啟服務(wù)才會生效
創(chuàng)建站點目錄后,將war包放入站點目錄,會自動解壓自動部署
過一會訪問
配置數(shù)據(jù)庫
yum install mariadb-server -y
systemctl start mariadb.service
systemctl enable mariadb.service
站點部署成功
6.配置tomcat basic認(rèn)證
有了basic認(rèn)證使網(wǎng)站多了一層安全保障
nginx同樣也有basic認(rèn)證,參考nginx常用功能模塊 中 nginx通過賬戶登陸實現(xiàn)訪問控制
測試basic認(rèn)證時
點擊這三個按鈕后提示403
解決方法:
將以下兩個文件中的這兩行注釋掉
/app/apache-tomcat-9.0.90/webapps/manager/META-INF/context.xml
/app/apache-tomcat-9.0.90/webapps/host-manager/META-INF/context.xml
然后在 /app/apache-tomcat-9.0.90/conf/tomcat-users.xml
加入
配置過后需要重啟tomcat
/app/apache-tomcat-9.0.90/bin/shutdown.sh
/app/apache-tomcat-9.0.90/bin/startup.sh
重啟后再試即可認(rèn)證
如果是在部署的項目上開啟basic認(rèn)證時,需要在配置的站點目錄下找到 ROOT/WEB-INF/web.xml 例如站點目錄是/html,就編輯/html/ROOT/WEB-INF/web.xml文件
在文件倒數(shù)第二行加上basic認(rèn)證
配置過后重啟tomcat
/app/apache-tomcat-9.0.90/bin/shutdown.sh
/app/apache-tomcat-9.0.90/bin/startup.sh
7.Nginx+Tomcat集群架構(gòu)
大概架構(gòu)
在之前的基礎(chǔ)上,部署一臺配置相同的web服務(wù)器,jdk+tomcat+zrlog
再部署一臺nginx負(fù)載均衡服務(wù)器,配置文件如下
cat proxy_java.conf
upstream tomcat { #定義資源池
server 192.168.xx.1:8080; #tomcat01
server 192.168.xx.2:8080; #tomcat02
}
server {
listen 80;
server_name www.tct.com;
location / {
proxy_pass http://tomcat; #調(diào)?upstream資源池定義的名稱
proxy_set_header Host $host; #修改請求頭中的Host為實際請求的主機(jī)名
proxy_set_header X-Real-IP $remote_addr; #傳遞客戶端的真實IP地址
include proxy_params;
}
}
proxy_set_header Host $host; 修改由Nginx傳遞給代理后端的請求頭,修改請求頭中的Host, 不然會保留原始的Host,返回的頁面是tomcat默認(rèn)頁面, 并非實際請求頁面,$host的值就是請求的主機(jī)名。
proxy_set_header X-Real-IP $remote_addr; 傳遞客戶端的真實IP地址,當(dāng) Nginx做負(fù)載均衡時,后端服務(wù)器看到的客戶端 IP 是負(fù)載均衡的 IP,而不是真實用戶的 IP。
同時需要將兩臺tomcat服務(wù)器的日志格式修改
vim /app/apache-tomcat-8.0.27/conf/server.xml
pattern="%{X-Real-IP}i %l %u %t "%r" %s %b" />
參數(shù)含義:
%i 表示請求頭
%l 表示‘-’
%u 遠(yuǎn)程用戶身份驗證,應(yīng)該就是前面的basic認(rèn)證
%t 日期時間
" 表示空格
%r 第一行的請求(主要包含請求方法和請求的URI)
%s 響應(yīng)的HTTP狀態(tài)碼
%b 發(fā)送的字節(jié)數(shù)
修改后重啟tomcat
/app/apache-tomcat-8.0.27/bin/shutdown.sh
/app/apache-tomcat-8.0.27/bin/startup.sh
然后后端看到的IP就是真實的客戶端IP了。
8.tomcat+nfs實現(xiàn)文件共享
大概架構(gòu) 為了方便我就直接在數(shù)據(jù)庫服務(wù)器上部署NFS服務(wù)了
安裝配置nfs服務(wù)端
1.安裝 yum install nfs-utils -y
2.配置 vim /etc/exports
/data 192.168.51.1/24(rw,sync,no_root_squash,no_all_squash)
3.根據(jù)配置進(jìn)行初始化操作 mkdir -p /Data
4.啟動
systemctl start nfs
#systemctl enable nfs
客戶端配置nfs
在兩臺tomcat服務(wù)器上都要執(zhí)行以下操作
安裝nfs yum install nfs-utils -y
查看某主機(jī)提供的nfs服務(wù) showmount -e 192.168.xx.xxx
因為zrlog的圖片存放路徑在 /站點目錄/zrlog/attached下,所以創(chuàng)建對應(yīng)目錄 mkdir /html/zrlog/attached
掛載 將192.168.xx.xxx:/Data 掛載到本地的/html/zrlog/attached目錄 mount -t nfs 192.168.xx.xxx:/Data /html/zrlog/attached
df -h 查看是否掛載上
如果遇到客戶端權(quán)限不足的情況參考: NFS客戶端權(quán)限不足
接下來在任意一臺服務(wù)器上傳圖片,另外一臺服務(wù)器同樣可以讀到該圖片
9.nginx做靜態(tài)資源緩存
緩存服務(wù)器配置
nginx配置文件如下
vim /etc/nginx/conf.d/proxy.conf
proxy_cache_path /opt/nginx/cache levels=1:2 keys_zone=one:10m;
upstream tomcat {
server 192.168.xx.xx1:8080;
server 192.168.xx.xx2:8080;
}
server {
listen 80;
server_name www.tct.com;
location / {
proxy_pass http://tomcat;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
include proxy_params;
}
location ~ .*\.(gif|jpg|png|css|js|woff|flv|ico|swf)(.*) {
proxy_cache one;
proxy_cache_key $uri;
proxy_cache_valid 200 302 1h;
proxy_cache_valid 301 1d;
proxy_cache_valid any 1m;
expires 30d;
add_header Nginx-Cache "$upstream_cache_status";
proxy_pass http://tomcat;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
include proxy_params;
}
}
/opt/nginx/cache 目錄需要提前創(chuàng)建,并且授權(quán)給nginx, chown -R nginx:nginx /opt/nginx/cache 因為nginx需要往該目錄中寫緩存
參數(shù)介紹
/opt/nginx/cache 指定緩存目錄
levels=1:2 表示緩存目錄的層級 ,1:2表示生成的目錄是兩級目錄
keys_zone=one:10m key是索引,每個緩存都會生成唯一的標(biāo)識符來索引,下次請求緩存的時候,會先去索引key,有請求資源的話直接返回緩存,沒有的話生成新的緩存。one是給key區(qū)域的起的名。 10m指的是索引的大小。
gif|jpg|png|css|js|woff|flv|ico|swf 指定格式
proxy_cache one; 緩存到哪個區(qū)域,對應(yīng)前面創(chuàng)建的one
proxy_cache_key $uri; 指定uri作為key的索引
proxy_cache_valid 200 302 1h; 200 302狀態(tài)碼的緩存一小時
proxy_cache_valid 301 1d; 301狀態(tài)碼的緩存一天
proxy_cache_valid any 1m; 其他狀態(tài)碼的緩存一分鐘
expires 30d; 過期時間為30天
add_header Nginx-Cache "$upstream_cache_status"; 判斷是否命中緩存 ,在http 的響應(yīng)頭中添加一個緩存的命中狀態(tài)。HIT表示命中緩存,MISS表示沒有命中緩存。
緩存結(jié)果驗證
查看緩存目錄,可以看到緩存目錄層級是按照我們指定的兩層進(jìn)行緩存的
查看響應(yīng)頭,可以看到 png圖片資源、js文件 都命中了緩存
10.Nginx+Tomcat實現(xiàn)Https
其實就是給nginx配一個證書
nginx配置如下:
proxy_cache_path /opt/nginx/cache levels=1:2 keys_zone=one:10m;
upstream tomcat {
server 192.168.xx.xx1:8080;
server 192.168.xx.xx2:8080;
}
server { #主要是證書配置這一部分,其他的和之前的變化不大
listen 443 ssl;
server_name closeai.xyz;
ssl_certificate /opt/closeai.xyz_nginx/closeai.xyz.pem;
ssl_certificate_key /opt/closeai.xyz_nginx/closeai.xyz.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
location / {
proxy_pass http://tomcat;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
include proxy_params;
}
location ~ .*\.(gif|jpg|png|css|js|woff|flv|ico|swf)(.*) {
proxy_cache one;
proxy_cache_key $uri;
proxy_cache_valid 200 302 1h;
proxy_cache_valid 301 1d;
proxy_cache_valid any 1m;
expires 30d;
add_header Nginx-Cache "$upstream_cache_status";
proxy_pass http://tomcat;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
include proxy_params;
}
}
server { #做個協(xié)議層面的跳轉(zhuǎn),請求http時,自動跳轉(zhuǎn)到https
listen 80;
server_name closeai.xyz;
return 302 https://$server_name$request_uri; #$server_name:請求的域名,$request_uri:用戶請求的URI
}
修改完配置記得重載一下nginx服務(wù)
nginx -t
systemctl reload nginx
兩臺tomcat的配置文件中的站點也要記得修改成同樣的域名
vim /app/apache-tomcat-8.0.27/conf/server.xml
修改完記得重啟tomcat
/app/apache-tomcat-8.0.27/bin/shutdown.sh
/app/apache-tomcat-8.0.27/bin/startup.sh
結(jié)果驗證 通過https的方式訪問站點,可以成功打開 因為我用的證書是有效的,如果是自己生成的證書,瀏覽器會報證書無效的錯,但原理都一樣,花錢買個域名,再把有效的證書換上就可以了。
11.使用maven編譯java程序
maven安裝配置
下載maven wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.8.8/binaries/apache-maven-3.8.8-bin.tar.gz
解壓maven tar xf apache-maven-3.8.8-bin.tar.gz -C /usr/local/
創(chuàng)建軟鏈接 ln -s /usr/local/apache-maven-3.8.8 /usr/local/maven
配置maven環(huán)境變量
vim /etc/profile
#文件結(jié)尾添加兩行
export M2_HOME=/usr/local/maven
export PATH=${M2_HOME}/bin:$PATH
source /etc/profile
驗證maven mvn -v
配置maven倉庫 vim /usr/local/maven/conf/settings.xml
編譯java程序
下載好測試用的包:https://github.com/efsavage/hello-world-war
解壓后進(jìn)入項目目錄
unzip hello-world-war-master.zip
cd hello-world-war-master
編譯 mvn clean package
編譯后war包在target目錄下
配置tomcat站點
vim /app/apache-tomcat-8.0.27/conf/server.xml 再添加一個Host
記得創(chuàng)建站點目錄,再將之前的war包放到站點目錄下名為ROOT.war tomcat會自動解壓
mkdir /hello
mv /opt/hello-world-war-master/target/hello-world-war-1.0.0.war /hello/ROOT.war
記得做域名解析
記得重啟tomcat
/app/apache-tomcat-8.0.27/bin/shutdown.sh
/app/apache-tomcat-8.0.27/bin/startup.sh
然后訪問站點即可
12.使用redisson實現(xiàn)session共享
存在的問題:將相同業(yè)務(wù)的后端節(jié)點加入負(fù)載均衡后,在客戶端進(jìn)行登錄操作的時候,會發(fā)現(xiàn)不管在哪個節(jié)點都無法正常登陸,原因是session沒有共享。
解決方案:做會話保持 1.粘性session: ip_hash 始終定向?某?個后端web節(jié)點。 2.session共享: 將session通過存儲到指定?個位置,?不是存儲?本地,后端所有節(jié)點都通過這個位置進(jìn)行驗證 ( redis )
方法一:ip_hash 做會話保持
在負(fù)載均衡的配置文件的地址池中加入ip_hash 解決了無法登陸的問題,但是只能訪問固定的一個web節(jié)點,無法輪詢
upstream web {
ip_hash; #做會話保持
server 192.168.xx.xx1:8080;
server 192.168.xx.xx2:8080;
}
方法二:使用redisson實現(xiàn)session共享
redis部署
yum install redis -y
啟動redis
systemctl start redis
systemctl enable redis
修改redis配置文件 vim /etc/redis.conf 添加redis服務(wù)器的IP地址
重啟redis systemctl restart redis
配置redisson
在每臺tomcat服務(wù)器上都執(zhí)行以下操作
redisson項目地址 https://github.com/redisson/redisson
基于 Redis 的 Tomcat 會話管理器 https://github.com/redisson/redisson/tree/master/redisson-tomcat
官方使用教程:
1.添加會話管理器
vim /app/apache-tomcat-8.0.27/conf/context.xml
添加以下內(nèi)容
configPath="${catalina.base}/conf/redisson.conf" readMode="REDIS" updateMode="DEFAULT" broadcastSessionEvents="false" keyPrefix=""/> 然后將redisson.conf文件放到上面配置的目錄下 /app/apache-tomcat-8.0.27/conf/目錄下 這個配置文件是用來連接redis的 redisson.conf文件內(nèi)容如下 { "singleServerConfig":{ "idleConnectionTimeout":10000, "connectTimeout":10000, "timeout":3000, "retryAttempts":3, "retryInterval":1500, "password":null, "subscriptionsPerConnection":5, "clientName":null, "address": "redis://你的redis地址:6379", #這里記得改成你部署的redis的地址 "subscriptionConnectionMinimumIdleSize":1, "subscriptionConnectionPoolSize":50, "connectionMinimumIdleSize":32, "connectionPoolSize":64, "database":0, "dnsMonitoringInterval":5000 }, "threads":0, "nettyThreads":0, "codec":{ "class":"org.redisson.codec.JsonJacksonCodec" }, "transportMode":"NIO" } 2.將下載好的jar包放到指定目錄 將下載好的jar包放到官方指定的tomcat根目錄下的lib目錄中 /app/apache-tomcat-8.0.27/lib/ 重啟tomcat /app/apache-tomcat-8.0.27/bin/shutdown.sh /app/apache-tomcat-8.0.27/bin/startup.sh 每臺tomcat服務(wù)器都配置完畢后,session已經(jīng)共享,再去登陸就可以成功登陸了 可以查看到在redis中存的session redis-cli KEYS * 13.使用JConsole 監(jiān)控jvm 在被監(jiān)控的tomcat服務(wù)器上開啟監(jiān)控接口 vim /app/apache-tomcat-8.0.27/bin/catalina.sh CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=192.168.xx.xxx -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false" 重啟tomcat /app/apache-tomcat-8.0.27/bin/shutdown.sh /app/apache-tomcat-8.0.27/bin/startup.sh 驗證 使用JConsole 監(jiān)控 在一臺Windows機(jī)器上安裝jdk jdk下載地址: https://www.oracle.com/cn/java/technologies/downloads/#java11-windows 安裝jdk 按照他默認(rèn)的安裝路徑即可 點關(guān)閉 在剛才的安裝路徑下可以看到j(luò)dk-11 環(huán)境變量配置 右鍵此電腦,屬性 高級系統(tǒng)設(shè)置 點擊環(huán)境變量 瀏覽目錄找到剛才的安裝路徑,然后點確定 找到Path編輯,點擊新建輸入%Java_Home%\bin ,然后確定 然后都點確定關(guān)閉頁面 同時按下 win + R 輸入 cmd 回車 輸入java -version 查看版本 輸入javac 會輸出以下信息 jdk配置完成 啟動jconsole.exe 在C:\Program Files\Java\jdk-11\bin下找到j(luò)console.exe 因為我要監(jiān)控的是遠(yuǎn)程的tomcat服務(wù)器, 所以在遠(yuǎn)程進(jìn)程下輸入遠(yuǎn)程服務(wù)器的IP地址:JMX自定義的端口,然后點連接 然后點 不安全的連接 (前面沒開SSL連接) 稍等一會,就可以看到監(jiān)控頁面了 可以切換查看不同的信息 14.Tomcat性能優(yōu)化 ?Tomcat的性能優(yōu)化可以通過多個方面進(jìn)行, 主要包括:內(nèi)存優(yōu)化、并發(fā)優(yōu)化、?數(shù)據(jù)庫連接池優(yōu)化、線程優(yōu)化、緩存優(yōu)化等。 內(nèi)存優(yōu)化:通過調(diào)整JVM啟動參數(shù)如-Xms和-Xmx來設(shè)置JVM的初始堆大小和最大堆大小。 例如,可以設(shè)置JAVA_OPTS='-Xms1024m -Xmx2048m'來確保JVM有足夠的內(nèi)存資源。? 并發(fā)優(yōu)化:調(diào)整Tomcat的連接器配置文件server.xml中的參數(shù), 如minProcessors、maxProcessors、acceptCount和maxThreads, 以優(yōu)化并發(fā)處理能力。例如,增加acceptCount的值可以擴(kuò)大連接請求隊列,避免連接請求被拒絕。? 數(shù)據(jù)庫連接池優(yōu)化:選擇合適的數(shù)據(jù)庫連接池 (如Apache Commons DBCP、Tomcat JDBC Pool、HikariCP等), 并合理配置連接池參數(shù),如連接數(shù)、最大等待時間、最大空閑連接數(shù)等, 以提高數(shù)據(jù)庫連接的利用率和性能。? 線程優(yōu)化:根據(jù)服務(wù)器的CPU核數(shù)和負(fù)載情況調(diào)整maxThreads參數(shù), 以及考慮使用非阻塞模式的連接協(xié)議(如NIO或APR)來提高處理能力。? 緩存和壓縮優(yōu)化:開啟gzip壓縮來減小網(wǎng)絡(luò)傳輸大小,同時考慮使用緩存來減少對后端Tomcat的訪問。 例如,可以在Tomcat中配置壓縮相關(guān)的參數(shù),如compression="on"和設(shè)置壓縮的最小內(nèi)容長度等。? Tomcat的性能優(yōu)化是一個多方面的過程, 需要綜合考慮內(nèi)存、并發(fā)、數(shù)據(jù)庫連接池、線程以及緩存和壓縮等多個方面的設(shè)置和調(diào)整。 15.JVM內(nèi)存分代 內(nèi)存主要包括堆內(nèi)存與非堆內(nèi)存 JVM將內(nèi)存劃分為三大部分: 年輕代Young Generation 老年代Old Generation 永久代Permanent Generation 年輕代和老年代屬于堆內(nèi)存, 堆內(nèi)存會從JVM啟動參數(shù)(-Xmx:3G)指定的內(nèi)存中分配 年輕代和老年代將根據(jù)默認(rèn)的比例(1:4)分配堆內(nèi)存 永久代不屬于堆內(nèi)存,虛擬機(jī)直接分配, 但可以通過(-XX:PermSize -XX:MaxPermSize)等參數(shù)調(diào)整其大小。 年輕代:用來存放JVM剛分配的Java對象 老年代:年輕代中經(jīng)過垃圾回收沒有被回收掉的對象將被Copy到年老代 永久代:永久代存放Class、Method元信息,其大小跟項目的規(guī)模、類、方法的量有關(guān),一般設(shè)置為128M就足夠,設(shè)置原則是預(yù)留30%的空間。 年輕代 年輕代用來存放JVM剛分配的Java對象。 由于頻繁創(chuàng)建對象,所以新生代會頻繁觸發(fā)MinorGC進(jìn)行垃圾回收。 年輕代又分為 :Eden、SurvivorFrom、SurvivorTo三個區(qū)。 Eden區(qū):存放JVM剛分配的Java對象 (如果新對象占用內(nèi)存很大,則直接分配到老年代), 當(dāng)Eden區(qū)內(nèi)存不夠的時候就會觸發(fā)MinorGC(局部的GC),對年輕代區(qū)進(jìn)行一次垃圾回收。 SurvivorFrom(s0):保留了一次MinorGC過程中的幸存者。 SurvivorTo(s1):上一次GC的幸存者,作為這一次GC的被掃描者。 兩個Survivor空間一樣大,當(dāng)Eden中的對象經(jīng)過垃圾回收沒有被回收掉時,會在兩個Survivor之間來回Copy,當(dāng)滿足某個條件,比如對象的年齡,就會被Copy到Tenured。顯然,Survivor只是增加了對象在年輕代中的逗留時間,增加了被垃圾回收的可能性。 年輕代垃圾回收算法(復(fù)制算法) 首先把Eden和SurvivorFrom區(qū)域中存活的對象復(fù)制到SurvivorTo區(qū)域 同時把這些對象的年齡+1(如果ServicorTo不夠位置了就放到老年區(qū)) (如果有對象的年齡已經(jīng)達(dá)到了老年的標(biāo)準(zhǔn),一般是15,則復(fù)制到老年代區(qū)) 然后,清空Eden和SurvivorFrom中的對象; 最后把SurvivorTo和SurvivorFrom互換,原SurvivorTo成為下一次GC時的SurvivorFrom區(qū)。 老年代 老年代的對象比較穩(wěn)定,所以不會頻繁執(zhí)行GC。 老年代在進(jìn)行GC前一般年輕代都先進(jìn)行了一次GC,使得年輕代的對象晉升入老年代, 導(dǎo)致空間不夠用時才觸發(fā)。當(dāng)無法找到足夠大的連續(xù)空間分配給新創(chuàng)建的較大對象時也會提前觸發(fā)一次GC進(jìn)行垃圾回收騰出空間。 老年代垃圾回收算法 (標(biāo)記清除算法) 首先掃描一次所有老年代,標(biāo)記出存活的對象,然后回收沒有標(biāo)記的對象。 老年代的GC的耗時比較長,因為要掃描再回收。 GC會產(chǎn)生內(nèi)存碎片,為了減少內(nèi)存損耗,一般需要進(jìn)行合并或者標(biāo)記出來方便下次直接分配。 當(dāng)老年代也滿了裝不下的時候,就會拋出OOM(Out of Memory)異常。 永久代 主要存放Class和Meta(元數(shù)據(jù))的信息。 Class在被加載的時候放入永久區(qū)域。 它和其他區(qū)域不同,GC不會在主程序運行期對永久區(qū)域進(jìn)行清理。所以這也導(dǎo)致了永久代的區(qū)域會隨著加載的Class的增多而脹滿,最終拋出OOM異常。 在Java8中,永久代已經(jīng)被移除,被“元數(shù)據(jù)區(qū)”(元空間)的區(qū)域所取代。 元空間與永久代之間區(qū)別在于:元空間并不在虛擬機(jī)中,而是使用本地內(nèi)存。因此,默認(rèn)情況下,元空間的大小僅受本地內(nèi)存限制。 垃圾回收何時進(jìn)行 當(dāng)年輕代內(nèi)存滿時,會引發(fā)一次普通的局部GC,該GC僅回收年輕代。 需要強(qiáng)調(diào)的是,年輕代滿是指Eden代滿,Survivor滿不會引發(fā)GC。 當(dāng)老年代滿時會引發(fā)全局GC(Full GC)將會同時回收年輕代、老年代。 當(dāng)永久代滿時也會引發(fā)全局GC(Full GC),會導(dǎo)致Class、Method元信息的卸載。 GC垃圾回收: 回收次數(shù)越少越好,回收時間越短越好 系統(tǒng)崩潰前的一些現(xiàn)象: 每次垃圾回收的時間越來越長,由之前的10ms延長到50ms左右, FullGC的時間也有之前的0.5s延長到4、5s。 FullGC的次數(shù)越來越多,最頻繁時隔不到1分鐘就進(jìn)行一次FullGC, 老年代的內(nèi)存越來越大并且每次FullGC后老年代沒有內(nèi)存被釋放。 之后系統(tǒng)會無法響應(yīng)新的請求,逐漸到達(dá)OutOfMemoryError的臨界值。 dump文件 通過JMX的MBean生成當(dāng)前的Heap(堆棧)信息,大小為一個3G(整個堆的大?。┑膆prof文件,如果沒有啟動JMX可以通過Java的jmap命令來生成該文件。然后選用Eclipse專門的靜態(tài)內(nèi)存分析工具:Mat分析該文件。 Tomcat內(nèi)存調(diào)整(JVM內(nèi)存調(diào)整) Tomcat內(nèi)存優(yōu)化主要是對 tomcat 啟動參數(shù)優(yōu)化,我們可以在 tomcat 的啟動腳本 catalina.sh 中設(shè)置 JAVA_OPTS參數(shù)。 例: JAVA_OPTS="$JAVA_OPTS -server -Xms512m -Xmx512m -Xss256k -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/heapdump -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/tmp/heap_trace.txt -XX:NewSize=128m -XX:MaxNewSize=128m" 參數(shù)含義-Xms初始堆大小-Xmx最大堆大小-Xss線程棧的大小,這個選項對性能的影響比較大,建議使用256K的大小。-XX:NewRatio年輕代和老年代的堆內(nèi)存比例-XX:+HeapDumpOnOutOfMemoryError控制JVM 在 OutOfMemoryError 時打印堆的信息-XX:HeapDumpPath指定堆信息文件的存儲路徑-XX:+PrintGCDetails輸出詳細(xì)的GC收集日志的信息-XX:+PrintGCTimeStamps打印CG發(fā)生的時間戳-Xloggc設(shè)置GC打印的日志名稱-XX:NewSize設(shè)置年輕代大小-XX:MaxNewSize設(shè)置年輕代大小,通常會把-XX:newSize -XX:MaxNewSize設(shè)置為同樣大小-XX:SurvivorRatio年輕代中Eden區(qū)與兩個Survivor區(qū)的比值。注意Survivor區(qū)有兩個。如:3,表示Eden:Survivor=3:2,一個Survivor區(qū)占整個年輕代的1/5-XX:MaxPermSize設(shè)置永久代大小-XX:PermSize設(shè)置永久代大小-XX:+UseParalledlOldGC垃圾回收時,設(shè)置并行年老代收集器回收,在配置較好的機(jī)器上(比如多核、大內(nèi)存),可以為年老代選擇并行收集算法: -XX:+UseParallelOldGC ,默認(rèn)為Serial收集-XX:+UseSerialGC垃圾回收時,設(shè)置串行收集器回收-XX:+UseParallelGC垃圾回收時,設(shè)置并行收集器回收-XX:+UseConcMarkSweepGC垃圾回收時,設(shè)置并發(fā)收集器回收 年輕代和老年代設(shè)置多大才合理 更大的年輕代必然導(dǎo)致更小的老年代,大的年輕代會延長普通GC的周期,但會增加每次GC的時間;小的老年代會導(dǎo)致更頻繁的Full GC,更小的年輕代必然導(dǎo)致更大老年代,小的年輕代會導(dǎo)致普通GC很頻繁,但每次的GC時間會更短;大的老年代會減少Full GC的頻率。 如何選擇應(yīng)該依賴應(yīng)用程序?qū)ο笊芷诘姆植记闆r:如果應(yīng)用存在大量的臨時對象,應(yīng)該選擇更大的年輕代;如果存在相對較多的持久對象,老年代應(yīng)該適當(dāng)增大。但很多應(yīng)用都沒有這樣明顯的特性,在抉擇時應(yīng)該根據(jù)以下兩點: (A)本著Full GC盡量少的原則,讓老年代盡量緩存常用對象,JVM的默認(rèn)比例1:2也是這個道理。 (B)通過觀察應(yīng)用一段時間,看其他在峰值時老年代會占多少內(nèi)存,在不影響Full GC的前提下,根據(jù)實際情況加大年輕代,比如可以把比例控制在1:4。但應(yīng)該給老年代至少預(yù)留1/3的增長空間 調(diào)優(yōu)方法 在調(diào)優(yōu)之前,我們需要記住下面的原則: 1、多數(shù)的Java應(yīng)用不需要在服務(wù)器上進(jìn)行GC優(yōu)化; 2、多數(shù)導(dǎo)致GC問題的Java應(yīng)用,都不是因為我們參數(shù)設(shè)置錯誤,而是代碼問題; 3、在應(yīng)用上線之前,先考慮將機(jī)器的JVM參數(shù)設(shè)置到最優(yōu)(最適合); 4、減少創(chuàng)建對象的數(shù)量; 5、減少使用全局變量和大對象; 6、GC優(yōu)化是到最后不得已才采用的手段; 7、在實際使用中,分析GC情況優(yōu)化代碼比優(yōu)化GC參數(shù)要多得多; GC優(yōu)化的目的有兩個: 1、將轉(zhuǎn)移到老年代的對象數(shù)量降低到最小; 2、減少full GC的執(zhí)行時間; 為了達(dá)到上面的目的,一般地,你需要做的事情有: 1、減少使用全局變量和大對象; 2、調(diào)整年輕代的大小到最合適; 3、設(shè)置老年代的大小為最合適; 4、選擇合適的GC收集器; GC調(diào)優(yōu)是建立在GC監(jiān)控和調(diào)優(yōu)上的,進(jìn)行監(jiān)控和調(diào)優(yōu)的一般步驟為: 1、監(jiān)控GC的狀態(tài) 使用各種JVM工具,查看當(dāng)前日志,分析當(dāng)前JVM參數(shù)設(shè)置,并且分析當(dāng)前堆內(nèi)存快照和gc日志,根據(jù)實際的各區(qū)域內(nèi)存劃分和GC執(zhí)行時間,覺得是否進(jìn)行優(yōu)化; 2、分析結(jié)果,判斷是否需要優(yōu)化 如果各項參數(shù)設(shè)置合理,系統(tǒng)沒有超時日志出現(xiàn),GC頻率不高,GC耗時不高,那么沒有必要進(jìn)行GC優(yōu)化;如果GC時間超過1-3秒,或者頻繁GC,則必須優(yōu)化; 注:如果滿足下面的指標(biāo),則一般不需要進(jìn)行GC: Minor GC執(zhí)行時間不到50ms; Minor GC執(zhí)行不頻繁,約10秒一次; Full GC執(zhí)行時間不到1s; Full GC執(zhí)行頻率不算頻繁,不低于10分鐘1次; 3、調(diào)整GC類型和內(nèi)存分配 如果內(nèi)存分配過大或過小,或者采用的GC收集器比較慢,則應(yīng)該優(yōu)先調(diào)整這些參數(shù),并且先找1臺或幾臺機(jī)器進(jìn)行beta,然后比較優(yōu)化過的機(jī)器和沒有優(yōu)化的機(jī)器的性能對比,并有針對性的做出最后選擇; 4、不斷的分析和調(diào)整 通過不斷的試驗和試錯,分析并找到最合適的參數(shù) 5、全面應(yīng)用參數(shù) 如果找到了最合適的參數(shù),則將這些參數(shù)應(yīng)用到所有服務(wù)器,并進(jìn)行后續(xù)跟蹤。 參考:https://oldqiang.com/archives/435.html 柚子快報激活碼778899分享:java Tomcat 相關(guān)閱讀
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。