返回介绍

流量控

发布于 2023-06-25 22:01:52 字数 4380 浏览 0 评论 0 收藏 0

利用go channel实现限流量控制,原理:设置一个缓冲通道,设置访问中间键,当用户请求连接时判断channel里面长度是不是大于设定的缓冲值,如果没有就存入一个值进入channel,如果大于缓冲值,channel自动阻塞。当用户请求结束的时候,取出channel里面的值。

如果想限制用户HTTP请求进行速率限制可以参考 https://github.com/didip/tollbooth 这个中间键

目录:

-videos

--ce.html

-limiter.go

-main.go

main.go文件代码:

package main

import (
    "log"
    "net/http"
    "text/template"
    "time"

    "github.com/julienschmidt/httprouter"
)

type middleWareHandler struct {
    r *httprouter.Router
    l *ConnLimiter
}

//NewMiddleWareHandler ...
func NewMiddleWareHandler(r *httprouter.Router, cc int) http.Handler {
    m := middleWareHandler{}
    m.r = r
    m.l = NewConnLimiter(cc)
    return m
}

func (m middleWareHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if !m.l.GetConn() {
        defer func() { recover() }()
        log.Panicln("Too many requests")
        return
    }
    m.r.ServeHTTP(w, r)
    defer m.l.ReleaseConn()
}

//RegisterHandlers ...
func RegisterHandlers() *httprouter.Router {
    router := httprouter.New()
    router.GET("/ce", ce)
    return router
}

func ce(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
    //为了演示效果这块设置了等待
    time.Sleep(time.Second * 100)
    t, _ := template.ParseFiles("./videos/ce.html")
    t.Execute(w, nil)
}

func main() {
    r := RegisterHandlers()
    //里面的参数2为设置的最大流量
    mh := NewMiddleWareHandler(r, 2)
    http.ListenAndServe(":9000", mh)
}

limiter.go文件代码

package main

import (
    "log"
)

//ConnLimiter 定义一个结构体
type ConnLimiter struct {
    concurrentConn int
    bucket         chan int
}

//NewConnLimiter ...
func NewConnLimiter(cc int) *ConnLimiter {
    return &ConnLimiter{
        concurrentConn: cc,
        bucket:         make(chan int, cc),
    }
}

//GetConn 获取通道里面的值
func (cl *ConnLimiter) GetConn() bool {
    if len(cl.bucket) >= cl.concurrentConn {
        log.Printf("Reached the rate limitation.")
        return false
    }

    cl.bucket <- 1
    return true
}

//ReleaseConn 释放通道里面的值
func (cl *ConnLimiter) ReleaseConn() {
    c := <-cl.bucket
    log.Printf("New connction coming: %d", c)
}

videos/ce.html文件代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    www.topgoer.com是个不错的go语言中文文档
</body>
</html>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文