Some application servers (e.g. Ruby's Puma) halt progress when dealing with network I/O. Heroku's Cedar routing stack buffers only the headers of inbound requests. (The Cedar router will buffer the headers and body of a response up to 1MB) Thus, the Heroku router engages the dyno during the entire body transfer –from the client to dyno. For applications servers with blocking I/O, the latency per request will be degraded by the content transfer. By using NGINX in front of the application server, we can eliminate a great deal of transfer time from the application server. In addition to making request body transfers more efficient, all other I/O should be improved since the application server need only communicate with a UNIX socket on localhost. Basically, for webservers that are not designed for efficient, non-blocking I/O, we will benefit from having NGINX to handle all I/O operations.
/tmp/app-initializedwhen you are ready for traffic.
NGINX will output the following style of logs:
You can correlate this id with your Heroku router logs:
at=info method=GET path=/ host=salty-earth-7125.herokuapp.com request_id=e2c79e86b3260b9c703756ec93f8a66d fwd="22.214.171.124" dyno=web.1 connect=1ms service=8ms status=200 bytes=21
nginx-buildpack provides a command named
bin/start-nginx this command takes another command as an argument. You must pass your app server's startup command to
For example, to get NGINX and Puma up and running:
$ cat Procfile web: bin/start-nginx bundle exec puma -c config/puma.rb
You can configure NGINX's
worker_processes directive via the
NGINX_WORKERS environment variable.
For example, to set your
NGINX_WORKERS to 8 on a PX dyno:
$ heroku config:set NGINX_WORKERS=8
You can provide your own NGINX config by creating a file named
nginx.conf.erb in the config directory of your app. Start by copying the buildpack's default config file.
See scripts/build_nginx for the build steps. Configuring is as easy as changing the "./configure" options.
You can run the builds in a Docker container:
$ make build # It outputs the latest builds to bin/cedar-*
The buildpack will not start NGINX until a file has been written to
/tmp/app-initialized. Since NGINX binds to the dyno's $PORT and since the $PORT determines if the app can receive traffic, you can delay NGINX accepting traffic until your application is ready to handle it. The examples below show how/when you should write the file when working with Puma.
Update Buildpacks to use the latest stable version of this buildpack:
$ heroku buildpacks:add https://github.com/CareerFoundry/heroku-buildpack-nginx-pagespeed
web: bin/start-nginx bundle exec puma -c config/puma.rb
$ git add Procfile $ git commit -m 'Update procfile for NGINX buildpack'
Update Puma Config
workers Integer(ENV["WEB_CONCURRENCY"] || 2) threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 4) threads threads_count, threads_count rackup DefaultRackup bind "unix:///tmp/nginx.socket" environment ENV['RACK_ENV'] || 'development' preload_app! on_worker_fork do FileUtils.touch('/tmp/app-initialized') end
Push Heroku App:
$ git push heroku master $ heroku logs -t
$ heroku open
Copy the snippet above into CLI.