简体   繁体   中英

How does Passenger Nginx handle concurrent requests

I was trying to understand how Passenger Nginx handles concurrent requests. I reloaded a page and looked at the production log. Each time the page'll send several simultaneous ajax requests to the server. There are some quests that require expensive db queries, referred as 'statuses', 'mentorship_templates' and 'mentorships'. Two attempts seem gave me different results by analyzing the logs.

The first attempt gave me the log like:

Started GET "/admin/mentorships" for 162.213.96.35 at 2014-12-09 08:13:07 +0800
Processing by Admin::MentorshipsController#index as HTML
Completed 200 OK in 351ms (Views: 190.9ms | ActiveRecord: 148.0ms)

Started GET "/admin/task_templates/?with_types=true" for 162.213.96.35 at 2014-12-09 08:13:09 +0800
Started GET "/admin/statuses/?with_stages=true" for 162.213.96.35 at 2014-12-09 08:13:09 +0800
Started GET "/admin/mentorship_task_rules/" for 162.213.96.35 at 2014-12-09 08:13:09 +0800
Started GET "/admin/mentorship_templates/" for 162.213.96.35 at 2014-12-09 08:13:09 +0800 
Started GET "/admin/substages/" for 162.213.96.35 at 2014-12-09 08:13:09 +0800

Processing by Admin::TaskTemplatesController#index as HTML
  Parameters: {"with_types"=>"true"}
Processing by Admin::MentorshipTaskRulesController#index as HTML
Processing by Admin::StatusesController#index as HTML            [expensive db query]
  Parameters: {"with_stages"=>"true"}
Processing by Admin::MentorshipTemplatesController#index as HTML [expensive db query]
Processing by Admin::SubstagesController#index as HTML

Completed 200 OK in 308ms (Views: 0.5ms | ActiveRecord: 296.2ms)
Completed 200 OK in 391ms (Views: 155.6ms | ActiveRecord: 215.7ms)
Completed 200 OK in 429ms (Views: 3.4ms | ActiveRecord: 399.6ms)

Started GET "/admin/mentorships.json" for 162.213.96.35 at 2014-12-09 08:13:10 +0800
Started GET "/major_aliases/list_for_typeahead" for 162.213.96.35 at 2014-12-09 08:13:10 +0800

Processing by MajorAliasesController#list_for_typeahead as HTML
Processing by Admin::MentorshipsController#index as JSON        [expensive db query]

Started GET "/institutes_aliases/list_for_typeahead" for 162.213.96.35 at 2014-12-09 08:13:10 +0800
Started GET "/admin/applicants/list_for_typeahead" for 162.213.96.35 at 2014-12-09 08:13:10 +0800

Processing by InstitutesAliasesController#list_for_typeahead as HTML
Processing by Admin::ApplicantsController#list_for_typeahead as HTML

Read fragment views/palmdrive.cn/institutes_aliases/list_for_typeahead (0.5ms)
Completed 200 OK in 214ms (ActiveRecord: 39.1ms)
Completed 200 OK in 370ms (Views: 14.2ms | ActiveRecord: 174.2ms)

Started GET "/admin/advisors/list_for_ajax" for 162.213.96.35 at 2014-12-09 08:13:10 +0800

Processing by Admin::AdvisorsController#list_for_ajax as HTML

Completed 200 OK in 882ms (Views: 345.8ms | ActiveRecord: 198.8ms)
Completed 200 OK in 383ms (Views: 65.9ms | ActiveRecord: 84.4ms)
Completed 200 OK in 5166ms (Views: 79.2ms | ActiveRecord: 4544.3ms)    [statuses]
Completed 200 OK in 9193ms (Views: 670.0ms | ActiveRecord: 6973.8ms)   [mentorship_templates]
Completed 200 OK in 16588ms (Views: 113.8ms | ActiveRecord: 13952.2ms) [mentorships]

Here I can see that the requests processed concurrently. The expensive db queries didn't block the rest of requests.

After a while I tried another time and got the log:

Started GET "/admin/mentorships" for 162.213.96.35 at 2014-12-09 08:44:25 +0800
Processing by Admin::MentorshipsController#index as HTML
Completed 200 OK in 206ms (Views: 61.0ms | ActiveRecord: 128.7ms)

Started GET "/admin/task_templates/?with_types=true" for 162.213.96.35 at 2014-12-09 08:44:27 +0800
Processing by Admin::TaskTemplatesController#index as HTML
  Parameters: {"with_types"=>"true"}
Completed 200 OK in 263ms (Views: 59.6ms | ActiveRecord: 172.0ms)

Started GET "/admin/mentorship_task_rules/" for 162.213.96.35 at 2014-12-09 08:44:28 +0800
Processing by Admin::MentorshipTaskRulesController#index as HTML
Completed 200 OK in 169ms (Views: 0.9ms | ActiveRecord: 156.2ms)

Started GET "/admin/mentorship_templates/" for 162.213.96.35 at 2014-12-09 08:44:28 +0800
Processing by Admin::MentorshipTemplatesController#index as HTML
Completed 200 OK in 7759ms (Views: 732.5ms | ActiveRecord: 5539.6ms)   [mentorship_templates]

Started GET "/admin/substages/" for 162.213.96.35 at 2014-12-09 08:44:36 +0800  [blocked by the previous one]
Processing by Admin::SubstagesController#index as HTML
Completed 200 OK in 137ms (Views: 3.3ms | ActiveRecord: 126.2ms)
Started GET "/admin/statuses/?with_stages=true" for 162.213.96.35 at 2014-12-09 08:44:36 +0800
Processing by Admin::StatusesController#index as HTML
  Parameters: {"with_stages"=>"true"}
Connecting to database specified by database.yml      [didn't see this in the previous log]
Completed 200 OK in 6167ms (Views: 275.2ms | ActiveRecord: 5377.1ms)  [statuses]

Started GET "/admin/mentorships.json" for 162.213.96.35 at 2014-12-09 08:44:43 +0800 [blocked by the previous one]
Processing by Admin::MentorshipsController#index as JSON

Started GET "/major_aliases/list_for_typeahead" for 162.213.96.35 at 2014-12-09 08:44:48 +0800 [5 seconds delay. although the previous one didn't complete yet]
Started GET "/institutes_aliases/list_for_typeahead" for 162.213.96.35 at 2014-12-09 08:44:48 +0800
Started GET "/admin/applicants/list_for_typeahead" for 162.213.96.35 at 2014-12-09 08:44:48 +0800
Started GET "/admin/advisors/list_for_ajax" for 162.213.96.35 at 2014-12-09 08:44:49 +0800
Processing by MajorAliasesController#list_for_typeahead as HTML
Processing by InstitutesAliasesController#list_for_typeahead as HTML
Processing by Admin::ApplicantsController#list_for_typeahead as HTML
Processing by Admin::AdvisorsController#list_for_ajax as HTML

Read fragment views/palmdrive.cn/institutes_aliases/list_for_typeahead (0.6ms)
Completed 200 OK in 987ms (ActiveRecord: 183.7ms)
Completed 200 OK in 1716ms (Views: 15.2ms | ActiveRecord: 282.6ms)
Completed 200 OK in 1351ms (Views: 200.4ms | ActiveRecord: 269.5ms)
Completed 200 OK in 1938ms (Views: 342.7ms | ActiveRecord: 388.6ms) 
Completed 200 OK in 15694ms (Views: 286.0ms | ActiveRecord: 12694.9ms) [mentorships]

Looks like the expensive db was blocking the server to process other requests. That confuses me!

It is a rails app and using Passenger Nginx as production server and the database is mysql. I wonder what is the good explanation for this. How does the Passenger Nginx handle concurrent requests?

Passenger (in its opensource version version) is not using multithreading. Concurrency is being handled by starting a number of processes. Your requests can be served by any of the running processes. If your requests are all handled by the same process, they will block eachother. Say you have two passenger processes, chance is 50% that thay will be handled by the same process.

To improve performance:

  • Run more processes to lower the chance of requests blocking eachother

  • Get Passenger Enterprise and enable multithreading which will give higher performance

You might also want to check: https://www.phusionpassenger.com/documentation/Users%20guide%20Nginx.html#PassengerConcurrencyModel

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM