Developers Club geek daily blog

1 year, 6 months ago
I solved on the example of one project recently to learn, how strongly influences the speed of loading of the website domain sharding. I will remind, an essence of this optimization that static files are loaded from different domains (which, however, can indicate the same server), and it allows to bypass restriction of browsers for the number of simultaneous connections to one domain. Intuitively it seems that in case of a large number of small files it has to accelerate significantly loading of the website in general. Let's check, whether so it actually.

In brief I will describe a situation: there is quite long one-page website, in loading process slightly more than one hundred requests for loading of a statics are made (css, js, fonts, images). The website is written with use of the Ruby on Rails 4.1.12, as the Web server — puma-2.15.3, nginx gives a statics and looks at a puma. All this is started on Digital Ocean droplet in Frankfurt 1 location. And, having such initial data, we should transfer requests for a statics from domains of a type of example.com to domains of a type assets of % { i } .example.com.

First of all it is necessary to configure return of a statics from these addresses. For this purpose it is enough to configure the corresponding DNS records (at me was record for *.example.com is simply set, in my case of it there was enough), and then to change the nginx'a settings (in the directive server_name there is a regulyarka catching hosts of a type of assets0.example.com and assets0.example.ru since in my case the website is available from two different addresses):

server {
  listen       80;
  server_name  ~^assets\d\.(example\.com|example\.ru)$;

  root /home/deployer/sites/example/current/public;

  location ~ ^/assets/ {
    expires 1m;
    add_header Cache-Control public,max-age=259200;
    break;
  }
}

Then it is necessary to change generation of ways to a statics on the party of the application. In rails it is elementary: it is enough to add a line to config/production.rb
config.action_controller.asset_host = "assets%d.example.com"
Then rails at address generation will alternate hosts of "assets0.example.com", …, "assets3.example.com". By the way, I asked a question why 4 addresses, but not 118 (on one on each request that it is absolutely direct very in parallel was). First, for each additional host DNS lookup will be executed, and placement on the page of such quantity of hosts will only slow down loading. Secondly, browsers except a limit on amount of simultaneous requests to one host have a limit on total quantity of simultaneous requests (specific value of a limit I will bring in the end of a post).

Magic a rail — it, of course, is good, but in my case it would not work because of need to generate different addresses at visit of the website from different domains. However, it is configured not strongly more difficult. Also I decided to configure a possibility of optional inclusion / shutdown of domain sharding on the website without the need for change of an application code. It was simplest to make it with use of variables of an environment:

if ENV['DOMAIN_SHARDING'] == 'enabled'
  config.action_controller.asset_host = Proc.new { |source, request|
    if request
      "assets#{rand(4)}.#{request.host_with_port}"
    end
  }
end

For me remains a riddle why check on existence of request is necessary, but in docks it was written quite so, and I did not begin to dig more deeply. I start
$ DOMAIN_SHARDING=enabled rails s -e production
and everything works! Well, almost. Fonts broke, and in the console of the browser of the complaint to Cross-Origin Resource sharing policy.
Text of the message
Font from origin 'http://assets1.localhost:3000' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

With sad thought that not always everything works from a box reflex got to learn something about "Cross-Origin Resource sharing policy rails fonts". Saw mentioning font_assets gem, found the line "Sets Access-Control-Allow-Origin response headers for font assets" in README and decided that it just the fact that it is necessary for me.

My error was that it was necessary to think at first. Then I would understand at once that fonts, as well as other statics, on the fighting server are given to nginx'om which about any gems does not know. In practice there was a small quest: after connection of font_assets everything broke; found why broke, corrected source codes, earned; made fork, registered it in Gemfile; updated the version on the prodakshena; understood that it was necessary to think at first; rolled away the version, deleted fork.

Actually, correction of a situation on the prodakshena was simple: small editing of the section location solves a problem:

location ~ ^/assets/ {
  expires 1m;
  add_header Cache-Control public,max-age=259200;
  add_header Access-Control-Allow-Origin *;
  add_header Access-Control-Allow-Methods GET;
  break;
}

Generally, on it actually setup ended and I began measurements.

Results of measurements


Measured so: opened the Network tab in the inspector of chrome, in the filter put domain: *.example.com/domain:example.com, also refreshed the page. Not the most high-tech method, but allows to trace not only load time, but also its character. (On screenshots only the lower parts of diagrams are shown).
With the included caching, without sharding
Domain sharding: implementation on the Ruby on Rails and results of application
With the included caching, with sharding
Domain sharding: implementation on the Ruby on Rails and results of application

With the disconnected caching, without sharding
Domain sharding: implementation on the Ruby on Rails and results of application

With the disconnected caching, with sharding
Domain sharding: implementation on the Ruby on Rails and results of application

With the included caching, without sharding, Firefox
Domain sharding: implementation on the Ruby on Rails and results of application

With the included caching, with sharding, Firefox
Domain sharding: implementation on the Ruby on Rails and results of application

With the included cache final time quite strongly jumped around mean values, but usually loading happened to domain sharding for ≈0.2-0.4 seconds quicker. In the FF end of loading occurred approximately equally, but with the included sharding the most part of files became available earlier. Also on diagrams restrictions of browsers for the number of simultaneous connections are visually visible: at most 6 to one host, at most 10 in general.
With the disconnected cache the picture smoothed out, but all the same with a sharding was a little quicker. Not absolutely understood why, but at inclusion of restriction of speed to 750 kB/s without sharding worked a little quicker.

Summing up the results: generally, in those days, when browsers permitted only two simultaneous connections, domain sharding improved a situation much stronger, but also now its use makes sense.

This article is a translation of the original post at habrahabr.ru/post/274209/
If you have any questions regarding the material covered in the article above, please, contact the original author of the post.
If you have any complaints about this article or you want this article to be deleted, please, drop an email here: sysmagazine.com@gmail.com.

We believe that the knowledge, which is available at the most popular Russian IT blog habrahabr.ru, should be accessed by everyone, even though it is poorly translated.
Shared knowledge makes the world better.
Best wishes.

comments powered by Disqus