【Go】go-es统计接口被刷数和ip访问来源

go-es模块统计日志中接口被刷数和ip访问来源

  • 以下是使用go的web框架gin作为后端,展示的统计页面
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

背景

  • 上面的数据来自elk日志统计。因为elk通过kibana进行展示,但是kibana有一定学习成本且不太能满足定制化的需求,所以考虑用编程的方式对数据进行处理
  • 首先是接口统计,kibana的页面只会在 字段uri 的 top500 进行百分比统计,展示前5条数据,统计不够充分
    在这里插入图片描述
  • 其次是网关日志,ip来源的采集字段是通过x_forward_for,这记录了各级的代理来源ip。并不能直接对用户的ip进行数据聚合的统计
    • 举例,这里面 “223.104.195.51,192.168.29.135” ,这种数据我需要拿到223.104.195.51,因为这才是用户的ip。所以需要进行编程的处理
      在这里插入图片描述

环境

  • elk 7.9
https://www.elastic.co/downloads/past-releases/elasticsearch-7-9-3
  • go 1.17 ,gin 1.6.3,go-elasticsearch 7.9.0
# go1.17下载地址
https://go.dev/dl/
# 模块下载
go env -w GOPROXY=https://goproxy.cn,direct
go mod init go-ops  # 本项目的go mod 名字
go get github.com/elastic/go-elasticsearch/v7@v7.9.0
go get github.com/gin-gonic/gin@v1.6.3
  • 前端:layui 和 echarts
# layui下载
http://layui.dotnetcms.cn/res/static/download/layui/layui-v2.6.8.zip?v=1
# layui框架代码
http://layui.dotnetcms.cn/web/demo/admin.html
# layui数据表格
http://layui.dotnetcms.cn/web/demo/table.html
# echarts下载(需魔法)
https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js
# echarts直方图
https://echarts.apache.org/handbook/zh/get-started/
# echarts 饼图
https://echarts.apache.org/handbook/zh/how-to/chart-types/pie/basic-pie/
  • 后端
# gin静态文件服务(导入js、css、图片用的)
https://learnku.com/docs/gin-gonic/1.7/examples-serving-static-files/11402
# gin模板引擎(前后端不分离,后端数据渲染前端)
https://learnku.com/docs/gin-gonic/1.7/examples-html-rendering/11363
# gin绑定Uri(动态获取二级路由)
https://learnku.com/docs/gin-gonic/1.7/examples-bind-uri/11391

go-elasticsearch 模块

  • 顾名思义此模块作用是充当es的客户端往es索引中读取数据,其原理和kibana上的dev tools一样,都是对es的restful api调用
# 以下是go-elasticsearch 的增删查改文档
https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/getting-started-go.html

eql

  • 实现统计数据分析的核心就是eql(es查询语言),通过go-elasticsearch模块进行eql的发送,再接收es返回的回复体
    在这里插入图片描述
  • 以下是使用go-es发送eql后,es的回复体的struct源码
    在这里插入图片描述
  • 可以看到type Response struct 中,我们想要的json数据在Body中,但是注意Body的类型为 io.ReadCloser , 因此是需要用go的io模块进行获取json数据
    • 这边解决读取问题的代码如下。该函数接收es响应体,并返回未序列化的byte切片
// 处理es的响应,获取响应体里的Body
func getResponseBody(result *esapi.Response, context *gin.Context) []byte {// 接收es回复体里返回的数据,这里返回io流,需要用对应方法接收var bodyBytes []bytebodyBytes, err := io.ReadAll(result.Body)if err != nil {panic(err)}return bodyBytes
}

es客户端建立连接

  • 文档地址
https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/connecting.html
  • 这边给的是https连接 + 用户名密码认证 + 不受信任证书的解决方法
package esinitimport ("github.com/elastic/go-elasticsearch/v7""io/ioutil""log"
)var EsClient *elasticsearch.Clientfunc init() {EsClient = newEsClient()
}func newEsClient() *elasticsearch.Client {cert, certErr := ioutil.ReadFile("esinit/es.crt")  // 你的不受信任的https证书if certErr != nil {log.Println(certErr)}EsClient, error := elasticsearch.NewClient(elasticsearch.Config{Username: "你的用户名",Password: "你的密码",Addresses: []string{"https://es-cluster1:9200","https://es-cluster2:9200","https://es-cluster3:9200",},CACert: cert,})if error != nil {panic(error)}return EsClient
}

实现统计的三段eql

  • 这里eql使用 fmt.Sprintf() 方法进行参数传递
  • 第一段eql是统计PV
    • 这里注意的是,我们在东八区,所以统计pv从16:00开始。这里根据@timestamp字段进行“aggs”聚合统计
func getPvResponse(startYear int, startMonth int, startDay int, endYear, endMonth int, endDay int) *esapi.Response {query := fmt.Sprintf(`
{"query": {"bool": {"must": [{"range": {"@timestamp": {"gte": "%d-%02d-%02dT16:00:00","lte": "%d-%02d-%02dT16:00:00"}}}]}},"aggs": {"log_count": {"value_count": {"field": "@timestamp"}}}
}
`, startYear, startMonth, startDay, endYear, endMonth, endDay)result, _ := esinit.EsClient.Search(esinit.EsClient.Search.WithIndex("k8s-istio-ingress*"), // 索引名esinit.EsClient.Search.WithBody(strings.NewReader(query)), // eql)return result
}
  • 第二段是对微服务(java)的接口(uri字段)的聚合统计
    • 这里用的 sortUri 是gin的绑定uri功能(动态获取二级路由的名字)
    • 这里返回前1天10000条es文档的uri字段数据
func getSortResponse(context *gin.Context) *esapi.Response {if err := context.ShouldBindUri(&sortUri); err != nil { // sortUri二级路由,传递索引名context.JSON(400, gin.H{"msg": err})}//搜索文档// eql 搜索时间范围内10000条记录,并只展示uri字段的内容query := fmt.Sprintf(`{"_source": ["uri"],"query": {"bool": {"filter": [{"range": {"@timestamp": {"gte": "now-1d/d","lte": "now/d"}}}]}},"size": 10000}`)// 对应索引进行搜索result, _ := esinit.EsClient.Search(esinit.EsClient.Search.WithIndex(sortUri.Name+"*"),esinit.EsClient.Search.WithBody(strings.NewReader(query)),)return result
}
  • 第三段是对istio前一小时的ip请求统计,返回2000条记录
func getIstioDataResponse() *esapi.Response {query := `
{"_source": ["x_forwarded_for","@timestamp","path","user_agent_a","response_code","method","upstream_cluster"],"query": {"bool": {"filter": [{"range": {"@timestamp": {"gte": "now-1h/h","lte": "now/d"}}}]}},"size": 2000
}
`result, _ := esinit.EsClient.Search(esinit.EsClient.Search.WithIndex("k8s-istio-ingress*"),esinit.EsClient.Search.WithBody(strings.NewReader(query)),)return result
}
  • 上面的eql函数,会return 一个 []byte切片,可以进行 json.Unmarshal 或其他struct转json的模块进行处理,就能够得到数据。然后便可进行渲染

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/148187.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

lv7 嵌入式开发-网络编程开发 07 TCP服务器实现

目录 1 函数介绍 1.1 socket函数 与 通信域 1.2 bind函数 与 通信结构体 1.3 listen函数 与 accept函数 2 TCP服务端代码实现 3 TCP客户端代码实现 4 代码优化 5 练习 1 函数介绍 其中read、write、close在IO中已经介绍过,只需了解socket、bind、listen、acc…

国庆假期day5

作业:请写出七层模型及每一层的功能,请绘制三次握手四次挥手的流程图 1.OSI七层模型: 应用层--------提供函 表示层--------表密缩 会话层--------会话 传输层--------进程的接收和发送 网络层--------寻主机 数据链路层----相邻节点的可靠传…

【题解 动态规划】 Colored Rectangles

题目描述: 分析: 乍一看我还以为是贪心! 猫 想想感觉没问题 但是局部最优并不能保证全局最优 比如这组数据 19 19 19 19 20 20 20 20如果按照贪心的做法,答案是20*20*2 但是其实答案是19*20*4 因此这道题用贪心是不对的 于是我…

Redis分页+多条件模糊查询组合实现思路

Redis是一个高效的内存数据库,它支持包括String、List、Set、SortedSet和Hash等数据类型的存储,在Redis中通常根据数据的key查询其value值,Redis没有模糊条件查询,在面对一些需要分页、排序以及条件查询的场景时(如评论&#xff0…

基于SSM的健身房管理系统

基于SSM的健身房管理系统的设计与实现 开发语言:Java数据库:MySQL技术:SpringSpringMVCMyBatis工具:IDEA/Ecilpse、Navicat、Maven 【主要功能】 角色:管理员、用户 查看健身课程列表、新闻公告查看、推荐课程、购买…

《机器学习实战》学习记录-ch2

PS: 个人笔记&#xff0c;建议不看 原书资料&#xff1a;https://github.com/ageron/handson-ml2 2.1数据获取 import pandas as pd data pd.read_csv(r"C:\Users\cyan\Desktop\AI\ML\handson-ml2\datasets\housing\housing.csv")data.head() data.info()<clas…

【Leetcode】 131. 分割回文串

给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。 示例 1&#xff1a; 输入&#xff1a;s "aab" 输出&#xff1a;[["a","a"…

Spring Cloud Zuul 基本原理

Spring Cloud Zuul 底层是基于Servlet实现的&#xff0c;核心是通过一系列的ZuulFilter来完成请求的转发。 1、核心组件注册 1.1. EnableZuulProxy注解 启用Zuul作为微服务网关&#xff0c;需要在Application应用类加上EnableZuulProxy注解&#xff0c;而该注解核心是利用Im…

Web版Photoshop来了,用到了哪些前端技术?

经过 Adobe 工程师多年来的努力&#xff0c;并与 Chrome 等浏览器供应商密切合作&#xff0c;通过 WebAssembly Emscripten、Web Components Lit、Service Workers Workbox 和新的 Web API 的支持&#xff0c;终于在近期推出了 Web 版 Photoshop&#xff08;photoshop.adobe…

Qt+openCV学习笔记(十六)Qt6.6.0rc+openCV4.8.1+emsdk3.1.37编译静态库

前言&#xff1a; 有段时间没来写文章了&#xff0c;趁编译库的空闲&#xff0c;再写一篇记录文档 WebAssembly的发展逐渐成熟&#xff0c;即便不了解相关技术&#xff0c;web前端也在不经意中使用了相关技术的库&#xff0c;本篇文档记录下如何编译WebAssembly版本的openCV&…

区块链3.0时代 基于GoMars构建的新概念TravelFi能否注入新力量?

区块链技术进入3.0时代 后疫情时代&#xff0c;全球数字化进程不断加快&#xff0c;世界范围内的移动通信、互联网技术及各类数字化应用的社会普及率也正在快速提升&#xff0c;疫情推动了互联网经济的增长&#xff0c;也让数字经济的价值开始显现。 数字经济一词的由来至今已经…

网络协议--概述

1.2 分层 网络协议通常分不同层次进行开发&#xff0c;每一层分别负责不同的通信功能。一个协议族&#xff0c;比如TCP/IP&#xff0c;是一组不同层次上的多个协议的组合。TCP/IP通常被认为是一个四层协议系统&#xff0c;如图1-1所示。 每一层负责不同的功能&#xff1a; 1.…

objective-c 基础学习

目录 第一节&#xff1a;OC 介绍 ​​第二节&#xff1a;Fundation 框架 ​第三节&#xff1a;NSLog 相对于print 的增强 ​第四节&#xff1a;NSString ​第五节&#xff1a;oc新增数据类型 第六节&#xff1a; 类和对象 ​类的方法的声明与实现 ​第七节&#xff1a;类…

Linux信号解析

文章目录 Linux信号概念信号种类Linux信号产生异步 LInux信号阻塞递达、未决、阻塞、忽略信号集操作函数阻塞信号集操作函数未决信号集操作函数 Linux信号捕捉signal函数sigaction函数 总结 Linux信号概念 信号在我们的生活中无处不在&#xff0c;常见的如电话铃声&#xff0c…

国庆10.4

QT实现TCP服务器客户端 服务器 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> //服务器头文件 #include <QTcpSocket> //客户端头文件 #include <QList> //链表容器 #include <QMe…

【C 语言进阶(12)】动态内存管理笔试题

文章目录 题目 1题目 2题目 3题目 4 题目 1 运行 Test 函数后的结果是什么&#xff1f; void GetMemory(char* p) {p (char*)malloc(100); }void Test(void) {char* str NULL;GetMemory(str);strcpy(str, "hello world");printf(str); }代码结果 程序崩溃。 代…

C++ YAML使用

C++工程如何使用YAML-cpp 一、前期准备工作 1、已安装minGW、cmake、make等本地工具。 2、下载YAML-cpp第三方开源代码(一定要下载最新的release版本,不然坑很多)。 3、生成YAML-cpp静态库 (1)在yaml-cpp-master下建立build文件夹; (2)在该文件夹下生成MakaFile文…

C++入门-day01

一、认识C C融合了三种不同的编程方式 C代表的过程性语言在C基础上添加的类、结构体puls代表的面向对象语言C模板支持泛型编程 C完全兼容C的特性 Tips&#xff1a;侯捷老师提倡的Modren C是指C11、C14、C17和C20这些新标准所引入的一系列新特性和改进。在我们练习的时候也应当去…

Blender 之创建一个简单的笔筒

文章目录 成品图实现步骤 你是不是想创建一个笔筒捏&#xff1f; follow me! 成品图 实现步骤 先添加一个柱体 选中柱体&#xff0c;然后按tab 进入编辑模式 切换到面模式 &#xff08;可以按主键盘的 3 键&#xff09; 分别选中上下面&#xff0c;鼠标右键&#xff0c;选…

BL808学习日志-2-LVGL for M0 and D0

一、lvgl测试环境 对拿到的M1S_DOCK开发板进行开发板测试&#xff0c;博流的官方SDK是支持M0和D0两个内核都进行测试的&#xff1b;但是目前只实现了M0的LVGLBenchmark&#xff0c;测试D0内核中发现很多莫名其妙的问题。一会详细记录。 使用的是开发板自带的SPI显示屏&#xff…