版权声明: https://blog.csdn.net/qq_29785317/article/details/86112759
总体流程
由于是模拟项目,所以先用golang生成一些假的用户访问日志数据,以便后面作分析。
模拟用户访问日志部分
代码实现(log.go):
package main
import (
"flag"
"fmt"
"math/rand"
"net/url"
"os"
"strconv"
"strings"
"time"
)
var uaList = []string{
"Mpzilla/5.0",
"IE/10",
"Chorme/34.2",
"Safari/2.12",
}
// 资源结构体,存放模拟url的生成配置
type resource struct {
url string // 用户访问页面的url
target string // 用户访问页面的具体资源对象,id表示
start int // 资源数的起始量
end int // 资源数的结束量
}
/*
* 获取初始化的url生成配置,以便生成用户访问日志数据
*/
func ruleResource() []resource {
var res []resource
r1 := resource{
url: "http://localhost:8888",
target: "",
start: 0,
end: 0,
}
r2 := resource{
url: "http://localhost:8888/list/{$id}.html",
target: "{$id}",
start: 1,
end: 21,
}
r3 := resource{
url: "http://localhost:8888/movie/{$id}.html",
target: "{$id}",
start: 1,
end: 12924,
}
res = append(res,r1,r2,r3)
return res
}
/*
* 根据url生成配置,构造用户访问的url,返回生成好的切片
*/
func buildUrl(res []resource) []string {
var list []string
for _,resItem := range res {
if len(resItem.target) == 0 { // 如果访问的是首页
list = append(list,resItem.url)
} else {
for i:=resItem.start;i<=resItem.end;i++{
urlStr := strings.Replace(resItem.url,resItem.target,strconv.Itoa(i),-1)
list = append(list,urlStr)
}
}
}
return list
}
/*
* 生成具体的日志数据
*/
func makeLog( current, refer, ua string) string {
// 生成url query部分字符串
u := url.Values{}
u.Set( "time","1")
u.Set( "url",current)
u.Set( "refer",refer)
u.Set( "ua",ua)
paramsStr := u.Encode()
logTemplate := "127.0.0.1 - - [08/Mar/2018:00:48:34 +0800] \"OPTIONS /dig?{$paramsStr} HTTP/1.1\" 200 43 \"-\" \"{$ua}\" \"-\" "
// 替换掉模板的 $paramsStr 和 ua 部分
log := strings.Replace(logTemplate,"{paramStr}",paramsStr,-1)
log = strings.Replace(log,"{ua}",ua,-1)
return log
}
/*
* 获取随机数
*/
func randInt(min, max int) int {
r := rand.New( rand.NewSource( time.Now().UnixNano()))
if min > max {
return max
}
return r.Intn(max-min)+min
}
func main() {
// 通过命令行收集参数 total-要创建的日志行数,filepath-要保存的日志文件路径
total := flag.Int("total",100,"rows be created")
filePath := flag.String("filePath","~/go/dig.log","file path")
flag.Parse()
// 需要构造出真实的网站url集合
res := ruleResource()
list := buildUrl( res )
// 随机取currentUrl,referUrl,ua,循环拼接 total 行日志
logStr := ""
for i := 0; i < *total; i++{
currentUrl := list[ randInt(0, len(list)-1) ]
referUrl := list[ randInt(0, len(list)-1) ]
ua := uaList[ randInt(0, len(uaList)-1) ]
logStr = logStr + makeLog( currentUrl, referUrl, ua ) + "\n"
//ioutil.WriteFile(*filePath,[]byte(logStr),0644)
}
// 写日志
fd,_ := os.OpenFile(*filePath,os.O_RDWR|os.O_APPEND,0644)
fd.Write([]byte( logStr ))
fd.Close()
//按照要求,生成total行日志内容,源自上面的这个集合
fmt.Println("done.\n")
}
基本流程:
1.从命令行收集用户想要生成的日志行数(total
),一行相当于一个请求,以及要保存日志文件的路径(filePath
)。
2.通过函数ruleResource()
获取生成url的配置,这个配置用切片存储,切片里面是程序最开始时定义好的 用于放具体url生成配置的 结构体。
3.根据配置生成具体url,放进一个叫list的切片里,返回这个切片。
4.基于list切片和程序开始时定义的uaList切片,随机取值分别赋值给currentUrl,referUrl,ua,然后循环拼接 total 行日志。
5.将拼接好的日志字符串以追加写得方式写进指定的日志文件。
涉及的点
- 字符串替换
usage:strings.Replace(resItem.url,resItem.target,strconv.Itoa(i),-1)
要引入strings包 - 整形转化为字符串
j := strconv.Itoa(i)
- 随机数
先说结论:
1.伪随机数并不是假随机数,这里的“伪”是有规律的意思,就是计算机产生的伪随机数既是随机的又是有规律的。
2.随机种子来自系统时钟,确切地说,是来自计算机主板上的定时/计数器在内存中的记数值。
3.随机数是由随机种子根据一定的计算方法计算出来的数值。所以,只要计算方法一定,随机种子一定,那么产生的随机数就不会变。也就是说,伪随机数也是某种对应映射的产物,只不过这个自变量是系统的时间而已
4.如果你每次调用时都提随机函数时供相同的种子值,那么,你将会得到相同的随机数序列
可参考这个链接 => 传送门
c语言的随机数请看这个链接 => 传送门
golang中生成随机数的方式(引入 math/rand 包):
import math/rand
// Rand对象
r := rand.New( rand.NewSource( time.Now().UnixNano()))
r.Intn(100) // 返回[0,100)的随机整数
/**------或者-------**/
// 全局函数
rand.Seed(time.Now().Unix())
rand.Intn(100)
- 收集命令行参数
total := flag.Int("total",100,"rows be created")
filePath := flag.String("filePath","~/go/dig.log","file path")
flag.Parse()
// 后面要获取total和filePath的值时,需要解引用,即 *total 和 *filePath才能拿到值
- 文件读写
logStr := "log str here"
fd,_ := os.OpenFile(*filePath,os.O_RDWR|os.O_APPEND,0644)
fd.Write([]byte( logStr ))
fd.Close()
- query字符串生成
u := url.Values{}
u.Set( "time","1")
u.Set( "url",current)
u.Set( "refer",refer)
u.Set( "ua",ua)
paramsStr := u.Encode()