效果图示:
场景一:
后端研发经常也需要做一些运维的活,通常的解决方案是在各个服务组件上报一些指标数据到promethues,telegraf,大数据实时计算平台等等,之后通过告警消息和grafana折线图展示等方式来通知故障和展示异常。然而出问题的时候,告警群总是会有一大堆的告警消息,各种服务组件级别的折现图也会有异常,但是很难在整体上看出来异常发生的地点区域或节点区域,简而言之就是各种指标数据和折线图只是展示了各个点的异常信息,过于细碎,还缺少一个全局总览的展示图来辅助查找问题。
场景二:
对于调度策略比较灵活的系统中,需要实时的关注当前服务组件间的调用关系,流量大小,丢包延时等等,可以通过一个全局的节点关系图来展示这样的关系。
具体有什么好处呢?
1. 直观:纵览全局,所见即所得的查看服务组件在全局的定位,与其他组件间关系,以及自身的各项指标,同时异常可以显眼的展示出来,以可视化的方式来展示服务质量的好坏及服务节点的物理联系。
2. 强大:依托与图形数据库,可以利用图形数据结构的各种算法和能力,辅助分析问题,如查找最优路径等。理论上可以用于各种图形数据结构的展示。
3. 精简:依托各个开源组件,如echarts,grafana,neo4j等等,轻松实现。
具体要怎么做呢?
0. 获取github仓库代码(https://github.com/YuanXiaoYaoZiZai/GraphMetric.git)
git clone https://github.com/YuanXiaoYaoZiZai/GraphMetric.git
cd GraphMetric/
1. 搭建并运行Neo4j图形数据库
下载对应的安装包(https://pan.baidu.com/s/1IYd8kyWBYXbJaeB64Z9SIg?pwd=ewm7 如果失效可以自行去官网Neo4j Graph Database & Analytics | Graph Database Management System下载) ,至GraphMetric目录。
执行如下命令,检查进程是否正常启动,可以自行修改neo4j.conf来设置jvm启动参数,默认用了1gb~4gb内存。
tar -xzvf neo4j-community-3.5.28-unix.tar
cd neo4j-community-3.5.28
cp ../run/neo4j.conf ./conf/
./bin/neo4j start
ps -ef |grep neo4j
通过http://ip:7474/访问:
初始账号:neo4j
初始密码:neo4j
修改账号为(可以修改账号,但是需要同步修改 cfg/metric.properties中的账号):neo4j
修改密码为(可以修改密码,但是需要同步修改 cfg/metric.properties中的密码,注意不要复制到空格):B7Nw8zIiAFlI2Gv
初次登录输入初始密码,之后重置为修改后密码,和上面贴的一样。
设置好后可以看到如下界面:
2. 下载neo4j数据初始化脚本(链接: https://pan.baidu.com/s/1szgI-gjYDNWmHYjFrzMD5g?pwd=9nwt 提取码: 9nwt )
执行如下命令导入数据(先关闭neo4j,执行导入,再执行启动):
./bin/neo4j stop
./bin/neo4j-admin load --from=init.db --force=true
./bin/neo4j start
界面输入查询语句 match (n) return n 来查看当前数据是否完成初始化,输入match (n) detach delete n 来清理所有数据,看到如下画面说明导入成功!
3. 搭建并运行GraphMetric服务(SpringBoot项目,Github开源,作用是屏蔽neo4j的sql语句操作,简练成节点关系的CRUD http接口,如果有人愿意继续优化,可以提交mr),该项目已经做好了性能优化,并提供部分配置项,提供初始化测试数据。
特性:
# SpringBoot项目,集成Neoj4
# 封装Neo4j SQL操作,申明式调用Neo4j的节点和关系的CRUD操作,并暴露出HTTP接口。
# 使用本地缓存提高性能
# 修改接口都为异步操作,操作封装为任务,写入任务队列,并发执行,HTTP接口迅速返回。common-utils 通用工具类
common-config 通用配置读取类,读取本地配置
common-cache 通用本地缓存
graph-metric-common 通用MODEL
graph-metric-client 通用SDK,可以打成jar包给服务节点进行数据上报
graph-metric-server 服务端,接受客户端上报数据
对外接口:
@POST("api/graph/cql/execute/v1")
Call<StreamResponse<Boolean>> executeCQL(@Body GraphReq req);
@POST("api/graph/node/save/v1")
Call<StreamResponse<Boolean>> saveNode(@Body GraphReq req);
@POST("api/graph/node/update/v1")
Call<StreamResponse<Boolean>> updateNode(@Body GraphReq req);
@POST("api/graph/node/get/v1")
Call<StreamResponse<GraphAll>> getNode(@Body GraphReq req);
@POST("api/graph/node/delete/v1")
Call<StreamResponse<Boolean>> deleteNode(@Body GraphReq req);
@POST("api/graph/relationship/save/v1")
Call<StreamResponse<Boolean>> saveRelationship(@Body GraphReq req);
@POST("api/graph/relationship/update/v1")
Call<StreamResponse<Boolean>> updateRelationship(@Body GraphReq req);
@POST("api/graph/relationship/get/v1")
Call<StreamResponse<GraphAll>> getRelationship(@Body GraphReq req);
@POST("api/graph/relationship/delete/v1")
Call<StreamResponse<Boolean>> deleteRelationship(@Body GraphReq req);
执行如下操作
先创建logs日志目录。
直接在GraphMetric/run 目录下执行 ./control.sh start就好了。
可以修改cfg/metric.properties配置文件来配置系统(默认2089端口)
可以修改control.config配置文件来修改jvm启动参数(默认1gb~4gb)
可以自行编译graph-metric-server springboot项目来编辑jar,替换graph-metric-common-0.0.1-SNAPSHOT.jar
启动成功后观察日志(tail -300f logs/rapid-cloud-metric-info.log)是否正常!
mkdir logs
chmod 777 control.sh
./control.sh start
tail -300 logs/rapid-cloud-metric-info.log
使用如下命令测试接口是否正常获取数据:
curl 'http://127.0.0.1:2089/api/graph/cql/v1' \
-H "Content-Type:application/json" \
-X POST \
-d '{"nodeCQL":"MATCH (m) RETURN m","relationshipCQL":"MATCH p=()-[r]->() RETURN p"}'
正常返回数据说明程序运行ok!
4. 搭建并运行Grafana监控服务。
自行网上教程安装,我用的版本是:V9.0.7
5. Grafana下载并启用访问HTTP接口的插件,下载并启用Echarts插件,设置对应的Grafana面板属性。
安装http插件:
安装echarts插件:
创建grafana数据源,使用JSON API,URL输入 http://host:2089,即刚才部署的服务ip和端口,点击保存:
新建dashboard 和panel,选择刚才创建的数据源
选择使用apach echarts图表
在echarts代码区域贴入GraphMetric/run/js/GrafanaGraph.js这个js文件中的全部内容,这个js必须要配置,手搓的一套算法布局,否则echarts的引力图根本就没法看!
设置dashboard面板的变量参数,resourceId为输入框,其他两个为custom定制参数:
设置resourceId
设置layout,值为:horizontal,vertical,用于设置图的水平或垂直走向
设置lessLines,值为:true,false,用于控制连线的密集或稀疏
设置HTTP 访问参数,params参数很多用于调节UI展示,具体作用看变量名:
Fields: $.data
Path: /api/graph/cql/v1
Headers: Content-Type application/json
Body选择text,并贴入下面json:
{
"nodeCQL":"MATCH p=(m:NODE {props_rid:'${resourceId}',props_label:'NAV_NODE'})-[r:RELATIONSHIP *..3]-(n:NODE) WHERE m.props_label <> 'USER_NODE' AND n.props_label <> 'USER_NODE' return m,n ORDER BY m.props_label,m.props_sid,n.props_label,n.props_sid desc",
"relationshipCQL":"MATCH p=(m:NODE {props_rid:'${resourceId}',props_label:'NAV_NODE'})-[rs:RELATIONSHIP *..3]-(n:NODE) RETURN filter(r IN rs WHERE r.props_label <> 'NAV_SUB' AND r.props_label <> 'STREAM_TRANSFER' AND r.props_label <> 'SM_SUB' AND (NOT EXISTS(r.props_cStatus) OR r.props_cStatus = '1')) as t order by m.props_label,m.props_sid,n.props_label,n.props_sid desc"
}Params参数如下,注意每行代表一个完整的k/v:
categoryProps:label
categoryGroups:RELAY_NODE,AWS_NODE
categoryGroups:PB_NODE,TRACKER_NODE,CDN_NODE
categoryGroups:HUB_NODE
categoryGroups:EDGE_NODE,RPS_NODE,VNO_NODE
categoryGroups:HD_RPS_NODE,SM_NODE,NAV_NODE
extraParams[layout]:${layout}
extraParams[lessLines]:${lessLines}
extraParams[linkEffect]:true
extraParams[nodeLabel]:sid
extraParams[nodeProps]:label,rid,sid,name,version,address,type,proxyAddress
extraParams[nodeField]:gcTh,rtt,delay,lossRate,hlsFailed,streamCount,onlineUsers,onlineMedias
extraParams[linkLabel]:protocol
extraParams[linkProps]:label,protocol
extraParams[linkField]:rtt,delay,lossRate,hlsFailed,streamCount
extraParams[keyFormatter]:{"label":"标签","protocol":"传输协议","serverRID":"已连接服务器ID","serverVID":"已连接服务器LOGIC ID","connectRID":"已连接服务器CID","gcTh":"GC 吞吐率(%)","onlineUsers":"在线用户数(个)","onlineMedias":"在播流数(条)","cStatus":"连接状态(0:OFF,1:ON)","format":"流格式","rtt":"延迟(ms)","delay":"收包延迟(ms)","lossRate":"丢包率(%)","hlsFailed":"HTTP错误率(%)","streamCount":"流数(条)","loginPrtTime":"登录PRT时间","loginTrackerTime":"登录TRACKER时间","reqNeighborTime":"请求分配邻居时间","respPlayServerTime":"请求分配服务器时间","respNeighbors":"返回邻居个数","neighbors":"分配的邻居","endpoint":"对外接口","lastSubTs":"上次订阅时间","lastRecvTs":"上次收包时间","drm":"DRM流(0:NO,1:YES)","mp4":"MP4流(0:NO,1:YES)","abr":"ABR流(0:NO,1:YES)","sendSpeed":"发包速度","indexSent":"INDEX发送","indexRecv":"INDEX接收","blockSent":"BLOCK发送","blockResend":"BLOCK重发","index":"INDEX本地缓存","block":"BLOCK本地缓存","indexContent":"INDEX缓存内容","rid":"资源组ID","cid":"服务器CID","sid":"服务器ID(或MAC)","type":"地址类型(2:地址,3:代理地址)","name":"服务器名称","version":"服务器版本号","address":"服务器地址","proxyAddress":"服务器代理地址(Relay)","streamId":"流ID","playStreamId":"在播流ID","appVer":"APP版本号"}
nodeExpressions[rippleEffectRed]:(is_def(deleted) && string.contains(deleted, "1")) || (is_def(delay) && long(delay)>500) || (is_def(lossRate) && long(lossRate)>30)
nodeExpressions[rippleEffectOrange]:(is_def(status) && string.contains(status, "1"))
linkExpressions[linkEffectGreen]:
linkExpressions[linkEffectOrange]:is_def(cStatus) && long(cStatus) == 0
linkExpressions[linkEffectRed]:(is_def(deleted) && long(deleted) == 1) || (is_def(delay) && long(delay)>500) || (is_def(lossRate) && long(lossRate)>30)
linkExpressions[linkEffectHidden]:!is_def(streamCount) || (is_def(streamCount) && long(streamCount) == 0)
linkExpressions[linkSolid]:
在resourceId变量栏输入rapid-cdn-dev,layout选择horizontal,less lines选择false。
全部设置好后保存dashboard(一定要先保存,否则白设置了)。
返回到主界面,刷新页面,可以看到图表是可以正常的展示的,到此就完全结束了!可以自行调节Params参数里面的配置来调整图表的UI页面元素,具体作用看备注!
最终图示如下(水平布局):
最终图示如下(垂直布局):
6. 自行上报数据,并设置Grafana图表。
通过graph-metric-client 通用SDK(也可以自行对接HTTP接口) 来上报节点数据,上报节点间关系数据,如下为示例:
//上报节点
metricGraphKit.saveGraphNode(GraphNodeLabel.EDGE_NODE.name(),
ImmutableMap.of("rid", config.getResourceId(), "sid", config.getServerId()),
ImmutableMap.of("address", config.getServerAddress(), "name", config.getServerName(), "version", heartbeat.getVersion()),
ImmutableMap.of("gcTh", gcThroughout, "streamCount", streamCount, "lossRate", lossRate, "delay", delay, "rtt", rtt)
);
//上报节点
metricGraphKit.saveGraphNode(GraphNodeLabel.HD_RPS_NODE.name(),
ImmutableMap.of("rid", config.getResourceId(), "sid", address.getApplication()),
ImmutableMap.of("address", address.getServerAddress()),
ImmutableMap.of()
);
//上报节点关系
metricGraphKit.saveGraphRelationship(GraphRelationshipLabel.HD_RPS_WITH_EDGE.name(),
ImmutableMap.of("protocol", config.getProtocolUsed()),
GraphNodeLabel.HD_RPS_NODE.name(), ImmutableMap.of("rid", config.getResourceId(), "address", rpsServer.getServerAddress()),
GraphNodeLabel.EDGE_NODE.name(), ImmutableMap.of("rid", config.getResourceId(), "sid", config.getServerId()),
ImmutableMap.of("cStatus", 1),
ImmutableMap.of("streamCount", streamCount)
);
自行决定上报的节点类型,关系类型,节点的属性,关系的属性,同时需要更新Grafana上的查询参数对应,不然无法正确展示。
需要了解一些Neo4j SQL的基本用法
需要一些Grafana图表配置的基本用法
需要SpringBoot项目编译和运行的基本能力文章来源:https://www.toymoban.com/news/detail-860342.html
如果还有任何问题可以加v(YuanXiaoYaoZiZai)文章来源地址https://www.toymoban.com/news/detail-860342.html
到了这里,关于Grafana+Echarts+Neo4j+SpringBoot 联合搭建节点实时拓扑图的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!