Several solutions to improve Ruby on Rails performance _ruby topics

Source: Internet
Author: User
Tags garbage collection memcached svn ssh fast web ruby on rails haproxy

Brief introduction

The Ruby on Rails framework has been widely watched since its inception and, guided by ideas like "Don't repeat Yourself" and "contract is superior to configuration", rails gives Web developers a very high level of development efficiency. ActiveRecord's flexibility allows you to use a very easy-to-use Hibernate without cumbersome configuration, Github and Rubygems's rich and varied rails plug-ins are another powerful guarantee for rails to develop efficiently. Rails is a really thorough MVC framework, and rails clearly separates the code of your model from the View code with the application logic of your model-view-controller. Rails developers have little or no trouble with where some code should be placed, and in the rails world, the responsibilities of your code are clearly positioned, and you can easily decide which layer they should be in. The Rails1.2 version begins to support the rest Service, and with these built-in special, you can provide Web Service based on the rest API while you're developing your Web application and presenting it to the user's HTML, and you'll also be able to make it easy. To consume a Web Service based on the Rest API provided by a third party, like using the Model of basic data.

Through search engines, you can find many similar articles that use rails for rapid development, such as creating a Blog system with Ruby on rails for 15 minutes. Ruby on Rails is also very friendly to the agile development process, incorporating unit test in the Rails framework, and Function test testing your Model and application logic. With these, you do not need to install any plug-ins or libraries to facilitate the test-driven development, through the support of Watir, you can easily use the Ruby code to achieve browser-based automated testing. In addition, with the support of plug-ins such as Rspec, you can even conduct the behavior-driven development (behaviour driven Development), make your test code more meaningful, and more easily accepted by customers.

While the advantages of rails are that you can list them all at once, you may also have examples of code lines that develop the same functionality Web applications with java/hibernate/spring/struts and Ruby on rails, or provide a Java/hiberna Te/spring/struts and Ruby on Rails develop the training materials that need to be accepted for examples, but we all inevitably face scalability (scalability) problems. Many WEB applications face a large number of user groups, and such applications can be challenged by the performance of concurrency. Rails does not convince everyone at this point, and there are still a lot of system architects and engineers who are skeptical that rails is suitable for developing high load concurrent WEB applications. But it is undeniable that with the advent of the large load applications such as Twitter, friends for Sale,basecamp, rails is increasingly recognized as scalable, and these sophisticated applications also tell us that it is possible to develop rails applications that handle millions of of user requests simultaneously. The Ruby on Rails framework is criticized for its scalability in the following points, the Ruby language itself is a performance problem, Ruby on Rails lacks a proven high-performance application server, supports database extensions, lacks a reliable network provider on the Internet, and so on. From these points, this article describes the deployment architecture for a scalable rails application and some of the better practices for developing high-performance rails applications.

The usual Web2.0 applications, especially the high load applications, in addition to Web and application server selection, load balancing such deployments need to face the problem, often have to face background tasks, high-performance Full-text Search These development problems, these in Java or PHP These more mature development environment has a relatively mature scheme, development and architecture staff will often have a variety of options, combined with specific applications to make architectural design. In the emerging rails community, these are not perfect and mature, this article will introduce some of the high-performance scalable rails application development and deployment of specific practices, for the typical Web 2.0 Web site encountered the specific problems of analysis and solutions, designed to provide Rails developers with specific reference. The content described in this article can be combined with the following diagram:
Figure 1. The overall structure of this article

Use Nginx+passenger to replace Apache+mongrel to deploy Rails applications

In fact, the Rails deployment can be described very simply, we need some machines to configure our environment, for performance and cost, we naturally choose the Linux series of servers, optional Centos,debian, Ubuntu server and so on. All of the programs, commands, and code in this article, if not specifically described, are based on Linux as a basic environment. Then we need the database to store our data, we can choose the free Mysql, and then we start to develop our Web application rails code, when we deploy, we need to support Ruby on Rails application server to get our rails code running, which may be rails Webrick, of course, this possibility is very small, can also be FastCGI, or mongrel,thin, passenger and so on, and then we through the Apache,nginx,lighttpd,haproxy and other Web Server access to our application server, this access can be directly through the HTTP protocol, can be FastCGI, or a custom other protocol, and so on, we can access our application through the browser. This is the usual Rails application deployment structure, as shown in the following illustration.
Figure 2. Rails Application Deployment Structure

For the front end of the Web Server,apache is the de facto industrial standard, in the Web server market, is the highest, the world's largest number of sites using Apache to deploy their applications, Apache is a mature and stable Web server, very powerful, providing for almost all We b Development Language and framework extension support, with the rails framework support, we can use the Mod_fcgid module, through the FastCGI protocol and the rails process communication. Alternatively, HTTP distribution is made using Mod_proxy_balancer on the back-end standalone Rails server such as Thin Cluster,mongrel Cluster or Apach/nginx+passenger. But Apache as a common server, in performance and some lightweight Web server is far from the difference. Apache's mod_proxy_balancer modules are less distributed than Nginx or Haproxy, and Apache does not currently support the event (event) model, which only supports prefork (process) mode and worker (thread mode, each process a link, you need to create a process or thread, and some lightweight Web servers such as Nginx and Lighttpd, are very good use of kernel event mechanism to improve performance, greatly reduce the number of threads or processes, reduce system load.

Nginx is a lightweight, efficient and fast WEB server that has high performance as an HTTP server and a reverse proxy server. Nginx can be compiled and run on most Unix like OS and has a Windows portable version. Nginx selected Epoll and Kqueue as the development model, which can support the response of up to 50,000 concurrent connections, and can directly support Rails and PHP programs for external service internally. In addition, Nginx as a load balancing server, can also support the external service as an HTTP proxy server, Nginx both system resource cost and CPU efficiency is much better than Apache. When you open the official website of Nginx, you will find that the official homepage of such a well-known Web server product is so simple, in fact, the Nginx itself is a very simple installation, the configuration file is very concise, can even use the Perl syntax in the configuration file.

Both Apache and Nginx are capable of handling static files. But for the application server or the front-end load-balancing server, we recommend Nginx rather than the relative Nginx of the more heavyweight Apache.

For application server, Mongrel was once the most popular way of deployment, its HTTP protocol parsing part is written in C language, the efficiency is guaranteed. Mongrel uses Ruby's user-threading mechanism for multithreaded concurrency, but Ruby is not a local thread, and Rails is not thread-safe, so Mongrel is completely lock-locked in the execution of rails code, which doesn't really make much difference to the single process. All we do when using Mongrel to deploy Rails applications is to start up a mongrel_cluster in the background to start multiple Mongrel processes, such as the following configuration in the mongrel_cluster.yml can be 8000~8009 The port starts 10 Mongrel processes.
Listing 1. MONGREL_CLUSTER.YML Configuration

 Port: "8000"

This deployment actually limits the ability of Mongrel to handle large concurrent applications. When processing large volume of data requests, the Mongrel process is often hung, but a number of concurrent, there will be all Mongrel into the situation, so that the front-end server will not be returned, the entire Web apps are paralyzed. So, Mongrel is not widely used, many sites would rather insist on using the oldest FastCGI deployment method also do not use Mongrel to deploy the application, and Mongrel also stopped updating for a long time, Mongrel developers have completely no longer Mongrel development. Therefore, Mongrel is not the most recommended Rails application server now.

Passenger is a mod_php-like Rails runtime environment, rather than a stand-alone Http server like Mongrel. Passenger supports both the current major Apache and Nginx WEB servers. Passenger is extremely convenient to use, and it has high performance, from the passenger official website published test results, passenger performance is better than the Mongrel server, at present, passenger is undoubtedly the best choice. Passenger inherits the practice of rails "do not repeat itself," and by passenger the application, you simply upload the Rails project program files to the target server without even having to reboot the server.

To install and run passenger in a Nginx environment, you only need to do the following:
Listing 2. Install passenger

 Gem Install passenger 

The following code shows the configuration of passenger on Nginx:
Listing 3. Configure passenger on the Nginx

 HTTP { 
  server { 
    Passenger_enabled on; 

Using Nginx+passenger to build a Ruby on Rails application Server can achieve significant performance improvements, and Ruby Enterprise Edition can be used to improve the performance of Ruby itself. This version is also developed by Phusion, using the Copy-on-write garbage collection strategy, and using Tcmalloc to improve memory allocation, their website published data, using Ruby Enterprise Edition can be reduced by 33 than the normal Ruby version % of memory consumption.

Nginx+passenger is deployed on a machine application server, but the concurrency is too large, a machine is not enough to provide such processing capacity, this time, generally do load balancing, this and the usual load balancing strategy is not different, Nginx In the use of reverse proxy to achieve load balancing ability on the superior to Apache reverse proxy module, we can in multiple Nginx+passenger front-end can add a Nginx Web server. Even for stronger processing power, we can use LVS to load balance.

Use Starling and workling to perform Rails background tasks asynchronously

In the development of Web applications, each Web request needs to be quickly returned, at which point some of the larger operations can be placed in the background asynchronous execution, such as a large number of data update operations, only to be triggered in the Web application, and then execute in the background. Some operations need to be performed regularly, such as data backup, statistical analysis of some data, image processing, mail delivery, and so on. It is obviously inappropriate for these operations to be immediately returned in a WEB application, and the load on the machine is severe, which, in addition to impacting the user experience, will block the rails server instance and thus lead to a drop in overall performance for the rails application. For this type of operation, we can use a task queue, join the actions that need to be performed, and then take out the tasks in the background and then start the process into the queue, and execute, the queues can be implemented using databases, Memcached, ActiveMQ or Amazon SQS, The back-end process can be manipulated using Cronjob+script/runner or BACKGROUNDRB in Rails. The solution to be presented here is to implement the Starling message queues and workling plug-ins that are contributed by Twitter developers using the Memcache protocol.

Starling is an open-source Rails plugin that the Twitter development team abstracts from Twitter, although Starling is not exactly the plugin used by Twitter's online version, but we can also be confident that Starling's performance and response to high concurrency Ability. Similar plug-ins also have backgroundrb,background job, Background_fu. BACKGROUNDRB is the use of DRB implementation of the queue message delivery, but it also has a problem, update the queue, BACKGROUNDRB use pessimistic lock, in the case of large traffic, this situation is not allowed. Background jobs and BACKGROUND_FU are database-based message queues, and the performance of the database is not easily guaranteed in a large amount of load. And Starling is based on the Memcached protocol Message Queuing, more efficient and easier to scale, usually you can run a starling server on each application server, and on the same machine or other machines to run the background program to interact with it.

We install starling with the following command:
Listing 4. Install Starling

 Gem sources-a 
 sudo gem install starling-starling 

When reading the Starling Server, we need memcache-client, the 1.5.0 version of this gem has some problems in fiveruns-memcache-client to be corrected, this FIVERUNS-MEMCACHE-CL The Ient gem is automatically installed as a dependency in the Starling-starling gem.

After installing starling, use the sudo starling-d-P 15151 command to start it, specifying the port to use with the-p parameter at startup, and the general-D argument to make it run in the background in a daemon way:

In order to understand what the Starling and Starling did, after starting the Starling, we can do a simple test using the program we opened under IRB:

Perform a simple test
Listing 5. Test Starling

 >> require ' starling '
 => true 
 >> starling = (' 
 => MemCache: 1 servers, Ns:nil, Ro:false 
 >> starling.set (' Test_queue ', 123) 
 => nil 
 >> loop {puts Starling . Get (' test_queue '); Sleep 1} 

Here we can see that the Server is actually started, and then we insert the data here, we use a loop to access the queue, and the final output is the result we want.

Next we install Workling:
Listing 6. Install workling

 Script/plugin Install Git://

Workling supports a variety of ways to perform background task operations, including the Starling installed above, and after installing Starling, we need to configure workling to use Sta in the Rails application with the following code ENVIRONMENT.RB Rling:
Listing 7. Using workling

 Workling::remote.dispatcher =

Workling's configuration file is workling.yml, similar to other Rails profiles, workling.yml can also be different modes for different product modes, where only the production configuration is listed.
Listing 8. Workling Configuration

   listens_on:localhost:15151, localhost:15152, localhost:15153 

The listens_on parameter is the address and port of the starling boot that workling_client accesses, where multiple starling addresses can be allowed, which means that you start multiple starling servers with a workling_client To call. Sleep_time is the wait time for workling_client to fetch data from the queue, and Reset_time defines the time that workling_client waits to rebuild and connect to the server if a memcache error occurs. The namespace parameter in Memcache_options defines the namespace used, which is useful if the same server starts the same starling server for different Rails applications.

We can start the workling_client process with the script/workling_client start script, sometimes we think a workling_client is not enough, we can modify Script/workling_client Start to support multiple workling_client instances so that a new workling_client instance is started each time the script/workling_client start is run.
Listing 9. Workling configuration for multi-client

 Options = { 
 : app_name  => "workling" 
 : ARGV    => ARGV, 
 :d ir_mode =>  : Normal, 
 :d ir    => File.join (File.dirname (__file__), ' ... ', ' log '), 
 : Log_output => True, 
 : multiple  => True, 
 : BackTrace => True, 
 : Monitor  => true 

Using Memcached and Cache-money to cache data

Rails itself provides four kinds of caching methods, namely Page cache, Action cache,fragment cache and ActiveRecord cache, three kinds of caching. Page cache is the most efficient caching mechanism, and he caches the entire page in the form of static page HTML, which is very effective for pages that don't change frequently. The action cache is a cache of an action, which differs from page cache in that the HTTP request passes through the Rails application server until all the before filters are processed, which can handle page cache processing If you need to log on to verify the page, you can verify the steps to join before filter, Fragment cache for caching a part of the page, different parts of the same page can also adopt different expiration strategies. For the caching mechanism of Rails itself, we can write sweeper for expiration and cleanup. ActiveRecord Cache is a new version of the caching mechanism for ActiveRecord in Rails, using SQL query caching, which uses caching for database operations of the same SQL statement within the same action.

The rails caching mechanism is very effective at improving Web site performance, and rails defaults to the caching of the file system, which is not suitable for storage in a production environment, the efficiency of file IO is limited, and rails supports saving cache in the same process's memory, but if there are multiple rails Application, the cache cannot be shared between them. What we recommend here is to store it in a MemCached way, which is also a popular way to cache storage at the moment.

The Memcached is developed by the Danga Interactive to enhance the access speed. has thousands of dynamic page accesses per second, user 7 million. Memcached is a highly high-performance distributed memory object caching system based on a hash table that stores key/value pairs. Its daemon (daemon) is written in C, Memcached the database load significantly reduced, better allocation of resources, faster access. Clients can be implemented in a variety of other languages. The Rails Memcached client is already installed in the introduction above, because we only need to configure the following in the rails application:
Listing 10. Memcached Configuration

 Config.cache_store =: Mem_cache_store, ' localhost:11211 '

Can be used to cache data using MemCached. In addition to the Rails itself caching mechanism, we also directly use the Rails.cache operation Memcached for data caching, such as we read the number of all blogs, you can use the following cache:
Listing 11. Using Rails.cache

 Blogs_count = Rails.cache.fetch ("Blogs_count") do 

Rails itself is limited in its own ActiveRecord, only for caching the SQL query statements in the same action, we need a more powerful ActiveRecord cache, and Cache-money is being introduced to solve this problem. As Twitter becomes more and more stable and gets rid of the shadow of being taken as a typical example of "rails cannot expand," people expect the Twitter development team to contribute more to the rails community, Cache-money after Starling Twitt Another plug-in contributed by the ER team. The level two cache of Cache-money and Hibernate is similar to a read-write (Write-through) cache. Instead of purging the data in the cache when the ActiveRecord object is updated, it writes the updated content directly to the cache.

Cache-money has a number of great features, such as caching automatic Cleanup (using After_save/after_destroy), supporting transactions, and because Rails ' Active record does not provide a after_commit mechanism, the current common cache The plug-in has a cache update competition conflict under high concurrency, and this feature is useful for solving this problem, and can be installed via a gem: Cache-money
Listing 12. Install Cache-money

 Gem sources-a 
 sudo gem install Nkallen-cache-money 
 require ' Cache_money '

Listing 13. Configure CONFIG/MEMCACHED.YML

 namespace: ... 

 development: ... 


 Config = yaml.load ( (File.join (rails_root, "config", "memcached.yml")) [rails_env] 
 $memcache = (config) 
 $memcache. Servers = config[' servers '] 
 $local = ($memcache) 
 $ Lock = ($memcache) 
 $cache = ($local, $lock) 
 class ActiveRecord::Base 
 is_cached:repository => $cache 

The use of Cache-money is very convenient, do not need additional operations, only in your Model inside a simple configuration, such as:
Listing 15. Configure Model to use Cache_money

 Class User < activerecord::base 
 class Post < activerecord::base 
 Index [: Title,: Author] 
 class Article < activerecord::base 
 version 7 
 index ... 

You can then use Rails to ActiveRecord various methods and transaction operations as before. If you change the table structure of the database, you can change the version number of Model to invalidate the previous cache without restarting the Memcached server.

Using Sphinx+libmmseg+ultrasphinx for Full-text search

Many applications will have the need for Full-text search, of course, you can directly integrate Google or other search engine to provide the search service, but if you want to better control your search results, or your search results for reuse, you may have to achieve full text search yourself. In Chinese full-text search, we generally consider two aspects, namely the performance of the search tool used, and the preparation of Chinese word segmentation. In the Java world, Lucene is the absolute authority and the first choice to do full-text search, although it does not have a good support for Chinese word segmentation, but there are many third-party plug-ins can be used to improve the preparation rate and performance of Chinese word segmentation. Ferret was once the most popular version of the Rails Full-text search plug-in, but this article recommends a more efficient Sphinx. Sphinx was developed by the Russian Andrew Aksyonoff, meaning "The lion body Face", which can complete the index of millions of records in a two-minute period and return the search results in the millisecond class. Sphinx and database integration is good, through the configuration file, directly used to index the data of the database, in addition, Sphinx developed a SPHINXSE database engine, you can compile MySQL directly into the MySQL inside to achieve a database-level efficient index. Using Sphinx in Rails enables the Ultrasphinx plug-in, which rails developers can use to easily invoke Sphinx functionality.

You can download Sphinx from here

After installing the Sphinx, you can install Ultrasphinx directly from the RubyForge:
Listing 16. Install Ultrasphinx

Ruby Script/plugin Install Svn://

Libmmseg is a Chinese word segmentation program, the latest version is 0.7.3, the use of C + + development, Word segmentation algorithm is "complex maximum matching (Complex maximum matching)", while supporting the Linux platform and Windows platform, segmentation speed around 300K/S (pm-1.2g), libmmseg from version 0.7.2, the author provides the interface for Ruby invocation, so we can use LIBMMSEG for word segmentation directly in Ruby, which is quite handy. Libmmseg can download the installation via

Users can modify the dictionary file to increase their own custom words, in order to improve the word segmentation in a specific field of segmentation accuracy, the system default dictionary file in the Data/unigram.txt. Then through the Mmseg-u unigram.txt This command to produce a file named Unigram.txt.uni, the file renamed to Uni.lib, complete the construction of the dictionary. It should be noted that unigram.txt must be encoded for UTF-8.

LIBMMSEG developers in order to better let Sphinx use libmmseg for Chinese participle, for Sphinx developed a related patch, from here two patch files:



And then patch it up:
Listing 17. Install Sphinx Patches

 CD Sphinx-0.9.8-rc2 
 Patch-p1 <. /sphinx-0.98rc2.zhcn-support.patch 
 Patch-p1 <. /fix-crash-in-excerpts.patch

After installing these plug-ins and patches, we can configure the Rails application to support Full-text search,

First we copy the vendor/plugins/ultrasphinx/examples/default.base from the Ultrasphinx plugin directory to: config/ultrasphinx/ Default.base, open this file, will be one of the following:

Charset_type = Utf-8 to: Charset_type = Zh_cn.utf-8 to support full-text retrieval of Chinese characters, and add a line below the Charset_type setting:

Charset_dictpath =/home/test/search/lib, this is the path where the Uni.lib dictionary is mentioned above, and then delete all charset_table related settings.

In the Rails application Model code, add full-text Search support:

If you have a Model for Article, which has two properties called Title,body, I want to do a full-text search of these two properties and I can add a line to the ARTICLE.RB:
Listing 18. Using Ultrasphinx

Is_indexed:fields => [' created_at ', ' title ', ' body ']

After this configuration, we can use rake ultrasphinx:configure this command to generate the Sphinx configuration file, which creates a command under Config/ultrasphinx development.conf, this file is the Sphinx configuration file. Use rake ultrasphinx:index This command to create the index. Rake Ultrasphinx:daemon:start and Rake ultrasphinx:daemon:stop correspond to the start and stop of the Sphinx searchd service. Searchd will start a searchd on port 3313 and the search request will be sent to this port for execution. We do a simple test in the console:
Listing 19. Test Full-text Indexing

 Search = (: Class_names => ' Article ') 

After everything is working, we can do a full-text search in the action code.

Using Capistrano for rapid deployment

When you do a Rails deployment, you can update your code directly from SVN or git, run db:migrate to update your database, and then start the server after you do this, and you'll be able to deploy even if you have only one machine, and you'll find it too much trouble. If you need more than one machine to run, you may find that each manual deployment is a nightmare, and you can use the shell script to simplify the deployment process. When developing applications with Rails, you can use the Capistrano plug-in for simpler deployments. In simple terms, Capistrano is a tool that executes the same command on multiple machines in parallel via SSH, and is used to install a whole batch of machines. It simplifies the deployment process through an existing and user-customized task.
Listing 20. Install Capistrano

 Gem sources-a 
 gem install Capistrano

Then configure the address of the server to be deployed in CONFIG/DEPLOY.RB, the roles of the various servers, and the unified username and password for each server, as in the following sample configuration:
Listing 21. Configure Capistrano

 Set:application, "Test_app" # application name
 set:scm_username, "test"  # repository username
 set:scm_password, ' Test '  # Resource pool password
 set:repository, {"--username #{scm_username} 
 --password #{scm_password} svn://localhost/" Test_app/trunk "}  
 # repository
 set:user," test "  # server SSH username
 set:p assword, ' Test ' # server SSH password
 set:d E Ploy_to,    "/var/www/#{application}" 
 # The deployment path on the server, the default deployment path is/u/apps/#{application} 
 role:web, ' ' # front-end Web server
 role:app, ' ', ' ', ' ' #Rails Application Server Role
 :d B, ' ',:p rimary => true 
 # A machine that runs migrate scripts, usually one of the application servers.

When you deploy with Capistrano, you typically use the CAP Sometask to run the task. You can use Cap-h to view all the options and see all of the existing tasks with CAP-T. For example, the CAP migrate executes the rake db:migrate command on a machine with role db. For more information on using Capistrano, refer to the website. In addition, Capistrano can also use automatic deployment in non-Rails environments, after configuring the Ruby environment and Capistrano Plug-ins, then installing the following plugins:
Listing 22. Non-Rails environment uses Capistrano

 Gem sources-a 
 gem install Leehambley-railsless-deploy


This article focuses on some useful practical practices for developing and deploying WEB applications using Ruby on Rails, without specifically addressing the common problems that common applications face, such as database optimization and distributed deployment, which is a problem that a large concurrent WEB application needs to face and solve, For example, you can deploy a distributed database in a master-slave way, or split the database in a split-or-table manner. Also, when running rails servers or other back-end applications, monitoring with a different process, such as using God to monitor the rails process, is a strategy that rails applications typically use. In addition, many times, more agile and lightweight Rack can be used instead of Rails to provide services for more efficient development. And the emergence of such rails network providers as Engineyard, Joyent, and Heroku is also a considerable measure of confidence in the development and deployment of large, large-scale concurrent Web applications with rails. While Ruby on Rails is inherently flawed, it's not impossible to develop scalable, high-performance applications. This article hopes to help Rails developers quickly grasp some concrete practices that can be written out and deployed with highly scalable Web applications.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.