The significance of limiting current
High concurrency system three powerful tools: cache, degrade, limiting
- Cache: Increases the system access speed and processing capacity, and adds caches for corresponding services.
- Degrade: When the server pressure increases sharply, degrade the server according to the service policy to release service resources and ensure normal services.
- Traffic limiting: The service denial, queuing, waiting, and degradation can be handled by limiting concurrent traffic
Leakage bucket flow limiting Time /rate
- rate.NewLimiter(limit,burst)
- Limit Indicates the maximum number of tokens generated and stored in the burst per second
- Allow Checks whether the token can be obtained
- Wait blocks waiting until a token is fetched
- Reserve returns to the wait time and then retrieves the token
Time /rate source code snooping
- Calculate the time difference between the last request and the current request
- Calculate the number of tokens generated within the time difference plus the number of old tokens
- If the token is negative, the wait time is calculated
- If the token is positive, token-1 is requested
Insert upper – limit flow wings into the gateway agent
package middleware
import (
"fmt"
"golang.org/x/time/rate"
)
func RateLimiter(a) func(c *SliceRouterContext) {
l := rate.NewLimiter(1.2)
return func(c *SliceRouterContext) {
if! l.Allow() { c.Rw.Write([]byte(fmt.Sprintf("rate limit:%v,%v", l.Limit(), l.Burst())))
c.Abort()
return
}
c.Next()
}
}
Copy the code
Access to middleware
package main
import (
"github.com/e421083458/gateway_demo/proxy/middleware"
"github.com/e421083458/gateway_demo/proxy/proxy"
"log"
"net/http"
"net/url"
)
var addr = "127.0.0.1:2002"
// Fuse solution
func main(a) {
coreFunc := func(c *middleware.SliceRouterContext) http.Handler {
rs1 := "http://127.0.0.1:2003/base"
url1, err1 := url.Parse(rs1)
iferr1 ! =nil {
log.Println(err1)
}
rs2 := "http://127.0.0.1:2004/base"
url2, err2 := url.Parse(rs2)
iferr2 ! =nil {
log.Println(err2)
}
urls := []*url.URL{url1, url2}
return proxy.NewMultipleHostsReverseProxy(c, urls)
}
log.Println("Starting httpserver at " + addr)
sliceRouter := middleware.NewSliceRouter()
sliceRouter.Group("/").Use(middleware.RateLimiter())
routerHandler := middleware.NewSliceRouterHandler(coreFunc, sliceRouter)
log.Fatal(http.ListenAndServe(addr, routerHandler))
}
Copy the code
test
$curl '127.0.0.1:2002 / abo' http://127.0.0.1:2004/base/abo RemoteAddr = 127.0.0.1:62366, X - Forwarded - For = 127.0.0.1, X-ray Real - Ip headers of = = map [Accept: * / * Accept - Encoding: [gzip] The user-agent: curl / 7.69.1 X - Forwarded - For: [127.0.0.1]] Administrator @ DESKTOP - U15QB8I MINGW64 / d/Dev/workplace/golang/gateway_v1 / pratise/proxy/limiter/rate_limiter (master) $curl '127.0.0.1:2002 / abo' rate Limit: 1, 2 Administrator @ DESKTOP - U15QB8I MINGW64 / d/Dev/workplace/golang gateway_v1 pratise/proxy/limiter/rate_limiter (master) $curl '127.0.0.1:2002 / abo' http://127.0.0.1:2004/base/abo RemoteAddr = 127.0.0.1:62366, X - Forwarded - For = 127.0.0.1, X-ray Real - Ip headers of = = map [Accept: * / * Accept - Encoding: [gzip] The user-agent: curl / 7.69.1 X - Forwarded - For: [127.0.0.1]] Administrator @ DESKTOP - U15QB8I MINGW64 / d/Dev/workplace/golang/gateway_v1 / pratise/proxy/limiter/rate_limiter (master) $curl '127.0.0.1:2002 / abo' rate Limit: 1, 2Copy the code