博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2019/07/03 tomcat使用进阶(03)
阅读量:3925 次
发布时间:2019-05-23

本文共 7909 字,大约阅读时间需要 26 分钟。

在这里插入图片描述

在这里插入图片描述前面讲过,java虚拟机运行时,主要有两个组件一个是class loader,一个叫执行引擎
class loader装载类以后,由执行引擎执行,在内部内存中大体上可分为5个段,运行时区域:
堆,方法区,java栈,pc寄存器,本地方法栈

**面向对象编程是以数据为中心,代码服务于数据的,同一个类的代码叫做方法或同一个类所实例化对象或方法是共享的,因此这些方法都将放在方法区当中,用于存储我们被加载的类的信息,常量,静态变量,主要方法 **

JVM运行时区域:

方法区:线程共享(众多类当中的代码部分); 用于存储被JVM加载的class信息、常量、静态变量、方法等;
堆:是jvm所管理的内存中占用空间最大的一部分;
也是GC(垃圾回收器)管理的主要区域;存储对象;
(对象本身都在堆中存放,对象的支持操作叫方法,都在方法区中存放)
Java栈:线程私有,存储 线程自己的局部变量;
(内存区域,会分为堆和栈,堆是用来大量做分类内存使用,而栈是用来存储变量,局部变量时使用,java中 的很多功能是基于线程来实现的,java栈是每一个线程自己都有自己的所有的,因为每一个线程都有自己专用的局部变量,是不能混淆使用)
PC寄存器:线程私有的内存空间,程序的指令指针;
(program c=指针或者叫计数器,主要存储程序的指令指针的,一个代码通常有很多条指令组成,当前的指令加载到cpu运行时,必须要指定下一跳指令在什么地方
因此对于不同的指令来讲,运行逻辑是不一样的,因此pc寄存器也是线程私有的,本地方法栈
java写代码既可以自己调自己的类,也可以调用系统上的调用,或者库当中c代码,这种叫本地方法
一旦程序员写java代码是调用的本地方法,就会使得它的移植变的困难了,所以这个部分一般用的并不是特别的多)
本地方法栈:

重点介绍堆空间,因为垃圾回收也主要回收对空间,性能优化业主要是针对堆空间能用多大内存进行设置的。

现在看下堆空间是如何分配的
在这里插入图片描述
堆内存来讲,大体分为三代,主要是针对早期版本的jdk来说明的,1.8的jdk可能会略有不同
堆空间可以大致分为3代,新生代,老年代,持久代
对于整个堆空间来讲,用来多大内存,这三代各自分多少,就有一些所谓的参数来进行定义,对于java而言,基于垃圾回收器,因为堆是共享的,整个java进程就只有这一个堆(多个java进程就另当别论),因此对堆着当中不同的程序,他们所拥有的新生代和老年代的空间的内部的对象数量可能是不一样的,
1,所以需要按照自己的实际情况进行调整,以便高效利用内存空间,
2.不同的业务模型中,创建的对象在做垃圾回收时,而不同的垃圾回收算法对他们性能影响也会各有不同,比如不会用默认的垃圾回收算法,垃圾回收,有很多种逻辑,比如标记清楚,哪些引用为0的表示没用了,标记起来,删除,叫做标记清楚算法。
还有一种标记完后,把仍然有用的挪到存活区当中,
不同的回收算法不一样,串行和并行回收的,可以多线程回收,同时执行标记和回收操作,很显然各自性能不一样,
另外老年代的回收方式和新生代的回收方式也不一样,各自有各自不同的垃圾回收算法,每一种代当中,都不止支持一种回收算法,是两种回收算法,需要你按照自己需要去指定

下面介绍下常用参数有哪些,对于新生代而言,大体分为三个空间或两类区段:

第一类叫做伊甸园区(所有的新创建的对象都在eden区域当中
而后是存活区,(在eden区可能会经常回收的,比如内存满了,就立即回收了,回收的时候,把哪些引用技术不为0的挪到存活区,
存活区又分为两部分(from ,to,两个之间经常转换,也就意味着,左侧的是to,右侧是from,下次,过来可能就是左侧是from,右侧是to,可以理解为s1,s2存活区1,存活区2,在eden中标为依然有用的就进入存活区1,再次回收时,标记为不用的,回到eden区,把那些仍然有用的放到存活区2,这个时候就把整个eden区的存活区1都清空了,下次再扫描的时候就扫描eden和存活区2,在存活区2依然存活的挪到存活区1,如果挪了两次还没死,差不多就到老年代去了
这就是对应的垃圾回收在新生代的算法,
在这里插入图片描述
如果熬过了前几次,一般7,8就把它挪到了old 区段当中,在这个区段回收的频率不会太高,就不像新生代没准会经常回收,因为有些对象创建完以后只使用一次就没用了,如果重复使用的放到old中,频繁检测也没用必要
在这里插入图片描述
**整个堆内存空间当中,持久代是不能回收,回收的只有新生代和老年代,因此xmx这个参数就是来定义新生代和老年代的最大空间(最大是多大,虽然指了这么多空间,但是一开始并不会用这么多,刚刚启动java进程时,可以先给你分配一部分而不分配完,所以-xms)
xms初始化的时候,刚启动java进程时给你分配多少,将来如果不够用了,还可以继续申请一直到最大的空间xmx为止
而在-xms当中有一个-xx:newsize定义新生代的初始化空间大小,
整体的初始空间减去新生代的初始空间就是老年代的初始空间
新生代的最大空间减去-xx:newsize初始空间就是预留空间reserved
老年代的最大空间减去老年代的初始空间就是老年代的预留空间reserved
**
**到了jdk8以后就没用持久代了,jdk7之前还有持久代的概念,
取而代之的是一个其他空间,元数据,元空间 meta space来存放一些,可以称为元数据的数据,这些数据将一直存在,所以可以理解为跟持久代一样
**
而刚刚启动tomcat进程时,来看看tomcat大概可以分多少内存
在这里插入图片描述在这里插入图片描述
可以查看(启动tomcat进程时用的命令行,到那里去加载类,启动的类是什么,还有一些属性,这里并没有说明一共可以用多大内存,但是在tomcat访问时,有一个所谓的 server status在这里插入图片描述
这个内存空间对于java来讲是极小的,对java程序来讲,动辄几个G的内存就吃完了,尤其是搜索引擎类的程序,如ELASTICSEARCH更是如此,吃掉几十G内存非常常见
所以下面这些内存需要调整,如何需要用到jdk的java程序,都需要跳jdk当中的启动进程时的堆内存空间,这几乎是必须的
在这里插入图片描述
下面展示如何调tomcat内存空间
在这里插入图片描述
Tomcat的常用优化配置:
(1) 内存空间:
/etc/sysconfig/tomcat,(rpm包安装的
/etc/tomcat/tomcat.conf,
/usr/local/tomcat/bin/catalina.sh
JAVA_OPTS="-server -Xms32g -Xmx32g -XX:NewSize= -XX:MaxNewSize= -XX:PermSize= -XX:MaxPermSize=" 定义tomcat进程大体使用那些参数来优化我们的java程序
-server:表示让java进程工作下服务器模型 ,默认工作在混合mixed模型,这样可以为服务器的运用而优化
-Xms:堆内存初始化大小;
-Xmx:堆内存空间上限; 新生代+老年代最大用多少空间(不能超过32G,单java进程所使用内存空间不能大于32G,否则会出现性能上面的麻烦,而且自己内存分配也会出现故障的,有人在生产环境中已经踩过很多次坑 了,如果服务器内存实在是过大,最好多实例化运行,另外为了,性能足够优化,甚至建议,你的初始化空间和你的最大化空间要保持一直,直接分配好,不要在用的时候再去申请,用的时候再去分配必然也会消耗时间的
-XX:NewSize=:新生代空间初始化大小;
-XX:MaxNewSize=:新生代空间最大值;
jdk1.8下面的就不用了
-XX:PermSize=:持久代空间初始化大小;
-XX:MaxPermSize=:持久代空间最大值;
在这里插入图片描述
当前主机有1给G空间还有400M空闲的,因为默认给jdk进程只分了256M
在这里插入图片描述
所以要调整下大小
在这里插入图片描述
xmx为512m -x’ms初始化大小 512m
新生代和老年代空间,既可以用大小来分配,还可以用比例的方式来分配,可以指明新生代和老年代的比例是多少,还有很多参数,可以查jdk的官方文档来看,多数情况下只需要定最大大小,或者由我们jdk程序自行决定,各自需要分配多大,尽量不要人为限制,新生代有多大,那么老年代用不完,新生代不够用,也会出现这种尴尬局面
定义好以后,只有重启tomcat才会生效
简短格式不带等号
-xx这样的才要加等号
在这里插入图片描述
systemct restart tomcat,在n2地址上
在这里插入图片描述
对应区域就是512M了
定义初始空间和最大空间,内存就是直接分配的
在这里插入图片描述
free -m看到内存空闲量就没有那么多了
在这里插入图片描述
这是第一个需要调整的内存空间在这里插入图片描述
对于jdk来讲,线程池就是connector定义的,之前讲过线程池很多属性,还可以定义一些其他属性

(2) 线程池设置:

** 常用属性:

maxThreads:最大线程数;最大并发连接数;
minSpareThreads:最小空闲线程数;
maxSpareThreads:最大空闲线程数;
上面三个是非常有用的优化方式
acceptCount:等待队列的最大长度;
URIEncoding:URI地址编码格式,建议使用UTF-8;字符集编码格式
(之前安装的shopxx,就表明支持的字符机不是UTF-8
enableLookups:是否启用dns解析,建议禁用; (启用的话,每一次都对客户端的ip地址做反解
compression:是否启用传输压缩机制,建议“on";
(linux内核带宽可以达到10G,所以这里压缩不压缩无所谓,如果真正面临请求时就需要压缩
compressionMinSize:启用压缩传输的数据流最小值,单位是字节;
(最小压缩的阈值)
compressableMimeType:定义启用压缩功能的MIME类型;
(对哪种类型 压缩)
text/html, text/xml, text/css, text/javascript**
在这里插入图片描述
(3) 禁用8005端口;

** (4) 隐藏版本信息:(别人看到你的版本会按照漏洞攻击**

** Server=“SOME STRING”

Tomcat Session Server (memcached)**

**https://github.com/magro/memcached-session-manager

支持的session server类型:
memcached:
couchbase:
redis:
**在这里插入图片描述在这里插入图片描述
在这里插入图片描述
一般分析工具可能是程序员在进行。每一个运行的java程序说白了就是一个jdk进程,刚才发现我们自己给的参数加到后面了,这个java的jdk程序,堆内存可能会做垃圾回收的,到底从开始到现在有没有回收给,新生代回收一次,一次回收的空间老年代多少时间回收一次,一次回收多少空间,有可能需要做监控的
java自己提供了很多的监控例子,jdk提供的不是tomcat,对能够运行在jdk上的java程序都有效,因为这是一个底层的,java自身提供的

**JVM常用的分析工具:

jps:用来查看运行的所有jvm进程;(javaps
jinfo:查看进程的运行环境参数,主要是jvm命令行参数;
jstat:对jvm应用程序的资源和性能进行实时监控;
jstack:查看所有线程的运行状态;
jmap:查看jvm占用物理内存的状态;
jconsole:
jvisualvm:
**
在这里插入图片描述
sytemd运行的jps,和tomcat只能探测到进程号,很多信息是探测不到的,也可以使用详细格式来输出
jps:Java virutal machine Process Status tool,
jps [-q] [-mlvV] []
-q:静默模式;
-v:显示传递给jvm的命令行参数;
-m:输出传入main方法的参数;
-l:输出main类或jar完全限定名称;
-V:显示通过flag文件传递给jvm的参数;
[]:主机id,默认为localhost;

-v:显示传递给jvm的命令行参数;不加进程显示所有进程在这里插入图片描述

-l:输出main类或jar完全限定名称;
[]:主机id,默认为localhost;
jps是可以跨主机使用的,可以来连接到远程服务器上来用

jinfo:查看进程的运行环境参数,主要是jvm命令行参数;

在这里插入图片描述

依然探测不到,这个时候还是因为用systemd运行整个程序有关
但是依然可以显示工作在 server compiler detected下
jvm版本
但是java一些系统属性获取不到

jinfo:输出给定的java进程的所有配置信息;

jinfo [option]
-flags:to print VM flags 打印启动虚拟机的时候一些标记位
-sysprops:to print Java system properties
-flag :to print the value of the named VM flag 也可以看单个标记位的相关的值

jstack:查看指定的java进程的线程栈的相关信息;		jstack [-l] 
jstack -F [-m] [-l]
-l:long listings,会显示额外的锁信息,因此,发生死锁时常用此选项; -m:混合模式,既输出java堆栈信息,也输出C/C++堆栈信息; -F:当使用“jstack -l PID"无响应,可以使用-F强制输出信息;

jstat:对jvm应用程序的资源和性能进行实时监控;

**jstat:输出指定的java进程的统计信息

+java进程的 vmid能输出许多信息,可以自己定义 **
jstat -help|-options
jstat - [-t] [-h] [ []]
在这里插入图片描述

** jstat -options (可以显示支持哪些options) 这是1,8jdk所拥有的信息

-class:class loader 显示类相关的
-compiler:JIT 显示编译器相关的
-gc:gc 垃圾回收器
-gccapacity:统计堆中各代的容量
-gccause: 垃圾回收期回收垃圾的原因
-gcmetacapacity
-gcnew:新生代
-gcnewcapacity 新生代容量
-gcold:老年代
-gcoldcapacity 老年代容量
-gcutil
-printcompilation**

vmid号和进程号不一样,应该没错,可能还是没找到在这里插入图片描述

**现在可能要换一个新的环境来生成一个java进程了,172.0.16.7这个地址,这样就不会因为本地压力过大,尤其是虚拟机
现在用展开包的格式来安装tomcat
1.先安装jdk **
在这里插入图片描述
2.去下载这个包
在这里插入图片描述
3.制作软链接(错误的链接),不能在这里直接启动,因为用的是管理员账号
在这里插入图片描述
4.还需要创建一个tomcat用户,之前的软链接创建错了
在这里插入图片描述
su 到tomcat用户直接运行
在这里插入图片描述
8080监听了就说明进程起来了
还是探测不到可能是jdk问题
在这里插入图片描述
rpm包安装的方式还需要做初始化,要些sh脚本
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
*现在就需要安装tomcat了,把tomca包复制过去 **
在这里插入图片描述
,只改文件,不改目录本身
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
载入下整个脚本
。/etc/profile.d/java.sh
。/etc/profile.d/tomcat.sh
在这里插入图片描述
这样就可以,看来是和jdk本身的使用方式有关系
在这里插入图片描述
**s0c s1c 存活区0 存活区1
EC eden区
oc 老年代
mc meta space 元数据 jdk8才有
ygc 新生代 回收 次数发生的比例
fgc 老年代回收 **
1000毫秒=1s种采样一次,一直显示整个堆内存的垃圾回收器工作的方式
在这里插入图片描述
也可以指定只显示几次
在这里插入图片描述
c表示总空间容量,u表示用了多少
EC eden空间容量 EU Eden空间已用空间
OC 老年代容量 OU 老年代空间
MC 源空间容量 MU 元空间使用
YGC:新生代的垃圾回收次数;
YGCT:新生代垃圾回收消耗的时长;
FGC:Full GC的次数; 完全GC,对整个java程序来讲是致命的灾难,一旦java虚拟机发生FGC,意味着你的内存空间不够用,不得不stop world,整个内存空间标记为0回收
FGC次数太多,意味着你的内存被满掉的次数太多了(要么区找找程序代码是不是由内存溢出泄露了,分配多少都会回收,要么就是给的内存空间太小了
FGCT:Full GC消耗的时长;
GCT:GC消耗的总时长;

只要做运维必然会遇到java代码程序运行太慢的状况,使用jsp查看参数,真正要知道哪里是不是有内存泄露,不是你的工作能力,还需要懂jvm虚拟机编程机制才可以,不然你就需要背锅

如果检查没问题,你就要告诉程序员,要么内存泄露,你需要看一下代码
这就是jstat -gc

[
[
]] interval:时间间隔,单位是毫秒; count:显示的次数;

-gc:

YGC:新生代的垃圾回收次数;
YGCT:新生代垃圾回收消耗的时长;
FGC:Full GC的次数;
FGCT:Full GC消耗的时长;
GCT:GC消耗的总时长;

# jstat -options

-class:class loader
-compiler:JIT
-gc:gc
-gccapacity:统计堆中各代的容量 (没指明老年代或者新生代多大的,就是按一定比例分配)
-gccause:
-gcmetacapacity
-gcnew:新生代
-gcnewcapacity
-gcold:老年代
-gcoldcapacity
-gcutil
-printcompilation
在这里插入图片描述
jstack几乎没有用,分析代码内部属性的
在这里插入图片描述
jstack:查看指定的java进程的线程栈的相关信息;
jstack [-l]
jstack -F [-m] [-l]
-l:long listings,会显示额外的锁信息,因此,发生死锁时常用此选项;
-m:混合模式,既输出java堆栈信息,也输出C/C++堆栈信息;
-F:当使用“jstack -l PID"无响应,可以使用-F强制输出信息;
在这里插入图片描述
看不懂代码就没有用
只需要记住,jps,jstat,jinfo
在这里插入图片描述
cicompilercount编译的次数’
naxnewsize新生代空间大小
使用什么垃圾回收器
还可以定义哪一代的垃圾回收器算法
在这里插入图片描述
还有两个图形化工具
在这里插入图片描述
是可以用图形界面去查看指定的java进程的信息,这两个工具是可以用远程的查看其他主机的信息,如果不指定主机可以看本地的
对方主机要打开jmx才可以
在这里插入图片描述
探测本地有两个进程,链接以后显示整个进程的概览
jconsole
在这里插入图片描述
jvm参数就是启动传入的参数
在这里插入图片描述有图形在这里插入图片描述
profiler可以对性能做分析
在这里插入图片描述java程序的确非常消耗资源
监控也无非是引用多少类,创建多少对象,打开多少进程
jconsole看起来更美观一点,看到的参数其实和jstat没什么不同,只不过更直观而已
将来会用监控系统加载它来监控的,需要打开jmx接口,java监控扩展
叫做java性能指标观察工具
jps jinfo jstat 比较有用
jconsole和jvlsualvm

转载地址:http://fdkgn.baihongyu.com/

你可能感兴趣的文章
使用 docker 构建分布式调用链跟踪框架skywalking
查看>>
Github Actions 中 Service Container 的使用
查看>>
别在.NET死忠粉面前黑.NET5,它未来可期!
查看>>
Winform 进度条弹窗和任务控制
查看>>
部署Dotnet Core应用到Kubernetes(二)
查看>>
持续交付二:为什么需要多个环境
查看>>
FreeSql接入CAP的实践
查看>>
浅析 EF Core 5 中的 DbContextFactory
查看>>
听说容器正在吃掉整个软件世界?
查看>>
真实经历:整整一年了,他是这样从程序员转型做产品经理的
查看>>
netcore一键部署到linux服务器以服务方式后台运行
查看>>
还在犹豫是否迁移.NET5?这几个项目已经上线了!
查看>>
被 C# 的 ThreadStatic 标记的静态变量,都存放在哪里了?
查看>>
ASP.NET Core使用HostingStartup增强启动操作
查看>>
结合控制台程序和K8S的CronJob完成定时任务
查看>>
WPF开发的实用小工具 - 快捷悬浮菜单
查看>>
.Net orm 开源项目 FreeSql 2.0.0
查看>>
IdentityServer4系列 | 简化模式
查看>>
小试YARP
查看>>
如何使用 C# 中的 HashSet
查看>>