预见猿份
主题
首页面试题模拟面试SQL练习在线工具关于我们老苗一对一私教学员评价
实战项目
零基础学习路线项目前置基础创新WMS项目Java微服务框架与实战云岚到家项目闪聚支付项目学成在线项目青橙电商项目JVM原理与实战调优分布式事务专题Java高频面试题MySQL从入门到精通达梦数据库从入门到实战MongoDB从入门到实战PostgreSQL从入门到实战TiDB从入门到实战Java数据结构与算法Java 并发编程(JUC)实战课程老苗一对一私教学员评价
blog我的会员
  • JVM 原理与实战调优

    • 课程介绍
    • JVM 虚拟机内存管理、性能工具、OOM & 死锁实战
    • 垃圾回收 判断垃圾、回收算法、各类收集器
    • JVM 调优实战、类文件结构、类加载机制、编译优化







----- 到底线了 -----

1、JVM调优实战 ​

通过前面的课程学习我们已经掌握了JVM调优的基本知识,下面我们进行实战,通过在Linux平台运行web项目,然后进行对其进行压力测试,我们通过对JVM的调优来观察是否对服务的性能有了提升。

最后我们将总结优化的经验以及一些建议。

1.1、环境准备 ​

测试环境需要1台Linux支持。

IP开放端口内存说明
192.168.31.13380804GB运行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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

image-20200513101514585

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
1
2
3
4
5
6
7
8
9

重新启动tomcat。

查看是否已经启动成功:http://192.168.31.133:8080/movie/query

image-20200520221416495

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;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
🔒关注公众号,免费阅读全文

请免费关注 预见猿份 公众号,发送:yjoffer.com,获取解锁密码

公众号二维码微信扫码关注

关注公众号回复获取密码后,在下方输入并点击解锁,本机后续再读无需重复输入。

← 垃圾回收 判断垃圾、回收算法、各类收集器








如果发现文档内容有错误或排版错乱,请及时联系站长老苗修改,不胜感激。联系我们
关于我们 | 隐私政策 | 豫ICP备2026003386号-4 | 豫公网安备41010202004008号
目录

本页无章节