版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | 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的实现


请我喝瓶饮料

微信支付码