内容简介:本博客是深入研究Envoy Proxy和Istio.io 以及它如何实现更优雅的方式来连接和管理微服务系列文章的一部分。这是接下来几个部分的想法(将在发布时更新链接):Envoy通过两个
本博客是深入研究Envoy Proxy和Istio.io 以及它如何实现更优雅的方式来连接和管理微服务系列文章的一部分。
这是接下来几个部分的想法(将在发布时更新链接):
- 断路器(第一部分)
- 重试/超时(第二部分)
- 分布式跟踪(第三部分)
- Prometheus的指标收集(第四部分)
- rate limiter(第五部分)
第五部分 - rate limiter
Envoy ratelimit filters
Envoy通过两个 过滤器 与Ratelimit服务集成:
- Network Level Filter: envoy为安装过滤器的侦听器上的每个新连接调用Ratelimit服务。这样,您可以对通过侦听器的每秒连接进行速率限制。
- HTTP Level Filter:Envoy为安装过滤器的侦听器上的每个新请求调用Ratelimit服务,路由表指定应调用Ratelimit服务。许多工作都在扩展HTTP过滤器的功能。
envoy 配置 启用 http rate limiter
http rate limiter 当请求的路由或虚拟主机具有与过滤器阶段设置匹配的一个或多个速率限制配置时,HTTP速率限制过滤器将调用速率限制服务。该路由可以选择包括虚拟主机速率限制配置。多个配置可以应用于请求。每个配置都会导致将描述符发送到速率限制服务。
如果调用速率限制服务,并且任何描述符的响应超出限制,则返回429响应。速率限制过滤器还设置x-envoy-ratelimited标头。
果在呼叫速率限制服务中出现错误或速率限制服务返回错误并且failure_mode_deny设置为true,则返回500响应。
全部的配置如下:
envoy.yaml: |- static_resources: listeners: - address: socket_address: address: 0.0.0.0 port_value: 8000 filter_chains: - filters: - name: envoy.http_connection_manager config: codec_type: auto stat_prefix: ingress_http access_log: - name: envoy.file_access_log config: path: "/dev/stdout" format: "[ACCESS_LOG][%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% \"%REQ(X-FORWARDED-FOR)%\" \"%REQ(USER-AGENT)%\" \"%REQ(X-REQUEST-ID)%\" \"%REQ(:AUTHORITY)%\" \"%UPSTREAM_HOST%\" \"%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%\"\n" route_config: name: local_route virtual_hosts: - name: gateway domains: - "*" routes: - match: prefix: "/cost" route: cluster: cost rate_limits: # enable rate limit checks for the greeter service actions: - destination_cluster: {} http_filters: - name: envoy.rate_limit # enable the Rate Limit filter config: domain: envoy - name: envoy.router config: {} clusters: - name: cost connect_timeout: 0.25s type: strict_dns lb_policy: round_robin hosts: - socket_address: address: cost.sgt port_value: 80 - name: rate_limit_cluster type: strict_dns connect_timeout: 0.25s lb_policy: round_robin http2_protocol_options: {} hosts: - socket_address: address: limiter.sgt port_value: 80 rate_limit_service: grpc_service: envoy_grpc: cluster_name: rate_limit_cluster timeout: 0.25s admin: access_log_path: "/dev/null" address: socket_address: address: 0.0.0.0 port_value: 9000
通过配置文件可以看出,本demo设置的是一个全局的http filter rate limiter。
尽管分布式熔断通常在控制分布式系统中的吞吐量方面非常有效,但有时它不是非常有效并且需要全局速率限制。最常见的情况是当大量主机转发到少量主机并且平均请求延迟较低时(例如,对数据库服务器的连接/请求)。如果目标主机已备份,则下游主机将淹没上游群集。在这种情况下,在每个下游主机上配置足够严格的断路限制是非常困难的,这样系统在典型的请求模式期间将正常运行,但在系统开始出现故障时仍能防止级联故障。全局速率限制是这种情况的一个很好的解决方案。
编写rate limiter 服务
Envoy直接通过gRPC与速率限制服务集成。Envoy要求速率限制服务支持rls.proto中指定的gRPC IDL。有关API如何工作的更多信息,请参阅 IDL 文档。
本身envoy 只是提供了限流的接口,没有具体的实现,所以必须自己实现一个限流器。下面只是简单实现一下,给大家一个思路。
具体的代码如下:
package main import ( "log" "net" "time" rls "github.com/envoyproxy/go-control-plane/envoy/service/ratelimit/v2" "github.com/juju/ratelimit" "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/reflection" ) // server is used to implement rls.RateLimitService type server struct { bucket *ratelimit.Bucket } func (s *server) ShouldRateLimit(ctx context.Context, request *rls.RateLimitRequest) (*rls.RateLimitResponse, error) { // logic to rate limit every second request var overallCode rls.RateLimitResponse_Code if s.bucket.TakeAvailable(1) == 0 { overallCode = rls.RateLimitResponse_OVER_LIMIT } else { overallCode = rls.RateLimitResponse_OK } response := &rls.RateLimitResponse{OverallCode: overallCode} return response, nil } func main() { // create a TCP listener on port 8089 lis, err := net.Listen("tcp", ":8089") if err != nil { log.Fatalf("failed to listen: %v", err) } log.Printf("listening on %s", lis.Addr()) // create a gRPC server and register the RateLimitService server s := grpc.NewServer() rls.RegisterRateLimitServiceServer(s, &server{ bucket: ratelimit.NewBucket(100*time.Microsecond, 100), }) reflection.Register(s) if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } }
具体项目,查阅 github 。
PS:
- 使用了令牌桶算法来限流。令牌桶算法(Token Bucket)和 Leaky Bucket 效果一样但方向相反的算法,更加容易理解.随着时间流逝,系统会按恒定1/QPS时间间隔(如果QPS=100,则间隔是10ms)往桶里加入Token(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了.新请求来临时,会各自拿走一个Token,如果没有Token可拿了就阻塞或者拒绝服务.
- 该实现存在单点风险。
- Dockerfile均在代码仓库中,大家可以构建镜像自己测试。
结论
本文简单讲了envoy的 rate limit功能,提供了全局限流的配置文件,并简单实现了一个基于令牌桶的限流器。希望能帮助你理解Envoy的限速过滤器如何跟gRPC协议协同工作。
以上所述就是小编给大家介绍的《使用Envoy 作Sidecar Proxy的微服务模式-5.rate limiter》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- MongoDB – 使用模式构建之属性模式
- MongoDB – 使用模式构建之多态模式
- 使用函数式实现观察者模式模式
- 使用模式构建:模式版本控制模式(The Schema Versioning Pattern)
- 使用模式构建:多态模式(The Polymorphic Pattern)
- 使用模式构建:桶模式(The Bucket Pattern)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。