1、JVM调优实战
通过前面的课程学习我们已经掌握了JVM调优的基本知识,下面我们进行实战,通过在Linux平台运行web项目,然后进行对其进行压力测试,我们通过对JVM的调优来观察是否对服务的性能有了提升。
最后我们将总结优化的经验以及一些建议。
1.1、环境准备
测试环境需要1台Linux支持。
| IP | 开放端口 | 内存 | 说明 |
|---|---|---|---|
| 192.168.31.133 | 8080 | 4GB | 运行web项目 |
jdk使用的版本为jdk8,需要在Linux服务器中安装jdk8:
shell
#将资料中的jdk-8u144-linux-x64.tar.gz上传到/usr/local/src下
tar -xvf jdk-8u144-linux-x64.tar.gz
#修改环境变量
vim /etc/profile
#set java environment
#JAVA_HOME=/usr/local/src/jdk-11.0.7
JAVA_HOME=/usr/local/src/jdk1.8.0_144
CLASSPATH=.:$JAVA_HOME/lib.tools.jar
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME CLASSPATH PATH
#使环境变量立即生效
source /etc/profile
#测试
[root@itcast src]# java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)1.1.1、安装tomcat
tomcat服务器在JavaEE项目中使用率非常高,所以在生产环境对tomcat的优化也变得非常重要了。
对于tomcat的优化,主要是从2个方面入手,一是,tomcat自身的配置,另一个是tomcat所运行的jvm虚拟机的调优。
shell
cd /gc
wget http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-8/v8.5.34/bin/apache-tomcat-8.5.34.tar.gz
tar -xvf apache-tomcat-8.5.34.tar.gz
cd apache-tomcat-8.5.34/conf
#对tomcat进行优化配置
vim server.xml
#优化一:禁用AJP服务,一般是使用Nginx+tomcat的架构,所以用不着AJP协议,所以把AJP连接器禁用。
#将下面的配置注释掉
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
#优化二:设置线程池,并且调整最大并发线程数
<!--将注释打开-->
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="500" minSpareThreads="50" prestartminSpareThreads="true" maxQueueSize="500"/>
<!--
参数说明:
maxThreads:最大并发数,默认设置 200,一般建议在 500 ~ 1000,根据硬件设施和业务来判断
minSpareThreads:Tomcat 初始化时创建的线程数,默认设置 25
prestartminSpareThreads: 在 Tomcat 初始化的时候就初始化 minSpareThreads 的参数值,如果不等于 true,minSpareThreads 的值就没啥效果了
maxQueueSize,最大的等待队列数,超过则拒绝请求
-->
<!--在Connector中设置executor属性指向上面的执行器-->
<Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
#优化三:设置tomcat运行模式为nio2,tomcat的运行模式有3种:bio、nio、apr,其中nio2是nio的升级版,在tomcat8中才支持的,建议采用nio2模式。
<Connector executor="tomcatThreadPool" port="8080" protocol="org.apache.coyote.http11.Http11Nio2Protocol"
connectionTimeout="20000"
redirectPort="8443" />
#启动tomcat
cd /gc/apache-tomcat-8.5.34/bin/
./startup.sh && tail -f ../logs/catalina.out
#打开浏览器进行测试访问
http://192.168.31.133:8080/
1.1.3、部署web项目
为了方便测试性能,我们将部署一个java web项目,这个项目本身和本套课程没有什么关系,仅仅用于测试。
在资料中找到itcast-gc-demo-1.0.war,上传到linux服务器,进行部署安装。
shell
cd /gc/apache-tomcat-8.5.34/webapps
rm -rf *
mkdir ROOT
cd ROOT/
rz上传war包
jar -xvf itcast-gc-demo-1.0.war
rm -rf itcast-gc-demo-1.0.war重新启动tomcat。
查看是否已经启动成功:http://192.168.31.133:8080/movie/query

1.1.4、测试项目
实现的功能:
- 读取电影文件movies.dat,载入到内存
- 查询电影数据时,随机返回1w ~ 10W个数据
代码:
java
package cn.itcast.gc.controller;
import cn.itcast.gc.service.MovieService;
import cn.itcast.gc.vo.Movie;
import cn.itcast.gc.vo.MyResult;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("movie")
public class MovieController {
@Autowired
private MovieService movieService;
@GetMapping("query")
public MyResult queryMovieList(){
MyResult myResult = new MyResult();
List<Movie> movies = this.movieService.queryMovieList();
myResult.setCount(movies.size());
myResult.setTop10(movies.subList(0, 9)); //只返回前10条数据,不要将性能损耗在传输上
return myResult;
}
}java
package cn.itcast.gc.service;
import cn.itcast.gc.vo.Movie;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@Service
public class MovieService {
private static final List<Movie> MOVIE_LIST = new ArrayList<>();
@Autowired
private ResourceLoader resourceLoader;
@PostConstruct
public void init() {
try {
//读取电影数据文件到内存
Resource resource = resourceLoader.getResource("classpath:movies.dat");
InputStream inputStream = resource.getInputStream();
List<String> lines = IOUtils.readLines(inputStream, "UTF-8");
for (String line : lines) {
String[] ss = StringUtils.split(line, "::");
Movie movie = new Movie();
movie.setId(Long.valueOf(ss[0]));
movie.setTitle(ss[1]);
movie.setPeoples(ss[2]);
//将数据放入到集合中
MOVIE_LIST.add(movie);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public List<Movie> queryMovieList() {
//随机1w ~ 10w条数据
int count = RandomUtils.nextInt(10000, 100000);
List<Movie> list = new ArrayList<>();
for (int i = 0; i < count; i++) {
int index = RandomUtils.nextInt(0, MOVIE_LIST.size() - 1);
Movie movie = MOVIE_LIST.get(index);
Movie newMovie = new Movie(); //为了加大内存的损耗,创建新的对象
newMovie.setId(movie.getId());
newMovie.setPeoples(movie.getPeoples());
newMovie.setTitle(movie.getTitle());
list.add(newMovie);
}
return list;
}
}关注公众号,免费阅读全文
请免费关注 预见猿份 公众号,发送:yjoffer.com,获取解锁密码
微信扫码关注关注公众号回复获取密码后,在下方输入并点击解锁,本机后续再读无需重复输入。
