Fork me on GitHub

版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | http://vearne.cc

引言

我们打算统计服务的QPS,原型已经选了
go-metrics
PS: 1800多个star看来不会错
但是我还是打算自己实现一版,看看我自己的实现和它的实现有什么不同

实现

package main

import (
    "fmt"
    "time"
)

type MeterRate1 struct {
    count int64
    // start和end 是一段移动的时间区间
    // start和end 都是自新纪元起经历的秒数
    // end - start = 60 seconds
    start int64
    end   int64
    // 存储某一时刻,对应的count值
    timestampCountMap map[int64]int64
}

func NewMeterRate1() *MeterRate1 {
    m := MeterRate1{}
    m.count = 0
    t := time.Now().Unix()
    m.start = t - 60
    m.end = t
    m.timestampCountMap = make(map[int64]int64, 60)

    // 启动一个协程用于每秒"快照"
    go MeterTick(&m)
    return &m
}

func (m *MeterRate1) Mark(n int64) {
    m.count += n
}

func (m *MeterRate1) Rate() float64 {
    return float64(m.timestampCountMap[m.end]-m.timestampCountMap[m.start]) / 60.0
}

func MeterTick(m *MeterRate1) {
    // 每秒触发一次, 快照这一时刻的count值, 存入timestampCountMap
    c := time.Tick(time.Second * 1)
    for x := range c {
        fmt.Println("tick", x)
        t := time.Now().Unix()
        m.timestampCountMap[t] = m.count
        m.start = t - 60
        m.end = t
        delete(m.timestampCountMap, m.start-1)
        fmt.Println("---------------")
        for i := m.start; i < m.end+1; i++ {
            fmt.Printf("time:%v, count:%v\n", i, m.timestampCountMap[i])
        }
    }
}

func main() {
    m := NewMeterRate1()
    go MyPrint2(m)
    var j int64 = 1
    for true {
        time.Sleep(time.Second * 1)
        j++
        m.Mark(j)
    }
}

func MyPrint2(m *MeterRate1) {
    for true {
        time.Sleep(time.Second)
        fmt.Println("rate1", m.Rate())
    }
}

在下一篇文章中,我会来介绍一下go-metrics中关于Meter的实现


如果我的文章对你有帮助,你可以给我打赏以促使我拿出更多的时间和精力来分享我的经验和思考总结。

微信支付码

发表评论

电子邮件地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据