2

I have an application does full text search on my product database. Certain searches are suggested to the user and are much more common than other searches.

As full text searches are expensive, I'm using Nginx to cache the search results. I would like my users to be able to do as many of suggested common searches as they want as these searches should be cached most of the time. However, I would like to aggressively rate limit the uncached/uncommon searches.

Is it possible to apply different rate limiting depending on if Nginx has the resource cached?

nwarp
  • 143
  • 3
  • Are you not able to distinguish which are cached resources and which are to be generated on the fly based on some part of the URL (e.g. static resources being served below a `/static/` subfolder)? – anx Jun 05 '22 at 16:10
  • I've rewritten the question to give more background – nwarp Jun 06 '22 at 03:50
  • **How does your application know which search is part of the suggestions?** If that list is static, put it directly into your nginx config. If that list is cheap to lookup, have two search endpoints and redirect to the rate-limited one upon receipt of a query not ordinarily accessible from your site. If, however, it is expensive to even determine which queries are cheap.. then you can still make nginx respond from cache only for all requests exceeding rate limit. – anx Jun 06 '22 at 04:34

1 Answers1

0

I managed to disable rate limiting for cached resources by creating two separate instances of nginx. The first instance is caching requests and the second is rate limiting requests. I was kind of forced to do it because of the recent problems with https://search.maven.org.

The part of config of caching instance:

http {
    proxy_cache_path /data/nginx/cache keys_zone=mavencache:100m max_size=100m inactive=144h;
    server {
        proxy_cache mavencache;
        location / {
            proxy_cache_valid 200 144h;
            proxy_pass http://IP_ADDRESS_OF_THE_HOST_WITH_THE_RATE_LIMITING_INSTANCE:8080;
        }
     }
}

IP_ADDRESS_OF_THE_HOST_WITH_THE_RATE_LIMITING_INSTANCE could be localhost if both instances are on the same server.

The part of config of rate limiting instance:

http {
    limit_req_zone global zone=maven:100m rate=1r/s;
    server {
        location / {
            limit_req zone=maven burst=1000;
            proxy_pass https://search.maven.org:443;
        }
        listen       8080;
        listen       [::]:8080;
     }
}

Now if I create a request which is not cached the caching instance will call the rate limiting instance which will rate limit that request to https://search.maven.org:443. If I create the same request I will get it from the caching instance quickly without rate limiting.

Example:

$ export MAVEN_CENTRAL_URL=http://192.168.122.176/solrsearch/select

$ time trivy i --clear-cache; time trivy i -s "MEDIUM,HIGH,CRITICAL" --debug logstash:7.0.0

real    2m5,127s
user    0m10,140s
sys     0m0,588s

$ time trivy i --clear-cache; time trivy i -s "MEDIUM,HIGH,CRITICAL" --debug logstash:7.0.0

real    0m7,938s
user    0m8,991s
sys     0m0,611s