<dl id="opymh"></dl>

<div id="opymh"></div>
      <div id="opymh"><tr id="opymh"></tr></div>

        <em id="opymh"><ins id="opymh"><mark id="opymh"></mark></ins></em><sup id="opymh"><menu id="opymh"></menu></sup>

        <em id="opymh"></em>

        <em id="opymh"><ol id="opymh"></ol></em>

              频道栏目
              首页 > 程序开发 > Web开发 > Python > 正文
              基于zabbix用Python写一个运维流量气象图
              2016-03-09 09:16:29           
              收藏   我要投稿

              前言£º同事问我£¬你写运维?#25945;?#26368;先写哪一部分£¿好吧£¬还真把我问倒了£¬因为这是在问最应该放在放在第一位的东西~作为一个工作不足两年£¬运维不足一年的新手来说£¬还真不敢妄下评论£¬其实按照我的思路£¬觉得最重要的部分肯定是?#25910;?#22788;理£¬报警£¬但是这一块怎么写£¿怎么说£¿肯定不能重复造轮子了£¬?#36824;?#25105;最想写的是报表系统£¬思路是有的£¬但是一直耽搁了£¬详情参考https://youerning.blog.51cto.com/10513771/1708925¡£

              好吧£¬在回到那个问题£¬应该先写哪个部分¡£我没回答£¬反问他了¡£

              他说£¬应该是运维气象图£¬这张图上有各个节点的位置£¬并且标注出流量情况£¬如果我们在服务器发生?#25910;?#30340;时候发现其中一个节点流量过高或者过低£¬或者一些其他指标£¬我们在一定程度上可以快速的地?#36824;收?#30340;位置¡£注£ºcacti£¬zabbix似乎是有这个插件的£¬?#36824;?#19981;是那么好看£¬或者有一定局限性£¬我也没调查过£¬反正不想用¡£

              然后£¬我被上了一课£¬ 那么为毛类似这样的应用或者框架之类的(除了上面说的两个插件£¬本人暂时没有Google或百度到£¬如果你知道抨击一下我呗£¬当然£¬最好是Python开发的£¬我好自定义一下),他说£¬收费的软件有~~~

               

              首先瞧瞧?#19968;?#20102;几天鼓捣出来的Beta版本吧£º

              wKioL1bcIAqwbO3OAACOSx9nVX4089.png

              现在£¬正题~~~

              如果你不会python就收藏着?#38498;?#30475;吧£¬当下就看看思路吧¡£

              如果你会python就在涉猎一下JS吧£¬比如AngularJS£¬D3JS什么的£¬?#36824;?#21487;以

              如果你什么都不会£¬希望能激发你的兴趣¡£

              如果你是大神£¬还执意要看就忽略我代码中的一些写的不优雅£¬不好看的地方吧T_T

              题外话£º话说£¬有什么觉得比较实用的功能是需要收费的£¬或者一些想法需要实现的可以Q我£¬我?#21069;?#23427;实现了(仅限于大概一周以内能写完的£¬特别有意思的来说)

              授人以鱼不如授人以渔嘛£¬主要两部分£¬一部分思路£¬一部分代码讲解

               

              £¨一£©

              思路

              Q:数据来源,通过写客户端£¿

              A:当然不£¬nagios£¬cacti£¬zabbix什么的不是有一大堆么£¬为毛还要自己写£¬而?#19968;?#19981;一定写的比别人好£¬美其名曰不愿重复造轮子~~~根据自己情况选择吧£¬这里就选的通过zabbix的API作为数据来源¡£

              Q:用什么web框架£¿

              A:用Flask£¬很?#19981;?#19968;句从网上看来的评论django的话£¬上它的人很多£¬?#19981;端?#30340;很少£¬再者£¬我实在不想去配置什么配置文件£¬以及帮我创建一大堆文件(当然?#37096;?#20197;不需要)£¬再再者£¬我的功能不需要太多£¬再再再者£¬flask的官方文档写得太棒了~~~

               

              然后瞧瞧我们写什么£¬完成什么~

               

              代码实现£º

              web框架flask

              功能页面£º

              页面一£º?#25925;?#39029;面(bootstrap提供样式效果£¬AngularJS实时数据查询并刷新£¬为毛不用jQuery£¿因为jQuery我不会T_T)

              页面二£º数据查询接口

              代码文件£º

              一£º用于查询数据的py模块 x 1

              二£º用于提供web界面的py文件 x 1

              三£ºhtml模板文件 x 3

              ?#27169;ºjs文件 x 2

               

              注£º其实个人不建议用模板渲染直接把数据渲染到?#25925;?#39029;面?#20808;¥£?#34429;然这样不用写js了£¬但是写到后面£¬你就难过了£¬所以前台后台分离吧£¬这里也是前台后台分离£¬前台bootstrap加AngularJS~~~

               

              £¨二£©

              代码

              zabbix数据获取

              获取zabbix数据可参考£ºhttps://youerning.blog.51cto.com/10513771/1740152第三部分~~

              所以直接放代码吧~~

              #coding=utf-8
              importjson
              importrequests
              frompprintimportpprint
              fromosimportpath
              ###zabbixapi访问地址
              zabbix_pre="https://10.10.102.88/zabbix/"
              zabbix_url=zabbix_pre+"/api_jsonrpc.php"
              ###用户名密码
              user=""
              passwd=""
              ###这里只查询进出口流量£¬所以只有下面两个关键字£¬后面可能会查询一些其他的~~~
              net_in="net.if.in[eth0]"
              net_out="net.if.out[eth0]"
              ###构造post请求提交的数据
              auth_data=json.dumps(
              {
              "jsonrpc":"2.0",
              "method":"user.login",
              "params":{
              "user":"%s"%user,
              "password":"%s"%passwd
              },
              "id":0
              })
              ###http头部信息£¬zabbix要求的
              headers={
              'content-type':'application/json',
              }
              ###构造一个返回查询hostid的json数据£¬函数是一等公民~~~
              defhost_data(auth):
              data=json.dumps(
              {
              "jsonrpc":"2.0",
              "method":"host.get",
              "params":{
              "output":["hostid","host"],
              "search":{"host":""}
              },
              "auth":"%s"%auth,
              "id":1,
              })
              returndata
              ###如上£¬查询hostid
              defhost_data_search(auth,search):
              data=json.dumps(
              {
              "jsonrpc":"2.0",
              "method":"host.get",
              "params":{
              "output":["hostid","name"],
              "search":{"host":search}
              },
              "auth":"%s"%auth,
              "id":1,
              })
              ###如上£¬查询itemid
              defitem_data_filter1(auth,hostid,filters):
              data=json.dumps(
              {
              "jsonrpc":"2.0",
              "method":"item.get",
              "params":{
              "output":["itemid"],
              "hostids":"%s"%hostid,
              "search":{
              "key_":filters
              }
              },
              "auth":"%s"%auth,
              "id":1,
              })
              returndata
              ###如上£¬查询item的所有信息£¬hostname£¬itemid一大堆
              defitem_data_filter2(auth,hostid,filters):
              data=json.dumps(
              {
              "jsonrpc":"2.0",
              "method":"item.get",
              "params":{
              "output":"extend",
              "hostids":"%s"%hostid,
              "filter":{
              "name":filters
              },
              "sortfield":"name"
              },
              "auth":"%s"%auth,
              "id":1
              })
              returndata
              ###如上£¬获取最新监控值
              defhistory_data(auth,itemid,limit,his=0):
              data=json.dumps(
              {
              "jsonrpc":"2.0",
              "method":"history.get",
              "params":{
              "output":"extend",
              "history":his,
              "sortfield":"clock",
              "sortorder":"DESC",
              "itemids":"%s"%itemid,
              "limit":limit
              },
              "auth":"%s"%auth,
              "id":1,
              })
              returndata
              ###构造获取zabbix验证id£¬为了反复操作£¬当然封装成函数
              defgetauth(zabbix_url,auth_data,headers):
              auth_ret=requests.post(zabbix_url,data=auth_data,headers=headers)
              auth_id=auth_ret.json()["result"]
              returnauth_id
              ###将所有结果保存成本地之间£¬结果包括£¬主机名(这里指zabbix上的命名)£¬hostid£¬出入口的itemid
              defsavefile():
              host_ret=requests.post(zabbix_url,data=host_data(auth_id),headers=headers)
              host_ret=host_ret.json()["result"]
              
              ###这里请根据实?#26159;?#20917;设定£¬比如包括nginx集群£¬mysql集群£¬tomcat集群£¬如下
              json_all={}
              json_all["nginx_cluster"]={}
              json_all["tomcat_cluster"]={}
              json_all["mysql_cluster"]={}
              forhostinhost_ret:
              hostid=host["hostid"]
              hostname=host["host"]
              item_ret=requests.post(zabbix_url,data=item_data_filter1(auth_id,hostid,"net.if"),\
              headers=headers)
              item_ret=item_ret.json()["result"]
              #pprint(item_ret)
              item_in=item_ret[0]["itemid"]
              item_out=item_ret[1]["itemid"]
              """"这里如上£¬根据实?#26159;?#20917;设定
              if"nginx"inhostname:
              json_all["nginx_cluster"][hostname]=[hostid,item_in,item_out]
              elif"tomcat"inhostname:
              json_all["tomcat_cluster"][hostname]=[hostid,item_in,item_out]
              elif"mysql"inhostname:
              json_all["mysql_cluster"][hostname]=[hostid,item_in,item_out]
              else:
              pass"""
              #pprint(json_all)
              fp=open("clusters.json","w")
              fp.write(json.dumps(json_all))
              fp.close()
              ###然后通过itemid获取最新的监控值
              defgethist(auth_id,itemid,limit,outtype=3):
              whilenotpath.isfile("clusters.json"):
              savefile()
              history_ret=requests.post(zabbix_url,data=history_data(auth_id,itemid,limit,outtype),\
              headers=headers)
              #printhistory_ret.json()
              iflen(history_ret.json()["result"])==0:
              return0
              else:
              history_ret=history_ret.json()["result"][0]
              #pprint(history_ret["value"])
              returnhistory_ret["value"]
              ###然后通过集?#22909;?#33719;取整个集群的总?#22270;?#25511;值
              defgethist_cluster(auth_id,cluster_name,opt):
              clsname=cluster_name
              opt=opt
              auth_id=getauth(zabbix_url,auth_data,headers)
              whilenotpath.isfile("clusters.json"):
              savefile()
              cluster_file=json.load(open("clusters.json","r"))
              net_list={"in":1,"out":2}
              ifclsnameincluster_file.keys()andoptinnet_list.keys():
              sum=0
              cls=cluster_file[clsname]
              inf=net_list[opt]
              forhostincls:
              itemid=cls[host][inf]
              his_ret=int(gethist(auth_id,itemid,1,3))
              sum=sum+his_ret
              #printfloat(sum)/float(1024)
              returnfloat(sum)/float(1024)
              auth_id=getauth(zabbix_url,auth_data,headers)
              #gethist(auth_id,25919,1,3)
              printgethist_cluster(auth_id,"mysql_cluster","in")

               

              然后将上面的代码保存为getsource.py文件用作模块导入£¬之所以不将所有py代码不写在一起也是为了更好看£¬更容易反复使用¡£

              注£º如果主机多的话会很慢吧~~~因为我没有写并发

              然后是flask部分的web代码

              #coding:utf-8
              fromflaskimportFlask,jsonify,render_template
              ###flask的插件£¬用的restful作为提供api
              fromflask.extimportrestful
              ###从上面?#21738;?#20010;py文件导入我们需要的函数
              fromgetsourceimportgethist,getauth,gethist_cluster,savefile
              importjson
              fromosimportpath
              app=Flask(__name__)
              api=restful.Api(app)
              ###zabixurl
              zabbix_pre="https://10.10.102.88/zabbix/"
              zabbix_url=zabbix_pre+"/api_jsonrpc.php"
              ###usernameandpasswd
              user=""
              passwd=""
              ###authdata
              auth_data=json.dumps(
              {
              "jsonrpc":"2.0",
              "method":"user.login",
              "params":{
              "user":"%s"%user,
              "password":"%s"%passwd
              },
              "id":0
              })
              ###headers
              headers={
              'content-type':'application/json',
              }
              ###根据实?#26159;?#20917;设定£¬这里给每个集群加了个id£¬用于排序£¬实际集群参考上面代码£¬这里也以nginx_cluser,tomcat_cluster,mysql_cluster为例
              cluster_id={
              "nginx_cluster":1,
              "tomcat_cluster":2,
              "mysql_cluster":7
              }
              classMyApi(restful.Resource):
              defget(self,name,opt):
              cls=name
              opt=opt
              auth_id=getauth(zabbix_url,auth_data,headers)
              whilenotpath.isfile("clusters.json"):
              savefile()
              cluster_file=json.load(open("clusters.json","r"))
              net_list={"in":1,"out":2}
              ifclsincluster_file.keys()andoptinnet_list.keys():
              sum=0
              cls=cluster_file[cls]
              inf=net_list[opt]
              forhostincls:
              itemid=cls[host][inf]
              his_ret=int(gethist(auth_id,itemid,1,3))
              sum=sum+his_ret
              returnfloat(sum)/float(1024)
              elifcls=="cluster_all"andopt=="traffic":
              keys=cluster_file.keys()
              cls_ret={}
              cls_lis=[]
              forkeyinkeys:
              dic={}
              dic["name"]=key
              dic["id"]=cluster_id[key]
              dic["in"]=gethist_cluster(auth_id,key,"in")
              dic["out"]=gethist_cluster(auth_id,key,"out")
              cls_lis.append(dic)
              cls_ret["ret"]=cls_lis
              returnjsonify(cls_ret)
              elifcls=="cluster_all"andopt=="list":
              returnjsonify(cluster_file)
              elifclsincluster_id.keys()andopt=="list":
              ret=cluster_file[cls]
              returnjsonify(ret)
              else:
              return"None"
              api.add_resource(MyApi,"/api//")
              @app.route("/")
              defhello():
              return"Helloworld你好"
              @app.route("/weathermap")
              @app.route("/weathermap/")
              defweathermap(name=None):
              name=name
              ifname=="all":
              returnrender_template("weathermap_all.html")
              elifname=="list":
              returnrender_template("weathermap_list.html")
              elifname=="plot":
              returnrender_template("weathermap_plot.html")
              else:
              returnrender_template("weathermap_all.html")
              app.debug=True
              app.run(host="0.0.0.0")

              再是html模板文件

              layout.html

              
              
              
              <scriptsrc="/static/js/angular.min.js"></script><scriptsrc="/static/js/d3.v3.min.js"></script>Beta

              运维流量表

              {%blockbody%}{%endblock%}

              weathermap_all.hml

              {%extends"layout.html"%}
              {%blockbody%}
              

              集群流量一览表

              ID 集?#22909;?出口流量(KB/s) 入口流量(KB/s) <scriptsrc="/static/js/jquery-1.11.3.min.js"></script><scriptsrc="/static/js/bootstrap.min.js"></script><scriptsrc="/static/js/netdata.js"></script><scriptsrc="/static/js/cls_svg.js"></script>{%endblock%}

              weathermap_list.html

              {%extends"layout.html"%}
              {%blockbody%}
              

              集群流量一览表

              ID 集?#22909;?出口流量(KB/s) 入口流量(KB/s) <scriptsrc="/static/js/jquery-1.11.3.min.js"></script><scriptsrc="/static/js/bootstrap.min.js"></script><scriptsrc="/static/js/netdata.js"></script>{%endblock%}

              weathermap_plot.html

              {%blockbody%}
              

              集群拓扑图

              <scriptsrc="/static/js/jquery-1.11.3.min.js"></script><scriptsrc="/static/js/bootstrap.min.js"></script><scriptsrc="/static/js/cls_svg.js"></script>{%endblock%}

              最后js文件

              netdata.js

              varapp=angular.module('myApp',[]);
              app.controller('myCtrl',function($scope,$http){
              $http.get("/api/cluster_all/traffic")
              .success(function(response){$scope.names=response.ret;});
              });

              cls_svg.js

              ###假如是nginx_cluster,tomcat_cluster,mysql_cluster
              varnodes=[{name:"nginx_cluster"},{name:"tomcat_cluster"},
              {name:"mysql_cluster"},{name:"Internet"}];
              varedges=[{source:0,target:1},{source:0,target:2},
              {source:1,target:3},{source:3,target:0}];
              ###上面是0到1,0到2,1到3,3到0的连线£¬数字分别对应上面的nodes里的name顺序
              varwidth=500;
              varheight=500;
              varsvg=d3.select("body")
              .append("svg")
              .attr("width",width)
              .attr("height",height);
              varforce=d3.layout.force()
              .nodes(nodes)//指定节点数组
              .links(edges)//指定连线数组
              .size([width,height])//指定范围
              .linkDistance(200)//指定连线长度
              .charge([-400]);//相互之间的作用力
              force.start();//开始作用
              console.log(nodes);
              console.log(edges);
              //添加连线
              varsvg_edges=svg.selectAll("line")
              .data(edges)
              .enter()
              .append("line")
              .style("stroke","#ccc")
              .style("stroke-width",1);
              varcolor=d3.scale.category20();
              //添加节点
              varsvg_nodes=svg.selectAll("circle")
              .data(nodes)
              .enter()
              .append("circle")
              .attr("r",20)
              .style("fill",function(d,i){
              returncolor(i);
              })
              .call(force.drag);//使得节点能够拖动
              //添?#29992;?#36848;节点的文字
              varsvg_texts=svg.selectAll("text")
              .data(nodes)
              .enter()
              .append("text")
              .style("fill","black")
              .attr("dx",20)
              .attr("dy",8)
              .text(function(d){
              returnd.name;
              });
              force.on("tick",function(){//对于每一个时间间隔
              //更新连线坐标
              svg_edges.attr("x1",function(d){returnd.source.x;})
              .attr("y1",function(d){returnd.source.y;})
              .attr("x2",function(d){returnd.target.x;})
              .attr("y2",function(d){returnd.target.y;});
              //更新节点坐标
              svg_nodes.attr("cx",function(d){returnd.x;})
              .attr("cy",function(d){returnd.y;});
              //更新文字坐标
              svg_texts.attr("x",function(d){returnd.x;})
              .attr("y",function(d){returnd.y;});
              });

              注?#20309;一?#21578;诉你我直接去copy来的么£¬d3js还在钻研ing£¬所以仅作demo用

              然后是目录结构

              ©À©¤©¤clusters.json

              ©À©¤©¤getsource.py

              ©À©¤©¤myapp.py

              ©À©¤©¤static

              ©¦©À©¤©¤css

              ©¦©¦©¸©¤©¤bootstrap.min.css

              ©¦©¸©¤©¤js

              ©¦©À©¤©¤angular.min.js

              ©¦©À©¤©¤bootstrap.min.js

              ©¦©À©¤©¤cls_svg.js

              ©¦©À©¤©¤d3.v3.min.js

              ©¦©À©¤©¤jquery-1.11.3.min.js

              ©¦©¸©¤©¤netdata.js

              ©¸©¤©¤templates

              ©À©¤©¤layout.html

              ©À©¤©¤weathermap_all.html

              ©À©¤©¤weathermap_list.html

              ©¸©¤©¤weathermap_plot.html

               

              如果都完成了£¬整个项目是下面这样的

              注:bootstrap,jquery,angularjs这些css£¬js文件百度Google下载吧

               

              API£º

              查询jjjr2集群列表 https://IP:5000/api/cluster_all/list

              查询jjjr2集群流量进出口情况 https://IP:5000/api/cluster_all/traffic

              查询单个集群列表(如tomcat集群) https://IP:5000/api/tomcat_cluster/list

              查询单个集群流量进出口情况 https://IP:5000/api/tomcat_cluster/in 其中in,out分别代表入口£¬出口流量

              查询单个主机流量进出口情况(暂不能提供)

              比如

              wKiom1bcI8DSG4q6AAEjzxhYrnw474.png

              访问:http//IP:5000/weathermap/list,仅访问列表

              访问:http//IP:5000/weathermap/plot,仅访问拓扑图

              访问:http//IP:5000/weathermap或者http//IP:5000/weathermap/all 查看列表与拓扑图在同一个页面

              比如

               

              wKiom1bcI9DDAe3xAAGQTMl9HE4742.png

              wKioL1bcJFDTPJ97AADJxt01lS8053.png

              存在问题£º

              1£ºmysql集群中包括了poms-mysql(后面更新)

              2?#21644;?#25169;图并不理想

              3£º页面不能实时刷新£¬通过在html页面加入

              可页面自动刷新£¬可是不优雅£¬所以并未添加

              4£º并未设置阈值已区别各个集群健?#30331;?#20917;

              5£º并没有考虑中间件之类£¬总而言之£¬现在很粗糙~~

              总结£º我们将获取zabbix数据的代码部分抽离出来做成一个模块£¬这样就能分工明确£¬也为了?#20040;?#30721;显得不是那么庞大很难看£¬然后web方面主要提供功能£¬API以及数据?#25925;ÇG?#36890;过API我们可以将数据反复利用£¬并且有很好的兼容性£¬web的?#25925;?#24403;然不能少了bootstrap£¬一个多漂亮的样式库£¬不用自己设置css£¬然后数据操作通过AngularJS£¬前台通过AngularJS去调用自身提供的API以获取数据£¬然后填充£¬最后拓扑图用?#30475;?#30340;D3JS£¬这是做前端的同事推荐的~~

              后记£º我一直想写个项目£¬不是很大的项目£¬因为这样很快的就能写完£¬太大的项目要写太久太久~基于的工作阅历还?#36824;?#24863;受到的痛点并不多£¬所以想到的点子并不多,并且也找到了很好的工具了£¬如果谁来俩点子£¬我帮你写出来呗~当然了£¬希望盈利的就算了£¬我想写的项目都是能直接放到github上~~大家一起爽?#21738;?#31181;£¬哈哈¡£

              在一定意义上也是为了练手¡£

              话说£¬我的从无到有写一个运维APP系列如果这个月前£¬写不完£¬也就也写不完了~~~因为拖太长了£¬热情要没了~

              点击复制链接 与好友分享!回本站首页
              相关TAG标签 气象 流量
              上一篇£ºPython基础--快速改造的基础知识介绍
              下一篇£ºPython与硬件学习?#22987; ¿ºÀ堆?二)
              相关文章
              图文推荐
              点击排行

              关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

              版权所有: 红黑联盟--致力于做实用的IT技术学习网站

              ¼«ËÙ·ÉͧºÃ¼Ù
              <dl id="opymh"></dl>

              <div id="opymh"></div>
                  <div id="opymh"><tr id="opymh"></tr></div>

                    <em id="opymh"><ins id="opymh"><mark id="opymh"></mark></ins></em><sup id="opymh"><menu id="opymh"></menu></sup>

                    <em id="opymh"></em>

                    <em id="opymh"><ol id="opymh"></ol></em>

                          <dl id="opymh"></dl>

                          <div id="opymh"></div>
                              <div id="opymh"><tr id="opymh"></tr></div>

                                <em id="opymh"><ins id="opymh"><mark id="opymh"></mark></ins></em><sup id="opymh"><menu id="opymh"></menu></sup>

                                <em id="opymh"></em>

                                <em id="opymh"><ol id="opymh"></ol></em>