Hadoop+hive+flask+echarts大数据可视化项目之flask结合echarts前后端结合显示hive分析结果

发布于:2023-01-26 ⋅ 阅读:(17) ⋅ 点赞:(0) ⋅ 评论:(0)

Hadoop+hive+flask+echarts大数据可视化项目(五)

------flask与echarts前后端结合显示hive分析结果-------

        关注过Hadoop+hive+flask+echarts大数据可视化项目的读者,这里是第五部分。前面的部分完成了Hadoop环境的搭建,并把系统收集的相关信息上传到了Hadoop平台中,hive导入hadoop中的数据完成了数据的分析部分。现在需要flask后端接口技术结合前端echarts框架进行图表展示。

一、Flask后端接口技术

        Flask是由python开发的轻量的web框架,小巧,灵活,一个脚本就可以启动一个web项目。

        Flask的程序思路可以从点餐平台的点餐流程说开去。

1、由点餐说到flask返回页面内容

        说到点餐,一般是在饿了吗或者美团这个平台上选择你喜欢的菜品,在这个平台上面集中了很多商家的特色食品,凉菜、热菜及特色菜应用尽有。你点过餐了以后,你只需要等待外卖小哥把订餐送到你的手中就可以了。然而,外卖小哥接单后,需要到指定的餐馆购买指定的食品,如我点了一家“黄焖鸡”主题店的“大份黄焖鸡米饭”,外卖小哥就要到指定的“黄焖鸡”主题店购买到指定的“大份黄焖鸡米饭”后,马不停蹄地来到顾客面前来送餐,外卖小哥接单的时候,有的是携带着顾客的要求,“不吃辣,不吃香菜”等要求,回来送到顾客手中的时候,一定是一碗大份的黄焖鸡米饭。具体流程如下图所示。

        flask编程程序的思路与我们日常点餐的流程是一致的。这里的Flask程序就可以理解成点餐平台,在点餐平台上有很多的菜品,在实现python程序时,调用主程序会使name==”main”语句,这表明name中不光只有main,可能还有其它进程,只有name的进程名称是main时,才会触发主程序的执行。那么name中的名字就可以形象地理解成各中特色的菜单,Flask平台中把name包裹起来,就相当于把菜单上传到到点餐平台中。然后点餐平台就可以调用外卖小哥对客户的点餐进行接单和跑单。代码如下。

#导包
from flask import Flask
#相当于把菜单整合到平台中
app=Flask(__name__,template_folder="myfolder")
#调用主程序
if __name__=="__main__":
    #相当于app理解成外卖小哥,代替本人去购餐送餐
    app.run()

        目前,上面的代码没有实现点餐,只有点过餐了,外卖小哥才会有目地性的去跑,现在相当于的哥没有乘客时的瞎转,一直在寻找着乘客,代码中没有指定具体点餐内容的flask就相当于外卖小哥没有接单时,在漫无目的的等待。只有客户有新的订单,外卖小哥接到单后,就会到指定的地点购餐,然后把购得的餐再返回给客户。点餐的实现就是限定了外卖小哥只能到指定的地点进行购买指定的餐饮,不然客户是不能接受付款的。Python需要一个技术实现特定条件限定的方法,即满足只有黄焖鸡店才能购买的黄焖鸡米饭。实现这个技术的方法在Python中使用装饰器即可以做到,装饰器可以实现满足一定函数要求的内容才能访问这个页面。如访问百度页面,只有满足输入“www.baidu.com”这样的网址才能访问百度页面。因此,装饰器的技术只需限定只有某个地址才能访问相关的页面,其他的地址是不能访问此页面的。flask中提供的路由技术实现了这样的需求。这样,通过@app.route指定具体的地址去做什么样的事情就可以了。@app.route就是修饰def方法的路由。在def修饰的方法中必须返回内容相当于返回的餐饮,如是程序员中最精典的程序“Hello World”,“你好,世界”展现了程序员拥抱世界的态度。

        代码修改如下。

#导包
from flask import Flask
#相当于把菜单整合到平台中
app=Flask(__name__,template_folder="myfolder")
#理解成点餐,点餐必须有一地址,还有一个功能,功能里面必须有返回
#下面的功能表示在页面显示Hello World,必须访问是/hello才可以
#显示文字
@app.route("/hello")
def hello():
    return "Hello World!"
#调用主程序
if __name__=="__main__":
    #相当于app理解成外卖小哥,代替本人
    app.run()

        这样的程序,其对应的图形解释与点餐的图形解释大同小异,如下图所示的具体解释。

        由图中所示,首先由用户提出访问“baidu.com”的请求,然后程序交由flask通过技术手段找到baidu.com对应的方法,这里@app.route称为路由技术,def就是路由技术装饰器装饰的方法,由路由找到方法,在方法中会有flask技术做为拉车人,把return的内容装在车上,带回到用户请求的浏览器中,最终产生的百度的页面。

                “Hello World”的实现就是如此,用户提出访问“/hello”,然后程序交由flask通过@app.route的路由技术找到“/hello”修饰的def方法,其方法内部返回“Hello World”的文字内容,flask技术把return的内容“Hello World”装在车上,带回到用户请求的浏览器中,最终产生的“Hello World”内容的显示。

2、flask返回页面

        Flask除了返回页面中的内容外,还可以返回一个html页面。

        Flask返回页面是有一定规定的,就像文件有一定的管理一样,flask规定把所有的html页面放在一个template模板指定的目录下,相当于管理日常的文件内容,不然就很杂乱,就像原来返回了一个简单内容的人力车,现在返回的是豪华汽车,豪华汽车会通过防止碰撞的保护措施,因此在特定的地方存放豪华汽车。

        Flask通过初始化时指定templatefolder的目录,也就是html页面模板所在的目录位置,这个目录位置一定位于项目目录下。Html页面在这个指定的templatefolder中,然后在返回数据的时候通过render_template渲染模板的方法来渲染最终的html页面。具体代码如下。

from flask import Flask,render_template
#相当于把菜单整合到平台中,整合时指定网页的模板位置,携带参数template_folder
app=Flask(__name__,template_folder="myfolder")
#显示页面,需要使用render_template
@app.route("/index")
def myindex():
    return render_template("index.html")
if __name__=="__main__":
    #相当于app理解成外卖小哥,代替本人去购餐送餐
    app.run()

        其代码对应的项目结构目录如下图所示。

        在图中指示的项目目录下有一个myfolder的文件夹,是代码初始化Flask时指这下的templatefolder的值,在myfolder的文件夹下有一个index.html文件,这个文件在myindex()方法中return返回的rendertemplate渲染index.html页面。

        这里的index.html页面的代码如下。

        运行此flask程序后,通过flask装饰器路由限制访问“/index”,在浏览器中访问“http://localhost:5000/index”的地址显示的效果如下图所示。

3、flask返回接口

        企业中常见的开发方式为前后端分离式开发,对于前后端分离式开发主要以开发接口为主要内容,开发接口的实质就是flask程序中返回的数据是json数据。Python程序中可以创建json数据,然后在返回前端时调用json模块的dumps方法将json数据转换成字符串,这样前端接收到的就形成了json数据。

        代码如下。

from flask import Flask,render_template
#导入json模块
import json
#相当于把菜单整合到平台中,整合时指定网页的模板位置,携带参数template_folder
app=Flask(__name__)
#返回json数据,企业常用
@app.route("/json")
def myjson():
    a=a={"书名":"三国演义","作者":"罗贯中"}
    #dumps把json数据转成字符串
    return json.dumps(a,ensure_ascii=False)
if __name__=="__main__":
    #相当于app理解成外卖小哥,代替本人去购餐送餐
    app.run()

        注意,代码中使用dumps时使用了参数ensure_ascii,这个参数可以使数据在返回前端时保持编码不变,否则数据返回前端的编码为unicode编码,最终显示到页面的数据都是“\u49ff”等形式,用户很难识别出这是一个什么样的汉字。这样的代码运行后,通过flask装饰器限定的访问地址/json,所以在浏览器中访问http://localhost:5000/json的结果如下图所示。

        从html页面中的显示结果可以看出,flask接口返回了关于“三国演义”的json数据。

二、服务器端hiveserver2的启动

        大数据分析结果最终需要在前端展示hive的分析结果。如果实现hive的分析结果展示,必须通过flask连接hive,然后把hive的分析结果数据形成接口,这样前端获取这个接口数据后,就可以调用echarts框架进行前台图表的展示。

        Flask实现hive的连接必须使hive服务器启动metastore和hiveserver2两个服务,这两个服务一般都是有自己的进程的,linux终端运行时是不能够退出进程的。这里使用linux界面中的两个终端来运行metastore和hiveserver2。

        首先打开一个终端,先需要保证hadoop和zookeeper已经启动,jps查看进程如下图所示。

        图中关于hadoop启动的五个服务:NameNode,DataNode,SecondaryNameNode,ResourceManager和NodeManager,还有zookeeper的一个单机服务:QuorumPeerMain。在这种情况下,再进行hive的bin目录。如下图所示。

        在bin目录下,进入hive服务时开启metastore,使用指令如下。

./hive --service metastore

        使用命令后,显示效果如下图所示。

        接下来,在linux中再打开一个终端,便于启动hiveserver2。如下图所示。

        在这个终端中,仍然进入hive的目录中。在目录中启动hiveserver2,所使用的启动命令如下:

./hiveserver2

        运行后结果如下图所示。

        接下来再打开一个终端,其目的是使用beeline来测试连接一下hiveserver2,检查一下hiveserver2是否能够正常连接。

        进入beeline的指令如下。

./beeline

        执行指令后的结果如下图所示。

        如上图所示,当出现“beeline>”时表示beeline启动成功。

        进入beeline命令行后,使用!Connect命令来进行hiveserver2的连接测试,hiveserver2连接时的协议名称为jdbc:hive2,其地址是本机的ip地址,连接的端口号默认为10000。连接命令完整如下。

!connect “jdbc:hive2://192.168.110.156:10000”

        输入命令执行后,如下图所示。

        如上图所示,首先询问了连接的用户名,这里还不清楚具体的的用户名,直接回车,看下一步会提问什么内容。如下图所示。

        如上图所示,下一步又提问了密码的相关内容,这里也不清楚,直接回车,回车后就显示出报错信息如下图所示。

        图中标黄的部分显示,root并没有被允许实现anonymous,其原因可以通过hive-site.xml文件中获知,通过ftp下载hive-site.xml到本地,然后打开hive-site.xml文件,通过记录本的ctrl+f来搜索“hive.server2.thrift”这个关键词。在搜索的过程中,注意user和password选项。如下图所示。

        上图中搜索到标黄的选项,一个是“hive.server2.thrift.client.user”,一个是“hive.server2.thrift.client.password”,这两个选项的内容一个是设置hiveserver2登录的用户名,一个是设置hiveserver2登陆的密码,默认的情况下,两个都是anonymous,也就是匿名登录,这里将用户名设置为“root”,密码设置为“admin”,具体设置内容如下图所示。

        设置成功后,继续ftp上传hive-site.xml后,再次使用!Connect连接hive服务器,输入用户名和密码后的效果如下图所示。

        从结果图中看,又出现了报错信息,“root is not allowed to impersonate root”的信息报错根源在于hadoop平台不允许root用户的访问,因为hive中的数据是存储在hadoop平台中的。所以需要修改hadoop平台配置文件core-site.xml,在这个配置文件中指明root的权限。具体配置内容如下。

<property>
    <name>hadoop.proxyuser.root.hosts</name>
  <value>*</value>
</property>
<property>
       <name>hadoop.proxyuser.root.groups</name>
       <value>*</value>
</property>

        将上述内容添加到hadoop的配置目录下的core-site.xml中。具体的目录位置和文件指示如下图。

                修改core-site.xml中的内容,配置内容如下图所示。

        配置内容成功后,保存core-site.xml。然后需要重启虚拟机。重新启动hadoop、zookeeper服务,继续使用./hive --service metastore使用元信息存储hive,并启用另一个终端开启./hiveserver2服务,再打开另一个终端开启./beeline服务。进入beeline命令行后,再次使用!Connect连接hiveserver2服务器,如下图所示。

        上图中已经连接上了hiveserver2的服务器。这里beeline正常连接就会出现如下提示。

0: jdbc:hive2://192.168.110.156:10000> 

        可能在连接的过程中,也会出现非正常连接的情况,如下图。

        图中这种情况,可以多连接几次,很可能是延迟的问题。

        当beeline能够正常连接hiveserver2以后,就可以使用flask程序去连接hiveserver2了。

三、flask连接hive

        Flask是通过impyla模块实现与hive服务器的连接的。Impyla模块的安装可以使用如下命令。

pip3 install impyla

        安装成功后,先调用impyla中的connect方法连接服务器启动的hive2,连接时需要提供服务器的ip地址host,服务器连接的端口号port,服务器连接的用户名user和密码password,服务器连接的数据库名称database,其中最重要的是连接的认证,这里的认证auth_mechanism可以设为“PLAIN”。这样第一步连接的指令如下。

#连接hive2的服务器
conn=connect(host="192.168.110.156",port=10000,user="root",password="admin",auth_mechanism="PLAIN")

        连接hive服务器后,需要设置游标,游标这里指一种能从包括多条数据记录的结果集中每次提取一条记录的机制,游标中可以获取数据库查询的最终结果,这里必须获取游标,然后才能调用游标的execute执行方法执行HQL指令。获取游标和执行execute的HQL指令代码如下。

#连接后,获取游标,标志指示数据库的当前记录
cursor=conn.cursor()
#游标帮助我们执持HQL语句
cursor.execute("select hour(sysdate),max(cpu_us) from system group by hour(sysdate)")

        执行HQL语句后,其结果可以使用fetchall()方法来获取其结果,这里获取的是以小时为单位的cpu用户使用率峰值情况。由于小时分组后包括了很多个区间,会返回一个列表的结果集。结果集最好以json的形式返回前端,所以把结果集构造在json数据中,具体代码如下。

#查询的结果在cursor.fetchall方法中
results=cursor.fetchall()
#构造json数据
a_json={"result":results,"status":200}
#返回前端json数据集
return json.dumps(a_json,ensure_ascii=False)

        由于hive服务器是客户端进行连接的,不一定每次都会成功,可能由于网络情况造成hive服务器不可达,这里对hive的连接可以使用try...except的写法,防止代码出现连接hive服务器的意外。

        修改后的具体代码如下。

@app.route("/link")
def link():
    try:
        #连接hive2的服务器
        conn=connect(host="192.168.110.156",port=10000,user="root",password="admin",auth_mechanism="PLAIN")
        #连接后,获取游标,标志指示数据库的当前记录
        cursor=conn.cursor()
        #游标帮助我们执持HQL语句
        cursor.execute("select hour(sysdate),max(cpu_us) from system group by hour(sysdate)")
        #查询的结果在cursor.fetchall方法中
        results=cursor.fetchall()
        a_json={"result":results,"status":200}
        print(a_json)
        return json.dumps(a_json,ensure_ascii=False)
    except:
        return json.dumps({"result":"网络连接错误","status":404},ensure_ascii=False)

        整体代码封装在函数link中,并使用@app.route装饰器限定访问地址必须是“/link”,这样,浏览器中输入“/link”后,可以得到json数据的返回结果,也就构成了flask连接hive的接口,运行结果如下图所示。

        图中可以看到返回的列表数据,其中列表中每个元素由两个子项构成,第一个子项表示分隔的小时数,第二个子项表示这段小时时间内的峰值。如果访问地址后,没有出现结果,可能由于防火墙的问题。

        停止本次防火墙,可以使用如下命令。

systemctl stop firewalld.service

        如果需要下次启动时,防火墙也会停止,需要设置如下命令。

systemctl disable firewalld.service

        确认防火墙是否关闭或者开启的状态查询命令如下。

systemctl status firewalld.service

        查询防火墙状态如果是开启的,会在输出信息中显示running,如下图所示。

        图中标绿的部分为“active(runing)”表示防火墙开启,如果防火墙处于关闭状态,如下图所示。

        上图中这里显示的防火墙状态为“dead”,表示防火墙没有开启。这里flask客户端是可以连接到hive服务器的。

四、前端展示echarts数据图表

        由于echarts是一个图表类的前端插件,需要编辑专门的html页面来显示,同时echarts插件也需要与前端框架jquery相配合完成图表的展示。Html页面需要配合于模板的设置,这里在项目目录下建立myfolder目录,然后在myfolder目录下建立页面myweb.html。建立的这个页面中就是显示echarts图表的界面,由于echarts图表需要前端框架jquery和echarts的文件支持,这里需要在中引入两个js的文件。文件的地址可以使用bootcdn网站的技术,cdn是一种网站分发技术,对于处理前端页面中js的加载速度比较快。可以在百度的首页搜索“bootcdn”关键词。如下图所示。

        上图中点击第二项“BootCDN-Bootstrap中文网开源项目免费CDN加速服务”,就会进入到bootcdn网站界面,在界面中先输入“jquery”框架名称,如下图所示。

        在输入“jquery”结果后,在bootcdn网站页面中显示的第一项就是“jquery”的链接,直接点击输入框下面列的第一项“Jquery”。出现的结果如下图所示。

        在上图的页面结果中选择一种“jquery.js”的文件,点击右上角的“复制script标签”,然后把复制的标签ctrl+c粘贴在myweb.html页面的和之间。如下图所示。

        接下来继续回到bootcdn页面搜索“echarts”,在出来的结果中点击第一项“echarts”,如下图所示。

        进入echarts当中后,找到只有echarts的内容才可以复制script标签,凡是echarts后面带有其它内容的都不在此次设置文件中。如下图所示。

        复制script标签之后,把复制的代码ctrl+c粘贴在和标签之间,如下图所示。

        接下来使用echarts技术去完成页面的开发。

        首先定义一个div,div在前端叫盒子。盒子里在可以放图片,可以放文字,整体盒子放在页面的哪个位置,就可以形成页面的样式。引入div盒子的时候必须指定盒子的宽和高,也就是width和height的属性,同时div能够被echarts调用,其根本原因在于div有一个id属性,id属性也是echarts能够在此div中显示图表的关键。因此在定义div时,必须指定width、height属性及id值。代码如下。

        如上图所示,body标签中定义了一个〈div〉,接下来就要定义echarts部分的代码。Echarts的代码是需要写在标签。

        Script中间的逻辑部分,首先需要通过id获取div元素,这里使用js语言的document.getElementById方法通过id值来获取此div元素。代码如下。

var chartDom=document.getElementById(“mydiv1”)

        获取元素后,echarts框架会使用init方法进行初始化。代码如下。

myChart=echars.init(chartDom)

        当显示图表的div元素被echarts初始化之后,就可以调用echarts图表展示的option来定义具体图表展示的数据以及图表样式,echarts的图表option可以通过echarts的官网来查询具体的option设置,如下图echarts官网中各种图形的option指示。

        上图中展示的是echarts仪表盘的官网option选项。这里可以直接使用这个option,然后调用echarts初始化myChart变量的setOption方法,把这个option内容设置绑定在这个div元素上,就可以在div元素上显示echarts的内容。代码如下所示。

option = {
  tooltip: {
    formatter: '{a} <br/>{b} : {c}%'
  },
  series: [
    {
      name: 'Pressure',
      type: 'gauge',
      progress: {
        show: true
      },
      detail: {
        valueAnimation: true,
        formatter: '{value}'
      },
      data: [
        {
          value: 50,
          name: 'SCORE'
        }
      ]
    }
  ]
};
myChart.setOption(option)

        整个echarts图表展示的网页代码如下。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.3.3/echarts.js"></script>
</head>
<body>
<script>
var chartDom = document.getElementById('mydiv1');
var myChart = echarts.init(chartDom);
var option;

option = {
  tooltip: {
    formatter: '{a} <br/>{b} : {c}%'
  },
  series: [
    {
      name: 'Pressure',
      type: 'gauge',
      progress: {
        show: true
      },
      detail: {
        valueAnimation: true,
        formatter: '{value}'
      },
      data: [
        {
          value: 50,
          name: 'SCORE'
        }
      ]
    }
  ]
};
myChart.setOption(option)
</script>
</body>

        这样echarts框架页面就制作完成了。可以点击编辑器上方的浏览器看效果。具体点击位置如下图所示。

        点击代码编辑器右上角的浏览器看效果展示如下图所示。

        从图中展示可以看出,如果把仪表中的50换成20点的数值,就是cpu在20点的峰值,如果50换成21点的数值,那就是cpu在21点的数值,如果50换成22点的数值,就是cpu在22点时的数值。如果50换成23点的数值,就是cpu在23点时的数值。在linux系统获取数据中,只有4个时间的峰值。也就是显示这四个时段的cpu峰值。

        接下来需要清楚50的数据来自于后台,后台有一个地址/link,/link对应了一个cpu_us在4个时段的数值。也就是现在有一个数据的访问地址,缺少一个页面的访问地址,如果有一个页面的访问地址,在html页面中请求一个后端的/link地址,就可以显示页面了。这里html页面请求/link地址可以使用ajax,这是一个异步加载技术。

        在web1.0时代,没有ajax技术时,需要等待网页数据加载成功才能继续加载网页跳的其他元素,其原理图如下所示。

        从图中显示可以得知,前端必须等到数据过来时能全部显示所有元素。

        在web2.0的时代,数据由ajax来负责提交,如果有数据返回为,ajax就会对网页中没有填充数据的部分做填空题,不会影响网页中其他元素的加载。其原理图如下。

        类似于京东详情页,就是这样的情况,在最初打开页面时,价格数据是不显示的。如下图所示。

        上图中的数据是没有价格元素的,过一段时间,价格元素就会显示出来,其原因是此处的价格使用了ajax技术。Ajax技术可以理解成代办公司,代办了数据的提交业务。这里使用ajax的get方法,ajax的GET方式完成的是能够在网页地址栏敲出来显示的信息,/link的地址恰好满足这样的特征。

get方式的ajax使用格式如下。
$.get(“地址”,function(res){
请求成功后的内容
})

        通过格式得知,当数据请求成功后需要更新echarts中的图表。这里把echarts的图表信息写入到成功的function方法中,同时前端也需要对后端传来的json数据做json转换,前端的转换方法是JSON.parse()方法完成前端json数据的转换,转换后就可以把20点的cpu峰值数据取出,并显示到界面上。具体代码如下。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.3.3/echarts.js"></script>
</head>
<body>
<h1>20点cpu的峰值</h1>
<div style="width:400px;height:400px" id="mydiv1"></div>
<script>
var chartDom = document.getElementById('mydiv1');
var myChart = echarts.init(chartDom);
var option;
//由于成功以后改value值,ajax请求成功后改变表盘的值,数据采用GET方式
$.get("/link",function(res){
    //把option放在成功里,表示成功后加载数据
    //前端打印console.log
    console.log(res[0])
    //通过结果res[0]是一个"{",表示res是一个字符串
    //前端把res转换成json
    res=JSON.parse(res)
    //由于res.result是一个列表,列表第一个元素是由两个元素组成的列表,两个元素中第二个元素是20点的cpu峰值
    console.log(res.result[0][1])
    option = {
      tooltip: {
        formatter: '{a} <br/>{b} : {c}%'
      },
      series: [
        {
          name: 'Pressure',
          type: 'gauge',
          progress: {
            show: true
          },
          detail: {
            valueAnimation: true,
            formatter: '{value}'
          },
          data: [
            {
              value: res.result[0][1],
              name: 'SCORE'
            }
          ]
        }
      ]
    };
    //把option给图表
    myChart.setOption(option);
})

//myChart.setOption(option);
</script>
</body>
</html>

        其显示效果只有一个20点的数据展示表盘。现在加一个21点的峰值,首先在html代码中加入div,这个div的id与原来的id值有所不同。如下图所示。

        这里加入一个<h1>标签,表示“20点的cpu峰值”提示,如果增加一个21点的提示,代码如下。

        接下来修改js部分script里面的代码。需要再提取id为mydiv2的div元素,如下图所示。

        后面继续复制option,再产生一个option,复制成功后改变量名,改成option1。如下图所示。

        修改option的时候还需要修改加载成功的数据显示的内容,显示是列表中第二个数据的第二个值,相当于cpu在21的峰值。

        最后把显示的option设置的内容绘制到图表上,再复制一份setOption语句,如下图所示。

        依次类推,再产生另外两个时刻22点和23点的代码及html布局div,最终myweb.html页面代码如下。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.3.3/echarts.js"></script>
</head>
<body>
<h1>20点cpu的峰值</h1>
<div style="width:400px;height:400px" id="mydiv1"></div>
<h1>21点cpu的峰值</h1>
<div style="width:400px;height:400px" id="mydiv2"></div>
<h1>22点cpu的峰值</h1>
<div style="width:400px;height:400px" id="mydiv3"></div>
<h1>23点cpu的峰值</h1>
<div style="width:400px;height:400px" id="mydiv4"></div>
<script>
var chartDom = document.getElementById('mydiv1');
var chartDom1 = document.getElementById('mydiv2');
var chartDom2 = document.getElementById('mydiv3');
var chartDom3 = document.getElementById('mydiv4');
var myChart = echarts.init(chartDom);
var myChart1= echarts.init(chartDom1);
var myChart2= echarts.init(chartDom2);
var myChart3= echarts.init(chartDom3);
//由于成功以后改value值,ajax请求成功后改变表盘的值,数据采用GET方式
$.get("/link",function(res){
    //把option放在成功里,表示成功后加载数据
    //前端打印console.log
    console.log(res[0])
    //通过结果res[0]是一个"{",表示res是一个字符串
    //前端把res转换成json
    res=JSON.parse(res)
    //由于res.result是一个列表,列表第一个元素是由两个元素组成的列表,两个元素中第二个元素是20点的cpu峰值
    console.log(res.result[0][1])
    option = {
      tooltip: {
        formatter: '{a} <br/>{b} : {c}%'
      },
      series: [
        {
          name: 'Pressure',
          type: 'gauge',
          progress: {
            show: true
          },
          detail: {
            valueAnimation: true,
            formatter: '{value}'
          },
          data: [
            {
              value: res.result[0][1],
              name: 'SCORE'
            }
          ]
        }
      ]
    };
    //复制option ,修改变量名option1
    option1 = {
      tooltip: {
        formatter: '{a} <br/>{b} : {c}%'
      },
      series: [
        {
          name: 'Pressure',
          type: 'gauge',
          progress: {
            show: true
          },
          detail: {
            valueAnimation: true,
            formatter: '{value}'
          },
          data: [
            {
              value: res.result[1][1],
              name: 'SCORE'
            }
          ]
        }
      ]
    };
     //复制option ,修改变量名option2
    option2 = {
      tooltip: {
        formatter: '{a} <br/>{b} : {c}%'
      },
      series: [
        {
          name: 'Pressure',
          type: 'gauge',
          progress: {
            show: true
          },
          detail: {
            valueAnimation: true,
            formatter: '{value}'
          },
          data: [
            {
              value: res.result[2][1],
              name: 'SCORE'
            }
          ]
        }
      ]
    };
     //复制option ,修改变量名option3
    option3 = {
      tooltip: {
        formatter: '{a} <br/>{b} : {c}%'
      },
      series: [
        {
          name: 'Pressure',
          type: 'gauge',
          progress: {
            show: true
          },
          detail: {
            valueAnimation: true,
            formatter: '{value}'
          },
          data: [
            {
              value: res.result[3][1],
              name: 'SCORE'
            }
          ]
        }
      ]
    };
    //把option给图表
    myChart.setOption(option);
    myChart1.setOption(option1);
    myChart2.setOption(option2);
    myChart3.setOption(option3);
})

//myChart.setOption(option);
</script>
</body>
</html>

        后台flask连接hive并提供查看页面的程序myconnect.py代码如下。

from flask import Flask,render_template
#导入json模入
import json
#导入impyla中的dbapi
from impala.dbapi import connect
#相当于把菜单整合到平台中
app=Flask(__name__,template_folder="myfolder")
#定义根路径,专门访问myweb.html
@app.route("/")
def index():
    return render_template("myweb.html")
#定义一个连接hive的接口地址
@app.route("/link")
def link():
    try:
        #连接hive2的服务器
        conn=connect(host="192.168.110.156",port=10000,user="root",password="admin",auth_mechanism="PLAIN")
        #连接后,获取游标,标志指示数据库的当前记录
        cursor=conn.cursor()
        #游标帮助我们执持HQL语句
        cursor.execute("select hour(sysdate),max(cpu_us) from system group by hour(sysdate)")
        #查询的结果在cursor.fetchall方法中
        results=cursor.fetchall()
        a_json={"result":results,"status":200}
        print(a_json)
        return json.dumps(a_json,ensure_ascii=False)
    except:
        return json.dumps({"result":"网络连接错误","status":404},ensure_ascii=False)

if __name__=="__main__":
    #相当于app理解成外卖小哥,代替本人去购餐送餐
    app.run()

        运行这个flask程序,最终在页面上显示的效果图如下。

欢迎关注Hadoop+hive+flask+echarts大数据可视化项目,后续会有持续的精彩。

博客中部分采集的数据可以在github地址中下载:

https://github.com/wawacode/system_info_bigdata_analyse