1. 程式人生 > >golang 流量統計系統視訊總結(一)

golang 流量統計系統視訊總結(一)

總體流程

在這裡插入圖片描述

由於是模擬專案,所以先用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()