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 ratelimiter for node api #577

Merged
merged 3 commits into from
Sep 11, 2018
Merged

Add ratelimiter for node api #577

merged 3 commits into from
Sep 11, 2018

Conversation

evan2645
Copy link
Member

@evan2645 evan2645 commented Sep 1, 2018

This commit adds ratelimiting logic for calls to the node api. It uses
client IP as the ratelimiting key, and will drop log lines if/when a
client is affected by the limiting.

Signed-off-by: Evan Gilman evan@scytale.io

This commit adds ratelimiting logic for calls to the node api. It uses
client IP as the ratelimiting key, and will drop log lines if/when a
client is affected by the limiting.

Signed-off-by: Evan Gilman <evan@scytale.io>
Copy link
Member

@azdagron azdagron left a comment

Choose a reason for hiding this comment

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

Neato! A few comments...

l.notify(callerID, msgType)
}
if !res.OK() {
res.Cancel()
Copy link
Member

Choose a reason for hiding this comment

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

nit: do you need to cancel if the burst limit has been exceeded?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure :) I put it there "just in case"... I've removed it.

}

func (l *limiter) limiterFor(msgType int, callerID string) (*rate.Limiter, error) {
limiters := l.limitersFor(msgType)
Copy link
Member

Choose a reason for hiding this comment

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

since limitersFor is only ever called by limiterFor, and holds the lock for the entire function, you may consider calling it while under the lock (and removing the Lock()/Unlock() inside limitersFor.

Copy link
Member Author

Choose a reason for hiding this comment

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

I did this out of concern for code safety... instead, opted to leave a code comment on limitersFor, and moved to only taking a lock in limiterFor

// be processed. It introspects the context in order to identify the caller. An error will be
// returned if the context is cancelled, an invalid msgType is specified, or if the number
// of messages exceeds the burst limit.
func (l *limiter) Limit(ctx context.Context, msgType, count int) error {
Copy link
Member

Choose a reason for hiding this comment

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

so if i understand correctly, the limits are imposed per caller, per msg type? 500 ops a second per caller seems a tad high....

Copy link
Member Author

Choose a reason for hiding this comment

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

That's correct, though the "limit" is the max burst size - no request with more than 500 CSRs will be allowed to pass. The actual rate is defined when the struct is created, currently capped at 100 per second... In this example, if a request was submitted with 500 CSRs, it would (under the worst conditions) have to wait 5 seconds for it to be permitted.

Since exceeding this limit would be a permanent error condition, I have taught the agent to truncate requests that would exceed it, allowing the remainder to be submitted on the next manager cycle

@@ -0,0 +1,141 @@
package node
Copy link
Member

Choose a reason for hiding this comment

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

nit: use github.com/stretchr/testify helpers to cut down on assertion boilterplate

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

* Clean up tests through use of testify
* Teach agent to not exceed burst limit
* Use coarse outer lock w/ code comment instead of granular independent
locks
* Dont cancel reservations for limits that are not "OK"

Signed-off-by: Evan Gilman <evan@scytale.io>
Copy link
Member

@azdagron azdagron left a comment

Choose a reason for hiding this comment

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

Huzzah!

@evan2645 evan2645 merged commit dd55fcc into spiffe:master Sep 11, 2018
@evan2645 evan2645 deleted the ratelimit-node-api branch September 11, 2018 21:06
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.

2 participants