在我们的开发中会用到第三方的代码库,很多时候它都是符合我们的需求,但也许某些场景不太适合,比如我们需要对原有的请求或返回做一些处理,这时候我们就无可奈何了,因为代码库的权限属于其他人,我们无法更改逻辑,如果你也遇到过这个问题,那这时候就可以引入代理模式了,我们可以声明一个新的服务实例,它和原始的接口一模一样,但是我们可以在这个新的服务实例中添加自己的逻辑,然后客户端调用我们新的服务实例,相当于这个新的服务实例是老服务实例的代理人,所有的请求都必须先经过这里然后才被转发处理
现在有一个服务处理接口
package main
type server interface {
handleRequest(string, string) (int, string)
}
原有服务实例
package main
type Application struct {
}
func (a *Application) handleRequest(url, method string) (int, string) {
if url == "/app/status" && method == "GET" {
return 200, "Ok"
}
if url == "/create/user" && method == "POST" {
return 201, "User Created"
}
return 404, "Not Ok"
}
然后我们现在想在所有的请求被处理之前先判断一下是否超过了限流,如果超过了则不处理,那么我们就可以声明一个新的服务实例,它会实现原有的接口,但是会先判断接口是否超过限流
package main
type Nginx struct {
application *Application
maxAllowedRequest int
rateLimiter map[string]int
}
func newNginxServer() *Nginx {
return &Nginx{
application: &Application{},
maxAllowedRequest: 2,
rateLimiter: make(map[string]int),
}
}
func (n *Nginx) handleRequest(url, method string) (int, string) {
allowed := n.checkRateLimiting(url)
if !allowed {
return 403, "Not Allowed"
}
return n.application.handleRequest(url, method)
}
func (n *Nginx) checkRateLimiting(url string) bool {
if n.rateLimiter[url] == 0 {
n.rateLimiter[url] = 1
}
if n.rateLimiter[url] > n.maxAllowedRequest {
return false
}
n.rateLimiter[url] = n.rateLimiter[url] + 1
return true
}