73b0131a9fe92020365449b67af2db40384cbc95
sie-snest-gw\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260.md
... | ... | @@ -141,6 +141,65 @@ |
141 | 141 | 如上图所示,在gw上分别配置就绪和存活探针,用于检测gw是否就绪和存活。 这个检测是独立于nginx存在的,nginx根本就不知道gw的存在,gw也不知道nginx的存在,它们唯一的联系就是```/api``` 这个接口,对于nginx来说不关心谁实现了这个接口,对于gw来说不关心这个接口来自于谁,都是解耦的。 |
142 | 142 | 所以任何一方由于某些原因导致的重启都不会影响其他的容器。 |
143 | 143 | |
144 | +### 3.8 熔断和限流 |
|
145 | + |
|
146 | +作为一个nginx网关的一部分,为了保护上游的引擎服务,需要提供限流和熔断的功能。 |
|
147 | + |
|
148 | +- 限流 |
|
149 | +使用的是优步开源的 ```go.uber.org/ratelimit``` |
|
150 | +只需要在handler中增加限流的middlerware即可,如下代码所示 |
|
151 | + |
|
152 | + ``` |
|
153 | + var ( |
|
154 | + r = ratelimit.New(500) // 100 op per second todo |
|
155 | + ) |
|
156 | + |
|
157 | + func RateLimit() gin.HandlerFunc { |
|
158 | + |
|
159 | + return func(ctx *gin.Context) { |
|
160 | + r.Take() // Call Take() before each operation. Take will sleep until you can continue. |
|
161 | + ctx.Next() |
|
162 | + } |
|
163 | + } |
|
164 | + ``` |
|
165 | + |
|
166 | +- 熔断 |
|
167 | +使用的业界开源的hystrix ```github.com/afex/hystrix-go/hystrix``` |
|
168 | +在代理的地方使用限流保护,如下代码所示: |
|
169 | +``` |
|
170 | + err = hystrix.Do(appNameTag+AtSeparator+ip, func() error { |
|
171 | + var herr error |
|
172 | + startTime := time.Now() // 记录开始时间 |
|
173 | + |
|
174 | + // 创建一个反向代理 |
|
175 | + proxy := httputil.NewSingleHostReverseProxy(targetUrl) |
|
176 | + // 设置错误处理函数 |
|
177 | + proxy.ErrorHandler = func(rw http.ResponseWriter, req *http.Request, err error) { |
|
178 | + herr = err |
|
179 | + klog.Errorf("proxy to %v app=%v err=%v", key, appName, err.Error()) |
|
180 | + ctx.String(http.StatusBadGateway, "Bad Gateway: %v", err) |
|
181 | + } |
|
182 | + ctx.Request.Host = targetUrl.Host |
|
183 | + ctx.Request.URL.Path = path |
|
184 | + proxy.ServeHTTP(ctx.Writer, ctx.Request) |
|
185 | + |
|
186 | + // 计算并打印请求耗时 |
|
187 | + elapsedTime := time.Since(startTime).Milliseconds() |
|
188 | + |
|
189 | + klog.Infof("proxy to %v app=%v cost=%vms", key, appName, elapsedTime) |
|
190 | + return herr |
|
191 | + }, func(err error) error { |
|
192 | + // 熔断开启后,直接返回错误信息,保护下游服务 |
|
193 | + klog.Errorf("hystrix %v app=%v err=%v", key, appName, err.Error()) |
|
194 | + return err |
|
195 | + }) |
|
196 | + if err != nil { |
|
197 | + pkg.Error(ctx, pkg.ErrInternalServerError, "proxy hystrix failed: "+err.Error()) |
|
198 | + return |
|
199 | + } |
|
200 | +``` |
|
201 | + |
|
202 | + |
|
144 | 203 | ## 4. 总结 |
145 | 204 | 通过上述设计与实现方案,sie-snest-gw 网关能够在不修改现有Nginx代码的前提下,提供 app 维度的动态服务注册与发现能力,并通过高效的Unix Domain Socket通信机制,提升系统的整体性能。采用Golang实现的高性能边车服务,与Nginx共同运行,确保系统的高可用性和可扩展性。 |
146 | 205 |