【毕设扫描器】【参数Fuzz】第一篇:数据的定义、读取和装配(爬虫数据和Payload数据)

本文主要是介绍【毕设扫描器】【参数Fuzz】第一篇:数据的定义、读取和装配(爬虫数据和Payload数据),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 字典文件的数据结构
    • 读取嵌套的 Json 数据
        • 读取值为基本数据类型的Json文件
        • 读取值为数组的Json数据
        • 读取值为字典的Json文件
        • 读取包含两个层级键名的Json文件
    • 准备数据阶段
        • 修改爬虫保存结果(结合报错和实际情况未修改代码,可忽略)
        • 从 Json 文件读取需要的爬虫数据
        • 读取 paramsFuzz.json 文件
    • 装配数据阶段
        • 配置请求对象 req
        • 保存传递动态参数的 Url 信息
        • 装配数据
            • 第一步
            • 第二步
            • 第三四五步
    • 执行阶段
    • 接收结果并验证阶段

字典文件的数据结构

在项目根目录创建 fuzzDicts 目录,创建 fuzzDicts/params.json,用于测试参数。(使用 json 是因为常见/易读/复用性强)

参数测试Payload格式:不同的漏洞类型、漏洞类型下不同的软件系统、对应Payload。

一级数据是漏洞类型,如 SQLI、XSS等,数据结构是字典格式。(添加字段 description 描述payload,不需要专门使用一个字段进行分类。该部分是在读取 Json 文件时进行的修改)

二级数据是漏洞类型的下一级数据,可能需要根据不同软件类型选择 Payload,所以也要使用字典格式。二级数据如果不分软件类型,则定义键名为 universal(还要单独输入一个字段,而大多数情况都不知道软件类型,还是要枚举测试所有Payload,所以该字段不是很有必要)

二级数据是Payload,根据不同Payload需要选择不同的响应判断,如时间延迟注入的响应时间、响应内容中的关键字,所以使用字典格式。(Payload直接作为污染参数数据的键名即可)(实际读取 Json 文件时做出的优化)

一级数据是一个键 data,其键值是数据类型,用于存储 payload 的字典信息。

二级数据是最底层的数据,注入参数可能有很多、响应时间是整数、关键词是字符串等,所以根据实际需要分别使用 List、Int、String等数据类型。

未考虑的场景问题

  • 根据比较不同Payload下返回的响应信息来判断漏洞是否存在。

排版如下。

{"data":[{"description": "SQLI-001: MySQL-数字型延迟注入","payload": "/**/and/**/sleep(5)","time": 5,"keyword": ""},{"description": "SQLI-002: MySQL-字符型延迟注入","payload": "'/**/and/**/sleep(5)--+","time": 5,"keyword": ""},{"description": "SQLI-003: MySQL-字符型延迟注入","payload": "\"/**/and/**/sleep(5)--+","time": 5,"keyword": ""},{"description": "SQLI-004: MySQL-报错注入","payload": "'\"+,","keyword": "You have an error in your SQL syntax"},{"description": "XSS-001: 跨站脚本攻击漏洞""payload": "<script>alert(/xss/)</script>","keyword": "xxx"}]}

读取嵌套的 Json 数据

读取值为基本数据类型的Json文件

这里的单层是指,Json数据的值是基本数据类型,不是列表、字典等数据结构。

创建 test.json 文件,文件内容如下。

{"name": "pumpkin","date": "2022-04-05"
}

查找网上文章 Go 对象序列化 等,编写读取Json文件代码。

  • 读取配置文件的字节数据:bytesJSON, err := ioutil.ReadFile(“example.json”)

  • go 内置对 json 数据的处理包是 encoding/json

  • 把字节数据解析成Json编码数据:json.Unmarshal

  • 接收Json数据:需要事先定义一个结构体

成功运行解析的代码和打印结果如下。

/* 打印结果pumpkin2022-04-05
*///定义配置文件解析后的结构
type Test struct {Name	string 	`json:"name"`Date	string `json:"date"`
}func main() {var test Testbytes, err := ioutil.ReadFile("./test.json")if err != nil {fmt.Println("读取json文件失败", err)return}err = json.Unmarshal(bytes, &test)if err != nil {fmt.Println("解析数据失败", err)return}fmt.Println(test.Name)fmt.Println(test.Date)
读取值为数组的Json数据

test.json 配置文件的内容如下。

此时使用上一小节读取基本数据类型的代码,json.Unmarshal(bytes, &test) 会报错并退出程序,无法把数组结构解析成 Go 结构体的 string 类型:
解析数据失败 json: cannot unmarshal array into Go struct field Test.name of type string

{"name": ["pumpkin", "watermelon"],"date": "2022-04-05"
}

修改结构体的参数类型为字符串数组:[]string。运行成功且打印结果如下。

/*	打印结果[pumpkin watermelon]2022-04-05
*/
//定义配置文件解析后的结构
type Test struct {Name	[]string 	`json:"name"`Date	string 		`json:"date"`
}
读取值为字典的Json文件

参考文章 golang 数据三 (字典),golang基本数据结构Map也叫字典,字典的声明格式是:map[KeyType]ValueType

此时 test.json 配置文件的内容如下。

{"name": ["pumpkin", "watermelon"],"date": "2022-04-05""sex":{"man":1,"woman":0}
}

定义接收 Json 数据的结构体如下,成功读取并打印 Json 数据内容。

//定义配置文件解析后的结构
type Test struct {Name	[]string 		`json:"name"`Date	string 			`json:"date"`Sex 	map[string]int	`json:"sex"`
}// main()函数中的操作代码
func main() {var test Testbytes, err := ioutil.ReadFile("./test.json")if err != nil {fmt.Println("读取json文件失败", err)return}err = json.Unmarshal(bytes, &test)if err != nil {fmt.Println("解析数据失败", err)return}fmt.Println(test.Name)fmt.Println(test.Date)fmt.Println("man: ", test.Sex["man"])fmt.Println("woman: ", test.Sex["woman"])
}
读取包含两个层级键名的Json文件

此时 test.json 配置文件的内容如下。

{"req_list": [{"url": "http://127.0.0.1/sqli-labs-master/Less-1/?id=1","method": "GET","headers": {"Spider-Name": "crawlergo","User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.0 Safari/537.36"},"data": "","source": "Target"}],"all_req_list": [{"url": "http://127.0.0.1/sqli-labs-master/Less-1/?id=1","method": "GET","headers": {"Spider-Name": "crawlergo","User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.0 Safari/537.36"},"data": "","source": "Target"}],"all_domain_list": ["127.0.0.1"],"sub_domain_list": ["127.0.0.1"]

尝试定义 req_list 的值为数组 array,json.Unmarshal() 函数报错:解析数据失败 json: cannot unmarshal object into Go struct field Crawler.req_list of type string。

type Crawler struct {ReqList         []string `json:"req_list"`AllReqList      []string `json:"all_req_list"`AllDomainList 	[]string `json:"all_domain_list"`SubDomainList 	[]string `json:"sub_domain_list"`
}

数组的元素值类型应该是字典 map,尝试定义如下结构体,仍然是相同的报错信息。

type Crawler struct {ReqList         []map[string]string `json:"req_list"`AllReqList      []map[string]string `json:"all_req_list"`AllDomainList 	[]map[string]string `json:"all_domain_list"`SubDomainList 	[]map[string]string `json:"sub_domain_list"`
}

由于 Json 文件包含不同层级的键名,所以定义结构体的结构也肯定不同,参考文章:Go 解析嵌套 json。

如果 Json 数据有多层键,那么每层键都需要定义一个结构体接收对应的键名,并且定义变量时需要嵌套结构体类型。

查看参考文章编写代码,成功读取嵌套 Json 文件的代码和打印结果如下。

/*	打印结果http://127.0.0.1/sqli-labs-master/Less-1/?id=1GETSpider-Name crawlergoUser-Agent Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.0 Safari/537.36
*/
// 接收第一层 Json 数据
type CrawlerFirst struct {ReqList			[]CrawlerSecond			`json:"req_list"`AllReqList      []CrawlerSecond 		`json:"all_req_list"`AllDomainList 	[]string 				`json:"all_domain_list"`SubDomainList 	[]string 				`json:"sub_domain_list"`
}type CrawlerSecond struct {Url			string						`json:"url"`Method      string 						`json:"method"`Headers 	map[string]string 			`json:"headers"`Data 		string 						`json:"data"`Source 		string						`json:"source"`
}// Test 定义配置文件解析后的结构
type Test struct {Name	[]string 		`json:"name"`Date	string 			`json:"date"`Sex 	map[string]int	`json:"sex"`
}func main() {//var req model.Requestvar crawlerFirst CrawlerFirstbytes, err := ioutil.ReadFile("./debug.json")if err != nil {fmt.Println("读取json文件失败", err)return}err = json.Unmarshal(bytes, &crawlerFirst)if err != nil {fmt.Println("解析数据失败", err)return}for _,req:= range crawlerFirst.ReqList{fmt.Println(req.Url)fmt.Println(req.Method)fmt.Println(req.Data)for key,value:= range req.Headers {fmt.Println(key, value)}}}

准备数据阶段

修改爬虫保存结果(结合报错和实际情况未修改代码,可忽略)

读取爬虫结果的前提是,爬虫结果是我们需要的数据。原项目中把如下 4 种数据保存到一个 Json 文件,我们首先需要分离这些数据,使每种数据分别保存到各自的文件。

type Result struct {ReqList       []Request `json:"req_list"`AllReqList    []Request `json:"all_req_list"`AllDomainList []string  `json:"all_domain_list"`SubDomainList []string  `json:"sub_domain_list"`
}

crawlergo_cmd.go 文件保存结果的相关代码,调试打印 result 变量值发现,此时爬虫结果按照 Result 结构体都已经填充内容。先酱紫,后续对爬虫结果结构体有想法,再另外进行修改。

考虑到报错、以及直接可以读取 Json 文件,不修改代码。

	// 代码 350 行// 输出结果outputResult(result)// 代码 403 行
func outputResult(result *pkg.Result) {// 输出结果if outputMode == "json" {fmt.Println("--[Mission Complete]--")resBytes := getJsonSerialize(result)fmt.Println(string(resBytes))} else if outputMode == "console" {for _, req := range result.ReqList {req.FormatPrint()}}// 写入文件的主要代码if len(outputJsonPath) != 0 {resBytes := getJsonSerialize(result)tools.WriteFile(outputJsonPath, resBytes)}// 修改该部分主要代码为如下内容(不更改代码,直接读取 json 文件)/*注意,1.结构体中的变量名需要开启调试查看、或从其他代码中找到2.序列化结构体的变量时,报错如下。在结构体定义代码中,前两个变量的类型是 []Request,域名变量是 []string考虑到可以直接读取Json文件,不更改代码。cannot use result.ReqList (type []*model.Request) as type *pkg.Result in argument to getJsonSerializecannot use result.AllDomainList (type []string) as type *pkg.Result in argument to getJsonSerialize*/if len(outputJsonPath) != 0 {resBytes1 := getJsonSerialize(result.req_list)resBytes2 := getJsonSerialize(result.all_req_list)resBytes3 := getJsonSerialize(result.all_domain_list)resBytes4 := getJsonSerialize(result.sub_domain_list)tools.WriteFile("req_" + outputJsonPath, resBytes1)tools.WriteFile("all_req_" + outputJsonPath, resBytes2)tools.WriteFile("all_domain_" + outputJsonPath, resBytes3)tools.WriteFile("sub_domain_" + outputJsonPath, resBytes4)}}
从 Json 文件读取需要的爬虫数据

关于嵌套 Json 文件数据的读取,在本文的上一章节《读取嵌套的 Json 数据》已完成了代码的编写和调试。

读取数据的任务完成了,Fuzz 需要用到哪些数据呢?

url
method
headers	// 为了避免被反爬虫限制访问,必须使用合适的请求头
data

读取爬虫Json文件

// 接收第一层 Json 数据
type CrawlerFirst struct {ReqList			[]CrawlerSecond			`json:"req_list"`AllReqList      []CrawlerSecond 		`json:"all_req_list"`AllDomainList 	[]string 				`json:"all_domain_list"`SubDomainList 	[]string 				`json:"sub_domain_list"`
}type CrawlerSecond struct {Url			string						`json:"url"`Method      string 						`json:"method"`Headers 	map[string]string 			`json:"headers"`Data 		string 						`json:"data"`Source 		string						`json:"source"`
}// 封装函数
func read_crawler() CrawlerFirst{var crawlerFirst CrawlerFirstbytes, err := ioutil.ReadFile("./debug.json")if err != nil {fmt.Println("读取json文件失败", err)os.Exit(1)}err = json.Unmarshal(bytes, &crawlerFirst)if err != nil {fmt.Println("解析数据失败", err)os.Exit(1)}return crawlerFirst
}
读取 paramsFuzz.json 文件

读取代码改了又改,总是报错。无奈从基本数据类型开始编写 Json 文件进行读取,然后逐渐嵌套数据并完成读取 Json 数据,最终代码和打印结果如下。

读取的 Json 文件见本文第一章 字典文件的数据结构

/* 打印 sqli 键值的结果
//	/**/and/**/sleep(5)
//	MySQL-数字型延迟注入
//	5//	'/**/and/**/sleep(5)--+
//	MySQL-字符型延迟注入
//	5//	"/**/and/**/sleep(5)--+
//	MySQL-字符型延迟注入
//	5//	'"+,
//	MySQL-报错注入
//	0
//	You have an error in your SQL syntax
*/// 定义配置文件解析后的结构
type ParamsFuzzJson struct {SqlInjection	[]ParamData		`json:"sqli"`Xss				[]ParamData		`json:"xss"`
}type ParamData struct {Payload 	string		`json:"payload"`Description string 		`json:"description"`Time 		int			`json:"time"`Keyword		string		`json:"keyword"`
}func main() {//var req model.Requestvar paramsFuzzJson ParamsFuzzJsonbytes, err := ioutil.ReadFile("./fuzzDicts/paramsFuzz.json")if err != nil {fmt.Println("读取json文件失败", err)// os.Exit(1)return}err = json.Unmarshal(bytes, &paramsFuzzJson)if err != nil {fmt.Println("解析数据失败", err)return//os.Exit(1)}// fmt.Println(paramsFuzzJson.SqlInjection)// 读取 Json 的 sqli 键for _, param:= range paramsFuzzJson.SqlInjection{// for _,param:= range param.key{fmt.Println(param.Payload)fmt.Println(param.Description)fmt.Println(param.Time)fmt.Println(param.Keyword)}}

装配数据阶段

配置请求对象 req

项目文件 crawlergo/pkg/model 定义的请求对象结构体包含 8 个变量,考虑只保留如下 5 个变量,重新在 paramsFuzz.go 文件定义请求对象结构体。

type Request struct {URL             *URLMethod          stringHeaders         map[string]interface{}PostData        stringProxy           string
}

明确参数 Fuzz 的需求

  • 遍历 req_list:爬虫结果中 req_list 键的内容,如果存在Get参数或Post参数则进行 Fuzz
  • 遍历 paramJson 中的每一个键:sqli、xss等
保存传递动态参数的 Url 信息

对于爬虫结果,要筛选出传递动态参数的URl进行参数Fuzz测试。

顺便把传递动态参数的Url保存到新的Json文件,方便人工查看,如下代码把传递动态参数的爬虫结果保存到指定文件 params_debug.json。

// 接收第一层 Json 数据
type CrawlerJson struct {ReqList			[]CrawlerData			`json:"req_list"`AllReqList      []CrawlerData 		`json:"all_req_list"`AllDomainList 	[]string 				`json:"all_domain_list"`SubDomainList 	[]string 				`json:"sub_domain_list"`
}type CrawlerData struct {Url			string						`json:"url"`Method      string 						`json:"method"`Headers 	map[string]string 			`json:"headers"`Data 		string 						`json:"data"`Source 		string						`json:"source"`
}// 调用代码
for _,crawler:= range crawlerReq {outputParamsResult(crawler)
}func outputParamsResult(result CrawlerData) {// 写入的文件名变量,在合并代码时需要调整修改outputJsonPath := "debug.json"// 输出结果if len(outputJsonPath) != 0 {resBytes := getParamsJsonSerialize(result)tools.WriteFile("params_" + outputJsonPath, resBytes)}
}func getParamsJsonSerialize(paramsResult CrawlerData) []byte {resBytes, err := json.Marshal(paramsResult)if err != nil {log.Fatal("Marshal result error")}return resBytes
}
装配数据

算法步骤:

  • 准备数据1:读取爬虫结果,调用爬虫结构体的参数信息
  • 准备数据2:读取参数 Fuzz 字典,调用结构体
  • 筛选:遍历爬虫结构体,通过条件判断找出传递动态参数的Url,根据传参方式分为 Get 和 Post
  • 准备数据3:逐个添加 Payload 到动态参数末尾,如果是 Get 方式则拼接 Url 和参数
  • 装配:把爬虫结构体的信息、以及处理后的动态参数信息,装配到请求对象 req
  • 运行和验证:发送请求,查看响应信息验证漏洞是否存在(运行阶段)
  • 标记去重:如果动态参数测试过了,则加入 Array ,并且在测试动态参数前检查是否在 Array 中(验证阶段)
第一步

读取爬虫结果

// 接收第一层 Json 数据
type CrawlerJson struct {ReqList			[]CrawlerData			`json:"req_list"`AllReqList      []CrawlerData 		`json:"all_req_list"`AllDomainList 	[]string 				`json:"all_domain_list"`SubDomainList 	[]string 				`json:"sub_domain_list"`
}type CrawlerData struct {Url			string						`json:"url"`Method      string 						`json:"method"`Headers 	map[string]string 			`json:"headers"`Data 		string 						`json:"data"`Source 		string						`json:"source"`
}func main() {// 1.读取爬虫结果crawlerReq := read_crawlerReq()}func read_crawlerReq() []CrawlerData{var crawlerJson CrawlerJsonbytes, err := ioutil.ReadFile("./debug.json")if err != nil {fmt.Println("读取json文件失败", err)os.Exit(1)}err = json.Unmarshal(bytes, &crawlerJson)if err != nil {fmt.Println("解析数据失败", err)os.Exit(1)}return crawlerJson.ReqList}
第二步

读取参数 Fuzz 的 payload 文件 paramsFuzz.json

// 定义结构体接收参数 Fuzz 的 Json 数据
type ParamsFuzzJson struct {Data			[]ParamData		`json:"data"`
}type ParamData struct {Description string 		`json:"description"`Payload 	string		`json:"payload"`Time 		int			`json:"time"`Keyword		string		`json:"keyword"`
}func main() {// 1.读取爬虫结果crawlerReq := read_crawlerReq()// 2.读取参数 Fuzz 字典/*	功能说明:读取得到一个数组,数组里的元素是 Payload 字典。可以通过遍历数组来逐个读取装配 Payload。调用说明:每次装配 payload 都要绑定一个 request以便使用 payload 字典的关键字等字段判断漏洞是否存在,以及探测漏洞存在后打印 payload 信息也就是说,遍历 payload 数组,是遍历的第一层*/paramsArray := read_paramsPayload()// 遍历 Json 数据中 data 键的键值数组,用于获取每一个 payload 字典for _, payloadDict := range paramsArray.Data {fmt.Println(payloadDict.Payload)}}func read_paramsPayload() ParamsFuzzJson {var paramsFuzzJson ParamsFuzzJsonbytes, err := ioutil.ReadFile("./fuzzDicts/paramsFuzz.json")if err != nil {fmt.Println("读取json文件失败", err)os.Exit(1)}err = json.Unmarshal(bytes, &paramsFuzzJson)if err != nil {fmt.Println("解析数据失败", err)os.Exit(1)}return paramsFuzzJson
}
第三四五步

第三步筛选,遍历爬虫结构体,通过条件判断找出传递动态参数的Url,根据传参方式分为 Get 和 Post。

第四步准备数据3:逐个添加 Payload 到动态参数末尾,然后对URL或者PostData进行字串替换。

第五步装配:把爬虫结构体的信息、以及处理后的动态参数信息,装配到请求对象 req。

嵌套的比较复杂,这三部分代码可以通过 封装函数进行优化。不过目前更重要的还是发送 req 对象,尤其是以多线程的方式发送请求,需要进一步深入查看 crawlergo 的项目代码。第六步和第七步都是其他阶段的任务,可以查看下一章。

func main() {// 定义 req 对象var reqFuzz Request// 代理字段,需要等合并代码时设置相同的字段// reqFuzz.Proxy = crawler.// 1.读取爬虫结果crawlerReq := read_crawlerReq()// 2.读取参数 Fuzz 字典/*功能说明:读取得到一个数组,数组里的元素是 Payload 字典。可以通过遍历数组来逐个读取装配 Payload。调用说明:每次装配 payload 都要绑定一个 request以便使用 payload 字典的关键字等字段判断漏洞是否存在,以及探测漏洞存在后打印 payload 信息也就是说,遍历 payload 数组,是遍历的第一层*/paramsPayloadArray := read_paramsPayload()//fmt.Println(paramsPayloadArray)// 3.从爬虫结果中筛选传递动态参数的请求for _,crawler:= range crawlerReq {if crawler.Method == "GET" {if strings.Contains(crawler.Url, "?") {// 4.逐个装配payload// 获取 Url 数组urlArray := strings.Split(crawler.Url, "?")// 分离Url中的Get参数// 字符串中不包含&时,并不会报错,而是返回只有一个元素的数组paramsArray := strings.Split(urlArray[1], "&")// 装配payload:直接使用 payload 分别替换参数,比如用 id=1<script>alert(/xss/)</script> 替换 id=1for _, value := range paramsArray {// 4.遍历payload装配到每个Get参数,逐个添加 Payload 到动态参数末尾for _, payloadDict := range paramsPayloadArray.Data {payload := value + payloadDict.Payloadfmt.Println("原数据:" + value)fmt.Println("替换后的数据:" + payload)// 5.设置 req 对象,使用 payload 替换元素值,然后装配所有数据reqFuzz.URL = strings.Replace(crawler.Url, value, payload, 1)reqFuzz.Method = crawler.MethodreqFuzz.Headers = crawler.HeadersreqFuzz.PostData = crawler.Data// 6.发送 req 对象,接收响应信息// 7.根据响应信息、以及payload中的关键字、响应时间等信息验证漏洞,如果存在则打印。over}}// 保存传递动态参数的URL信息到文件:params_JsonPathoutputParamsResult(crawler)}}if crawler.Method == "POST" {// 4.逐个装配Post参数paramsArray := strings.Split(crawler.Data, "&")// 遍历每个Post参数for _, value := range paramsArray {// 4.遍历payload装配到每个Get参数,逐个添加 Payload 到动态参数末尾for _, payloadDict := range paramsPayloadArray.Data {payload := value + payloadDict.Payloadfmt.Println("原数据:" + value)fmt.Println("替换后的数据:" + payload)// 5.设置 req 对象,使用 payload 替换元素值,然后装配所有数据reqFuzz.URL = strings.Replace(crawler.Data, value, payload, 1)reqFuzz.Method = crawler.MethodreqFuzz.Headers = crawler.HeadersreqFuzz.PostData = crawler.Data// 6.发送 req 对象,接收响应信息// 7.根据响应信息、以及payload中的关键字、响应时间等信息验证漏洞,如果存在则打印。over}}outputParamsResult(crawler)}}
}

执行阶段

另开一篇文章进行记录,可以前往博客检索查看。

接收结果并验证阶段

另开一篇文章进行记录,可以前往博客检索查看。

这篇关于【毕设扫描器】【参数Fuzz】第一篇:数据的定义、读取和装配(爬虫数据和Payload数据)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/621798

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca