Rumah > Artikel > pembangunan bahagian belakang > Cara melaksanakan had harian pengguna dalam Go
Artikel ini ditulis oleh ruangan tutorial golang untuk memperkenalkan cara melaksanakan had harian pengguna dalam Go. Saya harap ia dapat membantu rakan yang memerlukan.
Laksanakan had harian pengguna dalam Go (contohnya, anda hanya boleh menerima faedah tiga kali sehari)
Jika anda menulis sistem pengurusan pepijat dan menggunakan ini
PeriodLimit
anda hanya boleh mengehadkan setiap pepijat setiap hari. Adakah kerja lebih mudah? :P
Sebab penting mengapa seni bina perkhidmatan mikro begitu popular pada masa kini adalah untuk mengurangkan kerumitan keseluruhan sistem, mengagihkan risiko sistem secara sama rata kepada subsistem untuk memaksimumkan kestabilan sistem, dan membahagikannya kepada yang berbeza. kawasan melalui pembahagian domain Selepas subsistem dipasang, setiap subsistem boleh dibangunkan, diuji dan dikeluarkan secara bebas, dan rentak dan kecekapan P&P boleh dipertingkatkan dengan ketara.
Tetapi ia juga membawa masalah, seperti: pautan panggilan terlalu panjang, kerumitan seni bina pelaksanaan meningkat dan pelbagai perisian tengah perlu menyokong senario yang diedarkan. Untuk memastikan operasi normal perkhidmatan mikro, tadbir urus perkhidmatan adalah amat diperlukan, yang biasanya merangkumi: pengehadan semasa, penurunan taraf dan pemutus litar.
Penghadan semasa merujuk kepada mengehadkan kekerapan panggilan antara muka untuk mengelakkan melebihi had beban dan menjatuhkan sistem. Contohnya:
Senario jualan kilat e-dagang
Had semasa API untuk pedagang yang berbeza
Biasa digunakan Algoritma pengehad semasa ialah:
Artikel ini menerangkan terutamanya algoritma pengehadan semasa tetingkap masa tetap.
Bermula dari masa tertentu, setiap permintaan datang dengan kiraan permintaan 1. Pada masa yang sama, ia dinilai sama ada bilangan permintaan dalam tetingkap masa semasa melebihi had Jika ia melebihi had, permintaan itu kemudiannya dikosongkan apabila tetingkap masa berikutnya mula menunggu permintaan.
Kelebihan
Mudah untuk melaksanakan Ia adalah cekap dan amat sesuai untuk mengehadkan senario seperti pengguna hanya boleh menghantar 10 artikel sehari, hanya boleh menghantar kod pengesahan SMS 5 kali, dan hanya boleh cuba log masuk 5 kali Senario sebegitu sangat biasa perniagaan.
Kelemahan
Kelemahan pengehadan arus tetingkap masa tetap ialah ia tidak dapat mengendalikan senario permintaan bahagian kritikal secara tiba-tiba.
Anggapkan bahawa had semasa ialah 100 permintaan setiap 1 saat, dan pengguna memulakan 200 permintaan dalam masa 1 saat bermula dari 500ms pertengahan Pada masa ini, semua 200 permintaan boleh diluluskan. Ini tidak konsisten dengan jangkaan kami untuk mengehadkan arus kepada 100 kali sesaat Puncanya ialah ketulusan had semasa adalah terlalu kasar.
core/limit/periodlimit.go
go-zero Gunakan masa tamat redis untuk mensimulasikan tetingkap masa tetap.
skrip redis lua:
-- KYES[1]:限流器key-- ARGV[1]:qos,单位时间内最多请求次数-- ARGV[2]:单位限流窗口时间-- 请求最大次数,等于p.quotalocal limit = tonumber(ARGV[1])-- 窗口即一个单位限流周期,这里用过期模拟窗口效果,等于p.permitlocal window = tonumber(ARGV[2])-- 请求次数+1,获取请求总数local current = redis.call("INCRBY",KYES[1],1)-- 如果是第一次请求,则设置过期时间并返回 成功if current == 1 then redis.call("expire",KYES[1],window) return 1-- 如果当前请求数量小于limit则返回 成功elseif current limit则返回 失败else return 0end
Takrifan pengehad semasa tetingkap masa tetap
type ( // PeriodOption defines the method to customize a PeriodLimit. // go中常见的option参数模式 // 如果参数非常多,推荐使用此模式来设置参数 PeriodOption func(l *PeriodLimit) // A PeriodLimit is used to limit requests during a period of time. // 固定时间窗口限流器 PeriodLimit struct { // 窗口大小,单位s period int // 请求上限 quota int // 存储 limitStore *redis.Redis // key前缀 keyPrefix string // 线性限流,开启此选项后可以实现周期性的限流 // 比如quota=5时,quota实际值可能会是5.4.3.2.1呈现出周期性变化 align bool } )
Beri perhatian untuk menjajarkan Parameter, apabila align=true, had atas permintaan akan berubah secara berkala.
Sebagai contoh, apabila kuota=5, kuota sebenar mungkin 5.4.3.2.1, menunjukkan perubahan berkala
Logik pengehad semasa
Malah, logik pengehad semasa berada di atas Skrip lua dilaksanakan Perlu diingat bahawa nilai pulangan
// Take requests a permit, it returns the permit state. // 执行限流 // 注意一下返回值: // 0:表示错误,比如可能是redis故障、过载 // 1:允许 // 2:允许但是当前窗口内已到达上限 // 3:拒绝 func (h *PeriodLimit) Take(key string) (int, error) { // 执行lua脚本 resp, err := h.limitStore.Eval(periodScript, []string{h.keyPrefix + key}, []string{ strconv.Itoa(h.quota), strconv.Itoa(h.calcExpireSeconds()), }) if err != nil { return Unknown, err } code, ok := resp.(int64) if !ok { return Unknown, ErrUnknownCode } switch code { case internalOverQuota: return OverQuota, nil case internalAllowed: return Allowed, nil case internalHitQuota: return HitQuota, nil default: return Unknown, ErrUnknownCode } }Had semasa tetingkap tetap ini boleh digunakan untuk mengehadkan, contohnya, pengguna hanya boleh menghantar mesej teks kod pengesahan 5 kali sehari Pada masa ini, kita perlu sepadan dengan zon waktu Cina (GMT 8), dan sebenarnya, masa had semasa harus bermula dari sifar, pada masa ini Kami memerlukan penjajaran tambahan (set align to true).
// 计算过期时间也就是窗口时间大小 // 如果align==true // 线性限流,开启此选项后可以实现周期性的限流 // 比如quota=5时,quota实际值可能会是5.4.3.2.1呈现出周期性变化 func (h *PeriodLimit) calcExpireSeconds() int { if h.align { now := time.Now() _, offset := now.Zone() unix := now.Unix() + int64(offset) return h.period - int(unix%int64(h.period)) } return h.period }Alamat projekgithub.com/zeromicro/go-zeroSelamat datang
dan go-zero
bintang untuk menyokong kami!
Atas ialah kandungan terperinci Cara melaksanakan had harian pengguna dalam Go. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!