logo
天地变化的道理
使用率很高网站
生活要常常分享
您身边百科全书

为什么网站一定要使用限流

原因

在生产环境中,我们要确保服务器的稳定的执行,cpu,内存,磁盘等资源能不超过一定量,尤其是对io密集型的服务接口更甚,因为很容易拖垮服务器。我们之前有个服务器就是容易爆,后来使用了限流,就保证了服务器能稳定运行。

使用go-water框架

go-water框架内置了限流,只需在需要限流的接口对应的服务定义时添加即可,例如:一分钟最多5次

超过流量将报错
water.ServerErrorLimiter(time.Minute, 5)
超过流量将等待加载
water.ServerDelayLimiter(time.Minute, 5)

完整代码

package main

import (
   "context"
   "fmt"
   "net/http"
   "time"

   "github.com/go-water/water"
)

func main() {
   router := water.New()
   router.POST("/", Index)
   router.Run(":80")
}

// 控制层
var (
   // 超过频次就报错
   options = []water.ServerOption{water.ServerErrorLimiter(time.Minute, 5)}
   index = water.NewHandler(&IndexService{ServerBase: &water.ServerBase{}}, options...)
)

func Index(ctx *water.Context) {
   request, err := water.BindJSON[IndexRequest](ctx)
   if err != nil {
   	ctx.JSON(http.StatusBadRequest, water.H{"err": "binding failure"})
   	return
   }

   resp, err := index.ServerWater(ctx, request)
   if err != nil {
   	ctx.JSON(http.StatusBadRequest, water.H{"err": err.Error()})
   	return
   }

   ctx.JSON(http.StatusOK, resp)
}

// 业务服务层
type IndexService struct {
   *water.ServerBase
}

type IndexRequest struct {
   Name string `form:"name"`
}

type IndexResponse struct {
   Message string
}

func (s *IndexService) Handle(ctx context.Context, req *IndexRequest) (interface{}, error) {
   resp := new(IndexResponse)
   resp.Message = fmt.Sprintf("Hello, %s!", req.Name)
   return resp, nil
}

测试
--request:

{
    "name": "Jimmy"
}
--response:
{
    "Message": "Hello, Jimmy!"
}
--多请求几次就变成,按代码配置,请求6次就会返回如下
{
    "err": "rate limit exceeded"
}

如果要使用超过频次就延迟,修改如下,仅仅替代一行代码
//options = []water.ServerOption{water.ServerDelayLimiter(time.Minute, 5)}

Posted by 肖得胜 on 2025/6/9
如果网站内容有侵犯您的版权
请联系:pinbor@iissy.com
Copyright ©2014 iissy.com, All Rights Reserved.