Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add X-RateLimit-* response headers as an opt-in feature #56

Closed
wants to merge 3 commits into from

Conversation

armsnyder
Copy link

@lyft/network-team

Around August 2018, Envoy added a new field, headers to the RateLimitResponse proto message, which can be used to give Envoy custom headers to attach to its response:
envoyproxy/envoy#4015

With this PR the ratelimit service will populate this response field with three headers:

Header Description How it maps to the descriptor statuses
X-RateLimit-Limit The number of requests allowed in the configured unit of time The CurrentLimit.RequestsPerUnit value for the RateLimitResponse_DescriptorStatus if there is one. If more than one descriptor from the request has an associated limit, then this field is NOT included in the response.
X-RateLimit-Remaining The number of requests remaining before the subsequent request will be rate limited The smallest LimitRemaining value of the RateLimitResponse_DescriptorStatuss returned by the Redis cache.
X-RateLimit-Reset The number of seconds until the limit resets and requests will start to succeed Calculated similarly to the way the Redis client generates descriptor keys, using modulo arithmetic with the RateLimit.Unit and current time. If there are multiple descriptors, the one with the fewest remaining requests and longest time to reset is used.

The behavior of populating these headers is disabled by default, so this change is perfectly backwards-compatible. The behavior must be enabled explicitly using the RESPONSE_HEADERS_ENABLED environment variable.

The legacy rate limit API also still functions when RESPONSE_HEADERS_ENABLED is true, but the headers are dropped from the response during the conversion step.

Copy link
Member

@junr03 junr03 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay here @armsnyder, I was not able to allocate space to maintenance in the last few months, but will be very responsive going forward.

I have a high level comment about proto maintenance. If you are ok with taking that on in this PR, I would appreciate it. If not, let me know and I can review the rest of the PR.

@@ -7,6 +7,6 @@ $protoc --version
protoc --go_out=plugins=grpc:. proto/ratelimit/*.proto

# Data-plane-api proto
data_plane_cmd="protoc --go_out=plugins=grpc,Menvoy/api/v2/ratelimit/ratelimit.proto=github.com/lyft/ratelimit/proto/envoy/api/v2/ratelimit:proto/. --proto_path=vendor/github.com/envoyproxy/data-plane-api --proto_path=vendor/github.com/lyft/protoc-gen-validate --proto_path=vendor/github.com/google/protobuf/src "
data_plane_cmd="protoc --go_out=plugins=grpc,Menvoy/api/v2/ratelimit/ratelimit.proto=github.com/lyft/ratelimit/proto/envoy/api/v2/ratelimit,Menvoy/api/v2/core/base.proto=github.com/envoyproxy/go-control-plane/envoy/api/v2/core:proto/. --proto_path=vendor/github.com/envoyproxy/data-plane-api --proto_path=vendor/github.com/lyft/protoc-gen-validate --proto_path=vendor/github.com/google/protobuf/src "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

proposal: for ease of management of the envoy-api protos, I think we should just take go-control-plane as a glide dependency, and remove the proto compilation and the compiled protos. Leaving the legacy proto/ratelimit/ratelimit.pb.go in place of course.

@stevenscg
Copy link

@armsnyder I'm new this to project and evaluating it for rate-limiting outside of Envoy (for now). I was planning to build up these standard headers from the raw data in the response anyway, so this feature seems very useful.

Could a standard grpc client receiving the response proxy these headers upstream to the caller?

An example for the project readme could help give the feature some visibility.

@stevenscg
Copy link

@junr03 @armsnyder I was just building out my own client library that similarly constructs these headers and noticed that the value required for X-RateLimit-Reset was not already available via the existing response. I also noticed that Lyft does not expose these headers in their own APIs.

It seems like I see X-RateLimit-Reset included in most rate limiting schemes, so I wonder why the project originally decided not to calculate the reset time? (performance? lack of business need?)

Regardless, I am still a big fan of this PR!

rateLimitResetHeader(limitingDescriptor, now),
}
} else if limitCount > 1 {
// If there is more than one limit, then picking one of them for the "X-RateLimit-Limit"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@armsnyder I just ran into this same situation (two or more descriptors that match the request) while building my client library. My test case is contrived and might not represent real world usage, but do we have any sense as to whether most users of this project have multiple descriptors that match on a regular basis?

Like you did here, I have no obvious way to decide which set of limiting conditions to show. Maybe the closest to the limit on a literal or percentage basis - the worst case of them all?

The consuming app doesn't know which rate limiting condition they are hitting when given just the headers and I've never seen a provider that enumerated which rate limit I was hitting.

@mattklein123
Copy link
Member

Sorry for the embarrassingly long delay in getting this reviewed. Let's get this reviewed and merged. I think we need to fix our CI also which is probably out of date. @junr03 are you able to review this? If not I will take a look.

@junr03
Copy link
Member

junr03 commented Apr 5, 2019

My earlier comments were not resolved. I can take ownership of the branch and you can review, once I merge master to bring in #73. I still think it is for the best (especially since what you had to do for #73), to defer proto compilation to go-control-plane like we have done in other places. I can do that in a subsequent PR to this.

@mattklein123 We can land this together monday, I am ooo today.

@mattklein123
Copy link
Member

@junr03 sg sorry didn't realize you were still tracking. Thank you!

@junr03
Copy link
Member

junr03 commented Apr 8, 2019

@armsnyder (for obvious permissions reasons) I can't take over this PR. I have opened a new PR #77. PTAL if you would like to review, or let me know if you want to work on it. Closing this version for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants