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