As a ruby on rails developer, I also think about the performance and availability dimensions of system. We know that the blue green deployment help us this problem. But we don’t really need a complex kind of this deployment. It also costs us more money because we have to build more environment to switch when deploying. As a cloud engineer, a system manager, we always want to reduce the cost for our company.
Puma is a webserver. To minimize downtime when restarting Puma, you can implement a rolling restart strategy. A rolling restart involves restarting each worker process individually, allowing your application to continue serving requests while the restart is in progress. Here’s how you can implement a rolling restart for Puma:
Here we create puma_control.service
[Unit]
Description=Puma HTTP Server
After=network.target
[Service]
Type=simple
WorkingDirectory=/var/www/mpa-digital-bunkering/current
Environment="JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64"
Environment="RAILS_ENV=staging"
#This is normal Puma Config with downtime
#ExecStart=/home/ubuntu/.rbenv/shims/bundle exec puma -C /var/www/mpa-digital-bunkering/shared/puma.rb
#Zero downtime with Rolling Restart
#First, start puma with control server
ExecStart=/home/ubuntu/.rbenv/shims/bundle exec puma -C /var/www/mpa-digital-bunkering/shared/puma.rb --control 'tcp://127.0.0.1:9293'
Restart=always
[Install]
WantedBy=multi-user.target
Here we create puma.service
[Unit]
Description=Puma HTTP Server
After=network.target
[Service]
Type=simple
WorkingDirectory=/var/www/mpa-digital-bunkering/current
Environment="JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64"
Environment="RAILS_ENV=staging"
#Second, restart with control server
ExecStart=/home/ubuntu/.rbenv/shims/bundle exec pumactl --control-url 'tcp://127.0.0.1:9293' -S /var/www/mpa-digital-bunkering/shared/tmp/pids/puma.state phased-restart
Restart=always
[Install]
WantedBy=multi-user.target
First, we start (init) puma with a control server localhost, port 9293. Don’t forget to use absolute path behind -C.
ExecStart=/home/ubuntu/.rbenv/shims/bundle exec puma -C /var/www/xxx/shared/puma.rb --control 'tcp://127.0.0.1:9293'
Second, we use pumactl to restart. phased-restart tells puma to restart the worker one by one.
ExecStart=/home/ubuntu/.rbenv/shims/bundle exec pumactl --control-url 'tcp://127.0.0.1:9293' -S /var/www/mpa-digital-bunkering/shared/tmp/pids/puma.state phased-restart
How to run? We “start” puma_control service first. Next time, we “restart” puma service only. Can configure capistrano to “restart” puma service.
All these configs we do in linux service. Nothing changed in puma.rb. But don’t forget to configure the number of workers for puma which is larger than 1. How can it do rolling if only 1 cpu – 1 worker? Thus, our system has at least 2 cpu.