一,安装用到的库
1,从命令行安装 x/time/rate库
iuhongdi@ku:~$ go get -u golang.org/x/time/rate
说明:刘宏缔的go森林是一个专注golang的博客, 地址:https://blog.csdn.net/weixin_43881017
说明:作者:刘宏缔 邮箱: [email protected]
二,演示项目的相关信息
1,地址:
https://github.com/liuhongdi/digv14
2,功能说明:
演示了针对ip的地址的限流,
限制同一ip地址在单位时间内可以发起请求的次数
3,项目结构:如图:
三,配置文件
config/config.yaml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
LogFilePath: /data/gologs/logs
-
-
-
-
-
LogFilePath: /data/gologs/logs
-
-
-
-
四,go代码说明
1,global/limiter.go
-
-
-
-
-
-
-
-
type IPRateLimiter struct {
-
ips map[string]*rate.Limiter
-
-
-
-
-
-
-
RateLimiter *IPRateLimiter
-
-
-
-
func SetupIPRateLimiter() (error) {
-
-
-
b := LimiterSetting.CountPerSecond
-
RateLimiter = &IPRateLimiter{
-
ips: make(map[string]*rate.Limiter),
-
-
-
-
-
-
-
-
-
func (i *IPRateLimiter) AddIP(ip string) *rate.Limiter {
-
-
-
-
limiter := rate.NewLimiter(i.r, i.b)
-
-
-
-
-
-
func (i *IPRateLimiter) GetLimiter(ip string) *rate.Limiter {
-
-
limiter, exists := i.ips[ip]
-
-
-
-
-
-
-
2,global/setting.go
-
-
-
-
-
"github.com/liuhongdi/digv14/pkg/setting"
-
-
-
-
type ServerSettingS struct {
-
-
-
ReadTimeout time.Duration
-
WriteTimeout time.Duration
-
-
-
type DatabaseSettingS struct {
-
-
-
-
-
-
-
-
-
-
-
-
type LogSettingS struct {
-
-
-
-
-
-
-
-
type AccessLogSettingS struct {
-
-
-
-
-
-
type LimiterSettingS struct {
-
-
-
-
-
ServerSetting *ServerSettingS
-
DatabaseSetting *DatabaseSettingS
-
-
AccessLogSetting *AccessLogSettingS
-
LimiterSetting *LimiterSettingS
-
-
-
-
func SetupSetting() error {
-
s, err := setting.NewSetting()
-
-
-
-
err = s.ReadSection("Database", &DatabaseSetting)
-
-
-
-
-
err = s.ReadSection("Server", &ServerSetting)
-
-
-
-
-
err = s.ReadSection("Log", &LogSetting)
-
-
-
-
-
err = s.ReadSection("AccessLog", &AccessLogSetting)
-
-
-
-
-
err = s.ReadSection("Limiter", &LimiterSetting)
-
-
-
-
-
-
fmt.Println(ServerSetting)
-
fmt.Println(DatabaseSetting)
-
-
fmt.Println(AccessLogSetting)
-
fmt.Println(LimiterSetting)
-
-
3,main.go
-
-
-
-
"github.com/gin-gonic/gin"
-
_ "github.com/jinzhu/gorm/dialects/mysql"
-
"github.com/liuhongdi/digv14/global"
-
"github.com/liuhongdi/digv14/router"
-
-
-
-
-
-
-
err := global.SetupSetting()
-
-
log.Fatalf("init.setupSetting err: %v", err)
-
-
-
-
err = global.SetupLogger()
-
-
log.Fatalf("init.SetupLogger err: %v", err)
-
-
-
-
err = global.SetupAccessLogger()
-
-
log.Fatalf("init.SetupAccessLogger err: %v", err)
-
-
-
-
err = global.SetupDBLink()
-
-
log.Fatalf("init.SetupLogger err: %v", err)
-
global.Logger.Fatalf("init.setupDBEngine err: %v", err)
-
-
-
-
err = global.SetupIPRateLimiter()
-
-
log.Fatalf("init.SetupIPRateLimiter err: %v", err)
-
global.Logger.Fatalf("init.SetupIPRateLimiter err: %v", err)
-
-
-
global.Logger.Infof("------应用init结束")
-
-
-
-
-
global.Logger.Infof("------应用main函数开始")
-
-
gin.SetMode(global.ServerSetting.RunMode)
-
-
-
-
r.Run(":"+global.ServerSetting.HttpPort)
-
4,middleware/limit.go
-
-
-
-
-
"github.com/gin-gonic/gin"
-
"github.com/liuhongdi/digv14/global"
-
"github.com/liuhongdi/digv14/pkg/result"
-
"github.com/liuhongdi/digv14/pkg/util"
-
-
-
func LimitMiddleware() gin.HandlerFunc {
-
return func(c *gin.Context) {
-
-
ipAddr:=util.GetRealIp(c)
-
fmt.Println("current ip:"+ipAddr)
-
-
limiter := global.RateLimiter.GetLimiter(ipAddr)
-
-
fmt.Println("not allow,will return")
-
resultRes := result.NewResult(c)
-
resultRes.Error(2004,"访问超出限制")
-
-
-
fmt.Println("allow,next")
-
-
-
-
5,router/router.go
-
-
-
-
"github.com/gin-gonic/gin"
-
"github.com/liuhongdi/digv14/controller"
-
"github.com/liuhongdi/digv14/global"
-
"github.com/liuhongdi/digv14/middleware"
-
"github.com/liuhongdi/digv14/pkg/result"
-
-
-
-
func Router() *gin.Engine {
-
-
-
router.NoRoute(HandleNotFound)
-
router.NoMethod(HandleNotFound)
-
-
router.Use(middleware.AccessLog()).Use(middleware.LimitMiddleware())
-
-
-
-
articlec:=controller.NewArticleController()
-
router.GET("/article/getone/:id", articlec.GetOne);
-
router.GET("/article/list", articlec.GetList);
-
-
-
-
-
func HandleNotFound(c *gin.Context) {
-
global.Logger.Errorf("handle not found: %v", c.Request.RequestURI)
-
-
result.NewResult(c).Error(404,"资源未找到")
-
-
-
-
-
func Recover(c *gin.Context) {
-
-
if r := recover(); r != nil {
-
-
-
global.Logger.Errorf("panic: %v", r)
-
-
global.Logger.Errorf("stack: %v",string(debug.Stack()))
-
-
-
-
result.NewResult(c).Error(500,"服务器内部错误")
-
-
-
-
-
6,其他相关代码可访问github.com
五,测试效果
-
root@ku:/data/liuhongdi/digv14
-
This is ApacheBench, Version 2.3 <$Revision: 1879490 $>
-
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
-
Licensed to The Apache Software Foundation, http://www.apache.org/
-
-
Benchmarking 127.0.0.1 (be patient).....done
-
-
-
-
Server Hostname: 127.0.0.1
-
-
-
Document Path: /article/list
-
Document Length: 821 bytes
-
-
-
Time taken for tests: 0.056 seconds
-
-
-
(Connect: 0, Receive: 0, Length: 43, Exceptions: 0)
-
-
Total transferred: 14441 bytes
-
HTML transferred: 7897 bytes
-
Requests per second: 894.84 [
-
Time per request: 55.876 [ms] (mean)
-
Time per request: 1.118 [ms] (mean, across all concurrent requests)
-
Transfer rate: 252.39 [Kbytes/sec] received
-
-
-
min mean[+/-sd] median max
-
-
Processing: 10 25 9.0 25 41
-
-
-
-
Percentage of the requests served within a certain time (ms)
-
-
-
-
-
-
-
-
-
100% 46 (longest request)
一秒时间内,只有7次成功的访问,
和我们在配置文件中设置的CountPerSecond的值是一致的
六,查看库的版本:
-
module github.com/liuhongdi/digv14
-
-
-
-
-
github.com/gin-gonic/gin v1.6.3
-
github.com/go-playground/universal-translator v0.17.0
-
github.com/go-playground/validator/v10 v10.2.0
-
github.com/jinzhu/gorm v1.9.16
-
github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f
-
github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042
-
github.com/magiconair/properties v1.8.4
-
github.com/mitchellh/mapstructure v1.3.3
-
github.com/pelletier/go-toml v1.8.1
-
github.com/pkg/errors v0.9.1
-
github.com/spf13/afero v1.4.1
-
github.com/spf13/cast v1.3.1
-
github.com/spf13/jwalterweatherman v1.1.0
-
github.com/spf13/pflag v1.0.5
-
github.com/spf13/viper v1.7.1
-
go.uber.org/multierr v1.6.0
-
-
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68
-
|
请发表评论