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

feat!: gateway: fix rate limiting, better stateful handling #12327

Merged
merged 7 commits into from
Aug 9, 2024

Conversation

rvagg
Copy link
Member

@rvagg rvagg commented Jul 31, 2024

Ref: filecoin-project/go-jsonrpc#118
Ref: #11589
Ref: #11153


API changes and breakage:

  • Plain HTTP connections now can't use stateful ethereum APIs (they couldn't really before, but they allowed addition of filters and subs in a dangerous way), you have to be using WebSockets
  • gateway.NewNode now only takes 1 argument (the api) and a list of options to override defaults
  • gateway.NewRateLimiterHandler and gateway.NewConnectionRateLimiterHandler have been replaced with gateway.NewRateLimitHandler.
  • The handlers returned by both gateway.NewRateLimitHandler and the primary gateway.Handler return an http.Handler augmented with a Shutdown(ctx) method to be used for graceful cleanup of resources.
  • The default for the config option Events.FilterTTL has been reduced from 24h to 1h. It's a measure of "how long since this thing was last used", and 24h is way too long for that IMO.

Fix:

  • --per-conn-rate-limit was previously applied as a global rate limiter,
    effectively making it have the same impact as --rate-limit. This change fixes
    the behaviour such that --per-conn-rate-limit is applied as a API call
    limiter within a single connection (i.e. a WebSocket connection). The rate
    is specified as tokens-per-second, where tokens are relative to the expense
    of the API call being made.

Improve:

  • Auto-clean-up of stateful resources when a WebSockets connection ends, so we close down subscriptions and remove filters if the user didn't do so themselves.
  • Added --eth-max-filters-per-conn to override the default (16) and it now applies to the combined total of eth subs and filters, not separately
  • Replace the --conn-per-minute limit mechanism to a standard rate.Limiter instead of the custom rate limit implementation. There is a slight change of behaviour with this in that I allow a burst, which the original doesn't. It also has a different cleanup mechanism with a separate goroutine dedicated to this task instead of a goroutine per request that decrements and may cleanup if zero.

@rvagg rvagg changed the base branch from rvagg/gateway-cleanup to master August 1, 2024 08:12
@rvagg rvagg marked this pull request as ready for review August 1, 2024 11:30
@rvagg rvagg changed the title fix!: gateway: limit stateful calls to websockets (WIP) fix!: gateway: limit stateful calls to websockets Aug 1, 2024
@rvagg rvagg changed the title fix!: gateway: limit stateful calls to websockets feat!: gateway: fix rate limiting, better stateful handling Aug 1, 2024
@rvagg rvagg force-pushed the rvagg/gateway-stateful branch 2 times, most recently from c1c5891 to e5d5408 Compare August 1, 2024 11:56
Copy link
Member

@masih masih left a comment

Choose a reason for hiding this comment

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

Two potential blockers:

  • DoS attack vector due to unbounded limiters per host.
  • Repeated timer instantiation in loop instead of reusing ticker.

Other than that, I left a bunch of comments/suggestions.

Thank you for working on this @rvagg 🍻

cmd/lotus-gateway/main.go Outdated Show resolved Hide resolved
gateway/handler.go Outdated Show resolved Hide resolved
gateway/handler.go Outdated Show resolved Hide resolved
gateway/handler.go Outdated Show resolved Hide resolved
gateway/handler.go Outdated Show resolved Hide resolved
itests/gateway_test.go Outdated Show resolved Hide resolved
itests/gateway_test.go Outdated Show resolved Hide resolved
itests/gateway_test.go Outdated Show resolved Hide resolved
itests/gateway_test.go Outdated Show resolved Hide resolved
itests/gateway_test.go Outdated Show resolved Hide resolved
@rvagg
Copy link
Member Author

rvagg commented Aug 5, 2024

@masih thanks for the thorough review. I've gone through all your feedback and marked as resolved the easy bits here but left as unresolved the things that may either need follow-up or have responses to questions. Would you mind having another look please?

@rvagg rvagg force-pushed the rvagg/gateway-stateful branch 3 times, most recently from bd4f35d to 07fed9f Compare August 5, 2024 10:42
@rvagg
Copy link
Member Author

rvagg commented Aug 5, 2024

I've messed something up in rate limiting in my latest round of changes, TestGatewayRateLimits is failing now. I need to fix that first.

Minor API changes:

* gateway.NewRateLimiterHandler and gateway.NewConnectionRateLimiterHandler have
  been replaced with gateway.NewRateLimitHandler.
* The handlers returned by both gateway.NewRateLimitHandler and the primary
  gateway.Handler return an http.Handler augmented with a Shutdown(ctx) method
  to be used for graceful cleanup of resources.

Fix:

* --per-conn-rate-limit was previously applied as a global rate limiter,
  effectively making it have the same impact as --rate-limit. This change fixes
  the behaviour such that --per-conn-rate-limit is applied as a API call
  limiter within a single connection (i.e. a WebSocket connection). The rate
  is specified as tokens-per-second, where tokens are relative to the expense
  of the API call being made.
* CLI takes --eth-max-filters-per-conn
* gateway.NewNode() now takes the API plus an optional list of Options
@rvagg rvagg force-pushed the rvagg/gateway-stateful branch 2 times, most recently from 3017789 to e842d6e Compare August 8, 2024 08:21
@rvagg rvagg requested a review from masih August 8, 2024 10:36
@rvagg
Copy link
Member Author

rvagg commented Aug 8, 2024

@masih || @aarshkshah1992 would you mind having one last look over this before I merge please? @masih the final commit should be the delta between your review and now and contains mostly things you raised.

@rvagg rvagg enabled auto-merge (rebase) August 9, 2024 01:02
@rvagg rvagg merged commit a7b1db5 into master Aug 9, 2024
83 of 84 checks passed
@rvagg rvagg deleted the rvagg/gateway-stateful branch August 9, 2024 01:03
@rjan90 rjan90 mentioned this pull request Aug 22, 2024
37 tasks
@rjan90 rjan90 mentioned this pull request Aug 31, 2024
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: ☑️ Done (Archive)
Development

Successfully merging this pull request may close these issues.

2 participants