golang 流量統計系統視訊總結(一)
阿新 • • 發佈:2019-01-14
總體流程
由於是模擬專案,所以先用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()