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

Rate Limit API Calls #502 #509

Merged
merged 1 commit into from
Sep 6, 2022
Merged

Conversation

amvanbaren
Copy link
Contributor

Fixes #502

Testing steps

  • Open this PR in Gitpod, wait for the workspace to fully initialize.
  • Stop the server.
  • Edit server/src/dev/resources/application.yml file, change capacity to 1 and unit to hours.
  • Start the server.
  • Send a request to the public API (/vscode or /api), it shouldn't get rate limited.
  • Send another request to the public API, now it does get rate limited.

Copy link
Member

@filiptronicek filiptronicek left a comment

Choose a reason for hiding this comment

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

Hey @amvanbaren! Thanks for taking time to do this.

I like the approach, it seems to work reliably and the default of 15 / sec sounds reasonable. I also like that we have the x-rate-limit-remaining and x-rate-limit-retry-after-seconds headers.

A couple of things I found:

@amvanbaren
Copy link
Contributor Author

amvanbaren commented Aug 15, 2022

I looked through VS Code's source code and could not find any checks for HTTP 429. Maybe this is worth exploring further and seeing what VS Code does in this scenario (I don't think the Microsoft Marketplace has rate-limiting in place).

vscode-rate-limiting

I've tested this on VSCodium 1.70.1. There's no error popups, but it does break images and content isn't loaded. There's no retry logic. This is with heavy rate limiting (1 request every 15 seconds). With a rate limit of 15 requests every second, I wasn't able to hit the rate limit. A /extensionquery request that returns 50 extensions might cause rate limiting when the icons for all of these extensions are requested at once.

You can test this yourself, by:

  • Editing src/main/java/org/eclipse/openvsx/web/WebConfig.java by changing the vscode mapping to:
registry.addMapping("/vscode/**")
        .allowedOrigins("*")
        .allowedHeaders("content-type","vscode-sessionid", "x-market-client-id", "x-market-user-id")
        .allowedMethods("GET", "POST");
  • Editing VS Code or VSCodium resources/app/product.json to point to the server:
"extensionsGallery": {
  "serviceUrl": "https://8080-<GITPOD_WORKSPACE_ID>.gitpod.io/vscode/gallery",
  "itemUrl": "https://8080-<GITPOD_WORKSPACE_ID>.gitpod.io/vscode/item"
},
  • Change the rate limiting settings in src/dev/resources/application.yml
  • Restart the server
  • Start VS Code or VSCodium

@filiptronicek
Copy link
Member

Thanks for testing, @amvanbaren 🙏! Would it make sense to disable/increase the rate limit for just icons? So that we could really make it practically impossible to hit when using it with VS Code?

@amvanbaren
Copy link
Contributor Author

Would it make sense to disable/increase the rate limit for just icons?

Yes, that would make sense. Then /vscode/asset/{namespace}/{extension}/{version}/Microsoft.VisualStudio.Services.Icons.Default needs to be excluded or have its own rate limit.
On the other hand these responses are cached by the Open VSX load balancer, so in a lot of cases the request will not even hit the server.

@akosyakov
Copy link
Member

if we want to adjust rate limiting in production how the process would look like?

@amvanbaren
Copy link
Contributor Author

if we want to adjust rate limiting in production how the process would look like?

Then you change the bucket4j configuration in https://github.com/EclipseFdn/open-vsx.org/blob/main/configuration/application.yml and redeploy. Currently /api/-/namespace/create and /api/-/publish are grouped together and the other endpoints are grouped separately based on the way they're rate limited (access token vs. IP address), but you can split it up further and define different rate limits for each endpoint.

@akosyakov
Copy link
Member

It sounds great, if it is nuder our control then we can start with such generous limiting and then modify it as we go 🙏

@akosyakov
Copy link
Member

15 requests a second for the same client should be enough for VS Code.

@amvanbaren
Copy link
Contributor Author

I've increased the limit for icons to 75 per second, just in case. And yes, it that is too generous you can modify it as you go.

@kineticsquid
Copy link

@amvanbaren This is excellent! We also need to think about documentation updates before we deploy this, API and deployment info.

- capacity: 15
time: 1
unit: seconds

Copy link
Member

Choose a reason for hiding this comment

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

suggestion (non-blocking): can we add heavier rate-limiting for /sitemap.xml? Maybe there are even more endpoints which take a look of compute to respond, but this is one that's really easy to hit and it takes sometimes even 5 seconds to generate (on https://open-vsx.org).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, the sitemap endpoint is heavy. It gets all active extensions from the database and turns it into a XML document. It does return caching headers to the client, but it does re-generate the document for every request. So, even if clients respect the caching response headers, the server still re-generates the sitemap for every other client that requests the sitemap.

I think it's a good idea to cache the result on the server (possibly in combination with ETag headers), so that it only re-generates the sitemap when an extension is added, removed or updated. Or maybe even just generate it once a day.

Copy link
Member

@filiptronicek filiptronicek left a comment

Choose a reason for hiding this comment

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

Hey @amvanbaren, gave this another round of testing.

I think we can postpone my suggestion from #509 (review) to a later PR, since it's nothing blocking.

I tried the VS Code icon endpoint and it seems to work just fine as well.

Added CORS response headers to bucket4j configuration
Retry request in webui if request got rate limited
Abort in-flight requests when component unmounts
Load extension icon through `extension-registry-service.ts`, so that it reloads if the request got rate limited.

Increase rate-limit for VS Code icons

# Conflicts:
#	server/build.gradle
#	server/src/main/resources/ehcache.xml
#	webui/src/pages/user/user-settings-namespaces.tsx
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.

Rate Limit API Calls
4 participants