What is config.threadsafe!

Wešichni máme rádi Rails for its elegance and support of differentýfeatur, not to mention that it keepsá pace with thešním technologicalým age and is constantlyále innovating and bringingáší newé possibilities. Rails allows theýsoldieráto focus on the real work and not to solvešunnecessarily theéproblems of theélanguage itself and how to set someéthings up at all, etc. Iává prefer convention to configuration.

This can also be a complication for some, as the Rails framework hidesývá mostšin configurations in itséness and treats them as výchozí. If a výsoldieráwants to achieve certainýchanges and settings, heámustáknow how to do it or where to find it. Startýc´ inýwará usually have´ problems in understanding´ Rails concepts like Rack, Rack Middleware, ActiveRecord, Asset Pipeline, thread safety, etc. In this article, I will discuss the topic of thread safety. 

What is multithreading

Multithreading is a very importantý concept in computationalé science and we should give it moreá attention. Itá is theá processingá of aá pieceá of aá pieceá of aá pieceá of aá pieceá of aá pieceá of aá pieceá of aá pieceá of aá program, instructioná notá hanging on each other, where theá processorá requestsá runá iná parallel. We can use it, for example, when processing long tátás, which are processed asynchronously in the background. 

So how does this work in Ruby on Rails? Thread safety has been introduced in Rails since version 2.3. It means that if máme web server supports multivlákna, then náš kód should být thread safe. If the application is accessed by several waves at once, then the data should not be poý&ed once all waves are finished.

How do I ensure that our Rails application is thread safe?

Rails in a výchozím state adds aývají middleware, whichývá is called “Rack::Lock”. This middleware is a kind ofý iný orderý iný aý pack ofý chozí middlewares. If you want to list all the middleware that your application uses, just type rake middleware in your application root.

The ActionDispatch::Static middleware with the ActionDispatch::Static name is used to serve up static assets such as JavaScript, CSS, and giant assets.

Rack::Lock nám guarantees that only one waveáknob will be triggered at a givený time. If we remove this middleware, then all waves will be triggered at the same time. MRI Ruby has a mechanism called GIL (Global Interpreter Lock) or GVL (Global VM Lock / Giant VM Lock) since Ruby 1.9. The GIL nám thusé guarantees that only one waveák will be triggered at a time, but it doesác have a contextualánáná function. Ruby is so intelligent that it can run a process if another process is waiting for an operation to complete.

Let's take a look at an example of thread safety in a Rails application.

Createíme Rails application.

rails new test_app

Let's access the project folder and run the bundle to install the necessary gems.

bundle

Generate a controller with pár actions.

rails generate controller thread_safety index simple infinite

This example will generate a ThreadSafetyController with the actions index, simple and infinite. Open the šablone umíwall in app/views/thread_safety/index.html.erb and kickáwatchácí kód there:

 




This nám createá stránk with two pushátks, whose úfront is to send Ajax requests tošim actions in the controller and display data in the alert box.

Weá addáme a bit toádu to ourše controller um´walléhim in app/controllers/thread_safety_controller.rb

def simple
sleep(1)
render :text=> "Welcome from simple method"
end
def infinite
while true
end
end

Theód givený inýše is very simpleý. The simple method spí 1 second and poté returná plainý text to the client, andš if the infinite method má an infinite loop and never returná anything because it will probí hat infinitely. Start the server by typing rails s and go to http://localhost:3000/thread_safety/index

Click the “Simple Request” button and after a second you will get a response in the alert box from the server. Nyní click on the “Infinite Request” button and wait for the response.

The infinite method never returns aná iná sequence, due to the infinite loop. Change “Simple Request” again. If you are expecting a response from the server as you did a while ago, you are wrong :-).

This is thread safety. Rails nám guarantees that it will be onše application in this safeá, tím that it will only runá one request at a time. Theá nextá dayá waveá will not runá until it has finishedá an already runningá process.

If we run the application in production mode, we get the sameý vý sequence. This is a goodá and sprá behaviorá because nám Rails ensures safeá kód.

But there's a problem

If you have deployed this application on a production server using the WEBrick web server (which you shouldn't), then your users may have problems with the site because only one query will be served at a time in one wave. If any of the waves take a long time, then the other waves will wait. This solution will annoy the user.

Ourše assets will be released by the serveráváimmediately, as they are notáká by this setup. Assets are handled by the ActionDispatch::Static middleware, so one given asset will be released to several users at the same time.

How can we mediate requests without blocking the other ones? We can simply enable config.threadsafe! in the development.rb or production.rb file. When we enable this option, it causes a massiveí change in theší application!

You can click on the "Simple" button aýt after pressing the "Infinite" button, and the server will return výsequences. We have turned on multithreading support, but now it is our responsibility to write safeý kód.

In this article, weáve introduced the concept of thread safety in Ruby on Rails. However, this is not the case in realálnýl applications. You can use process-based webé servers to reproduce násobný requests even with the config.threadsafe option disabled! These web servers include e.g. Unicorn or Passenger. This is because process-based web servers create worker servers, where each server holds an instance of your application, and therefore the server can handle several requests from each server.