最终效果
这个项目能收获什么
-
搭建一个spring boot项目
-
与mybatis整合实现基本的CRUD
-
前后端联动
-
缓存基本的应用(redis)
-
负载均衡的使用(nginx)
-
对Linux和shell文件有个基本了解
-
麻雀虽小,相信能收获颇多
这个项目干什么的
**计算Linux虚拟机指标。**包括内存使用率,cpu使用率,实时网速。获取hdfs的健康信息,包括配置容量,现有容量,DFS余量,非DFS使用量。并进行可视化展示
涉及技术
【必用】spring boot + Echarts + thymeleaf+【选用】Redis+Vue+Bootstrap
怎么去看
核心基本的看1-3部分,美化拓展的看4-5部分。每个模块都是可以拆分的,取你所需。只要其中有涉及到你想看的,那就值得一看。
源码地址
程序流程图
集群部署架构图
项目技术栈
负载均衡实现效果
目录
Java连接Linux
进行Linux指标展现
整合mybatis
获取hdfs数据
整合redis
整合nginx
第一部分【Java连接Linux】
本篇实现思路
利用Java去读取Linux中的文件,读出其中的信息,并将获得的字符串加以计算,通过控制层传给前端,利用前端进行展示。
本篇效果展示
实现步骤
-
Java利用ssh连接Linux
-
数据准备
-
提供一个可视化模型
-
进行前后端联动,异步将数据传输到页面上
1、Java利用ssh连接Linux
2、数据准备
(1)CPU使用率获取
command:top -b -n 1 | head -3
第三行为cpu状态: 依次对应: us:user 用户空间占用cpu的百分比 sy:system 内核空间占用cpu的百分比 ni:niced 改变过优先级的进程占用cpu的百分比 id:空闲cpu百分比 wa:IO wait IO等待占用cpu的百分比 hi:Hardware IRQ 硬中断 占用cpu的百分比 si:software 软中断 占用cpu的百分比 st:被hypervisor偷去的时间
计算方式:100-cpu空闲百分比
(2)内存使用率获取
command:cat /proc/meminfo
红框代表含义:总内存,空闲内存
计算方式:(总内存-空闲内存)/总内存
(3)实时网速获取
command:cat /proc/net/dev(记录了不同网络接口(interface)上的各种包的记录)
最左边的表示接口的名字,Receive表示收包(下载量),Transmit表示发送包(上传量)
需要一个脚本文件(获取实时网速和实时上传率,我只做了第一个)
简单介绍以下脚本含义:sed将:替换为空格全局匹配, awk读第二个,grep 按什么匹配,echo代表输出什么,剩下的有点语言底子的都应该可以看懂
计算方式:根据前后一秒网络下载量所产生的差值作为数据
3、可视化模板
我们需要一个可视化前端模板,我找了一个官方案例,效果如下
echarts.apache.org/examples/zh…
4、进行前后端数据交互
前端部分
后端部分
本部分小结
对学习了spring boot或者Echarts想要一个练手项目的时候,那么这个项目就适合你。我为什么没有直接利用Java去实现本机(windows)一些性能指标的监控呢,比如下图。因为Java并不能直接获取本机的一些数据,应该是操作系统层面的权限问题吧,这些都是我踩过的坑,我也只获取到了jvm层面
win10指标监控
第二部分【整合mybatis】
步骤
- 增加pom依赖
- 修改application配置文件
- 增加mapper配置文件
- 创建entity(存放实体类),dao(进行数据操作),service(业务层)的包
1、增加pom依赖
2、修改application配置文件
被注释的那一行代表输出sql语句
3、增加mapper配置文件
在这里说一下为什么使用mapper而不适用注解的方式,比如说下面这段代码
注解方式只适合简单sql语句,而mapper.xml是通用的
@Select("select * from user ")
结构图
4、创建entity(存放实体类),dao(进行数据操作),service(业务层)的包
结构图
entity的类(这里用了lombok,没有的话还需要补充get、set方法)
dao下的类
service下的类
service.impl下的类
红框外的表示与redis整合,先不看
controller下的类
一个返回页面,一个异步访问
本部分结果截图
第三部分【获取hdfs数据】
思路
第一部分获取了Linux指标的一些信息,这篇文章是获取hdfs的数据,也是为了与大数据挂钩,实现思路也和第一篇类似,举一反三,还可以获取别的信息,比如一些znone节点健康信息之类的,重要不是获取什么,而是怎么获取。
步骤
-
Java利用ssh连接Linux
-
将命令得出的字符信息进行处理
-
提供一个可视化模板
-
进行前后端联动,异步将数据传输到页面上
重复的步骤我就不写了,可以看第一部分
实现方式
通过Linux的命令去返回字符串
获取hdfs健康信息的命令是:dfs dfsadmin -report
这里需要注意的是,此命令耗时3秒左右,所以做工具类方法的时候需要在一个方法中处理,不然一个用3秒,多了就吃不消了。还有这个命令本身并不提供,这里说的是即使你/etc/profile下面配了也不行。如下图
原因简单的说一下吧,不想了解的跳过
jsch方式通过SSH2连接的。而SSH直接执行远程命令和脚本,会使用Bash的non-interactive + non-login shell模式,它会创建一个shell,执行完脚本之后便退出,不再需要与用户交互。 non-interactive shell 执行它创建的脚本,默认情况下这个环境变量并没有设置。 no-login shell 他代表不会去执行/etc/profile文件,而会去用户的HOME目录检查.bashrc并加载。 那怎么解决?通过原因我们可以知道需要在当前用户下.bashrc文件末添加环境变量,也就是说如果当前你使用的是root用户,那么修改的就是/root/.bashrc这个文件。第二种方式就是运行的时候命令前加一句环境变量,如下
export PATH=$PATH:/opt/hadoop-2.7.1/bin:/opt/hadoop-2.7.1/sbin;hdfs dfsadmin -report
该命令的结果为下图,我想要的数据为红框中的信息
获取方式
字符串的subString方法,通过找到"("的下标+1,"GB"的下标-1来获取。这提一下+1,-1的意思,不+1的话你获取到的是"(",而不是后面的内容。indexOf这个就是获取下标的方法,但只能获取到第一个返回的下标,那我要获取第二行红框的数据怎么办?通过indexOf("\n")来获取一行的下标,我要找第二行将这个x2就可以了,第三行x3。具体代码实现如下
实现结果
第四部分【整合redis】
项目只实现了单机版整合
步骤
- 增加pom依赖
- 修改application.properties
- 编写PortUtil工具类
- 编写RedisConfig类
- 编写redis工具类
- 对业务层进行修改
1、增加pom依赖
2、修改application.properties
3、编写PortUtil工具类
作用:在运行项目的时候需要判断redis服务启动没有。启动走redis,没启动走数据库。
4、编写RedisConfig类
作用:当添加Redis依赖后,SpringBoot会自动帮我们在容器中生成一个RedisTemplate和一个StringRedisTemplate,但是,这个RedisTemplate的泛型是<Object,Object>,在代码中会不可避免的需要类型转换,这样不够安全,也过于麻烦,而且RedisTemplate没有设置序列化方式,所以,需要配置Redis。一句话:防止乱码。
5、编写redis工具类
作用:对redis进行操作,比如增删改一个对象,方法太多了,只写了常用的。
放个代表性的图,我比较喜欢将工具类写为静态的,这样方便调用。而需要的一个redis模板类,不能够直接进行@Resource注入,所以需要set注入。hasKey是其中的一个方法,其他方法也都大差不差的。
6、对业务层进行修改
一般redis加在业务层。
create方法
get方法
可以利用redis可视化工具去查看运行情况,也可以通过在application配置文件中加入
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
这句作用是打印程序所运行产生的sql语句
本部分结果截图
控制台
第五部分【整合nginx】
对于只学过理论的人来说,这或许是一个练手机会。
不用我这个项目,任意一个spring boot项目都是可以的,我的每一部分都是独立的。最后效果是通过访问一个网址或者ip达到访问不同端口的目的。负载可以负载端口也可以负载IP,在于你怎么配置。
实现效果图
首先就是打包
将你的项目打成jar包
下面是关于idea如何打包的,会打包的自行跳过
打包步骤
-
pom文件中添加打包插件
-
增加所打的包的方式,jar就写jar,war就写war
-
利用maven自带插件打包(建议先clean)
1、pom文件中添加打包插件
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
不加这个插件的的后果,都是亲身试验过的坑啊
2、增加所打的包的方式,jar就写jar,war就写war
<packaging>jar</packaging>
3、利用maven自带插件打包(建议先clean)
4、jar包所在位置
最后提一下,我用过idea自带的打包工具就是那个build,然后运行的时候报的信息一大堆看不懂的,当然项目最后启动不了,可能是我方式不对,但我还是极力的不推荐,一是麻烦,二是需要注意的地方太多,用我上面这种就可以了。
这个是idea的自带打包方式
这个是自带打包方式出现的报错信息
打包跳过的来这里,步骤如下
- 设置一个方法返回各自的端口
- 定义不同的端口
- 将打好的包用名字进行区分
- 修改nginx.conf
- 依次启动jar包
- 访问路径验证效果
- 启动nginx
1、为了观察效果,可以控制器中设置一个方法返回各自的端口(就是我演示中的效果)
2、将项目打包,分别定义不同的端口8080,8081,8082
3、将打好的包用名字进行区分,放入Linux中
4、进入nginx的conf目录下修改nginx.conf
5、启动nginx.
./nginx
6、依次启动jar包(也可以使用一键启动脚本,后面说)
nohup java -jar xxx(nohup表示后台运行)
7、访问路径验证效果,一直刷新会观察到端口的变化
一键启动tomcat脚本(偷个懒,每次太麻烦)
#!/bin/bash
#@author dali
#统一启动3个jar包文件
#这里定义你的jar包名称
APP_NAME1=computer8080.jar
APP_NAME2=computer8081.jar
APP_NAME3=computer8082.jar
#使用说明,用来提示输入参数
usage() {
echo "Usage: sh 执行脚本.sh [start|stop|restart|status]"
exit 1
}
#检查8080是否在运行
is_exist1(){
pid1=`ps -ef|grep $APP_NAME1|grep -v grep|awk '{print $2}' `
#如果不存在返回1,存在返回0
if [ -z "${pid1}" ]; then
return 1
else
return 0
fi
}
#检查8081是否在运行
is_exist2(){
pid2=`ps -ef|grep $APP_NAME2|grep -v grep|awk '{print $2}' `
#如果不存在返回1,存在返回0
if [ -z "${pid2}" ]; then
return 1
else
return 0
fi
}
#检查8082是否在运行
is_exist3(){
pid3=`ps -ef|grep $APP_NAME3|grep -v grep|awk '{print $2}' `
#如果不存在返回1,存在返回0
if [ -z "${pid3}" ]; then
return 1
else
return 0
fi
}
#启动方法
start(){
is_exist1
if [ $? -eq "0" ]; then
echo "${APP_NAME1} is already running. pid=${pid1} ."
else
nohup java -jar $APP_NAME1 > /dev/null 2>&1 &
fi
is_exist2
if [ $? -eq "0" ]; then
echo "${APP_NAME2} is already running. pid=${pid2} ."
else
nohup java -jar $APP_NAME2 > /dev/null 2>&1 &
fi
is_exist3
if [ $? -eq "0" ]; then
echo "${APP_NAME3} is already running. pid=${pid3} ."
else
nohup java -jar $APP_NAME3 > /dev/null 2>&1 &
fi
}
#停止方法
stop(){
is_exist1
if [ $? -eq "0" ]; then
kill -9 $pid1
else
echo "${APP_NAME1} is not running"
fi
is_exist2
if [ $? -eq "0" ]; then
kill -9 $pid2
else
echo "${APP_NAME2} is not running"
fi
is_exist3
if [ $? -eq "0" ]; then
kill -9 $pid3
else
echo "${APP_NAME3} is not running"
fi
}
#输出运行状态
status(){
is_exist1
if [ $? -eq "0" ]; then
echo "${APP_NAME1} is running. Pid is ${pid1}"
else
echo "${APP_NAME1} is NOT running."
fi
is_exist2
if [ $? -eq "0" ]; then
echo "${APP_NAME2} is running. Pid is ${pid2}"
else
echo "${APP_NAME2} is NOT running."
fi
is_exist3
if [ $? -eq "0" ]; then
echo "${APP_NAME3} is running. Pid is ${pid3}"
else
echo "${APP_NAME3} is NOT running."
fi
}
#重启
restart(){
stop
start
}
#根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
"start")
start
;;
"stop")
stop
;;
"status")
status
;;
"restart")
restart
;;
*)
usage
;;
esac