Forked from mhsamiei/gonicorn_nginx_django.md
Created
September 26, 2024 13:44
Revisions
-
mhsamiei revised this gist
Aug 2, 2020 . 1 changed file with 10 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -44,14 +44,23 @@ Group=www-data WorkingDirectory=/home/sammy/myprojectdir ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn \ --access-logfile - \ --workers 40 \ --threads=3 \ --worker-connections=10000 \ --bind unix:/run/gunicorn.sock \ myproject.wsgi:application [Install] WantedBy=multi-user.target ``` ``` The suggested maximum concurrent requests when using workers and threads is still(2*CPU)+1. So if we are using a quad-core (4 CPU) machine and we want to use a mix of workers and threads, we could use 3 workers and 3 threads, to get 9 maximum concurrent requests. gunicorn --workers=3 --threads=3 main:app ``` With that, our systemd service file is complete. Save and close it now. We can now start and enable the Gunicorn socket. This will create the socket file at `/run/gunicorn.sock` now and at boot. When a connection is made to that socket, systemd will automatically start the `gunicorn.service` to handle it: -
mhsamiei renamed this gist
Aug 2, 2020 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
mhsamiei created this gist
Aug 2, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,190 @@ **Testing Gunicorn**’s Ability to Serve the Project The last thing we want to do before leaving our virtual environment is test Gunicorn to make sure that it can serve the application. We can do this by entering our project directory and using gunicorn to load the project’s WSGI module: ``` (myenv) $ cd ~/myprojectdir (myenv) $ gunicorn --bind 0.0.0.0:8000 myproject.wsgi ``` **Creating systemd Socket and Service Files for Gunicorn** We have tested that Gunicorn can interact with our Django application, but we should implement a more robust way of starting and stopping the application server. To accomplish this, we’ll make systemd service and socket files. The Gunicorn socket will be created at boot and will listen for connections. When a connection occurs, systemd will automatically start the Gunicorn process to handle the connection. Start by creating and opening a systemd socket file for Gunicorn with sudo privileges: _sudo nano /etc/systemd/system/gunicorn.socket_ ``` [Unit] Description=gunicorn socket [Socket] ListenStream=/run/gunicorn.sock [Install] WantedBy=sockets.target ``` Inside, we will create a `[Unit]` section to describe the socket, a` [Socket]` section to define the socket location, and an `[Install]` section to make sure the socket is created at the right time: **Next**, create and open a systemd service file for Gunicorn with sudo privileges in your text editor. The service filename should match the socket filename with the exception of the extension: _sudo nano /etc/systemd/system/gunicorn.service_ Start with the [Unit] section, which is used to specify metadata and dependencies. We’ll put a description of our service here and tell the init system to only start this after the networking target has been reached. Because our service relies on the socket from the socket file, we need to include a Requires directive to indicate that relationship: ``` [Unit] Description=gunicorn daemon Requires=gunicorn.socket After=network.target [Service] User=sammy Group=www-data WorkingDirectory=/home/sammy/myprojectdir ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn \ --access-logfile - \ --workers 3 \ --bind unix:/run/gunicorn.sock \ myproject.wsgi:application [Install] WantedBy=multi-user.target ``` With that, our systemd service file is complete. Save and close it now. We can now start and enable the Gunicorn socket. This will create the socket file at `/run/gunicorn.sock` now and at boot. When a connection is made to that socket, systemd will automatically start the `gunicorn.service` to handle it: sudo systemctl start gunicorn.socket sudo systemctl enable gunicorn.socket **Checking for the Gunicorn Socket File** Check the status of the process to find out whether it was able to start: `sudo systemctl status gunicorn.socket` Next, check for the existence of the gunicorn.sock file within the /run directory: file /run/gunicorn.sock Output /run/gunicorn.sock: socket If the systemctl status command indicated that an error occurred or if you do not find the gunicorn.sock file in the directory, it’s an indication that the Gunicorn socket was not able to be created correctly. Check the Gunicorn socket’s logs by typing: sudo journalctl -u gunicorn.socket Take another look at your /etc/systemd/system/gunicorn.socket file to fix any problems before continuing. **Testing Socket Activation** Currently, if you’ve only started the gunicorn.socket unit, the gunicorn.service will not be active yet since the socket has not yet received any connections. You can check this by typing: sudo systemctl status gunicorn Output ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: inactive (dead) To test the socket activation mechanism, we can send a connection to the socket through curl by typing: curl --unix-socket /run/gunicorn.sock localhost You should see the HTML output from your application in the terminal. This indicates that Gunicorn was started and was able to serve your Django application. You can verify that the Gunicorn service is running by typing: sudo systemctl status gunicorn Output ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: active (running) since Mon 2018-07-09 20:00:40 UTC; 4s ago Main PID: 1157 (gunicorn) Tasks: 4 (limit: 1153) CGroup: /system.slice/gunicorn.service ├─1157 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application ├─1178 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application ├─1180 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application └─1181 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application Jul 09 20:00:40 django1 systemd[1]: Started gunicorn daemon. Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1157] [INFO] Starting gunicorn 19.9.0 Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1157] [INFO] Listening at: unix:/run/gunicorn.sock (1157) Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1157] [INFO] Using worker: sync Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1178] [INFO] Booting worker with pid: 1178 Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1180] [INFO] Booting worker with pid: 1180 Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1181] [INFO] Booting worker with pid: 1181 Jul 09 20:00:41 django1 gunicorn[1157]: - - [09/Jul/2018:20:00:41 +0000] "GET / HTTP/1.1" 200 16348 "-" "curl/7.58.0" If the output from curl or the output of systemctl status indicates that a problem occurred, check the logs for additional details: sudo journalctl -u gunicorn Check your /etc/systemd/system/gunicorn.service file for problems. If you make changes to the /etc/systemd/system/gunicorn.service file, reload the daemon to reread the service definition and restart the Gunicorn process by typing: sudo systemctl daemon-reload sudo systemctl restart gunicorn Make sure you troubleshoot the above issues before continuing. **Configure Nginx to Proxy Pass to Gunicorn** Now that Gunicorn is set up, we need to configure Nginx to pass traffic to the process. Start by creating and opening a new server block in Nginx’s sites-available directory: ` sudo nano /etc/nginx/sites-available/myproject` Finally, we’ll create a location / {} block to match all other requests. Inside of this location, we’ll include the standard proxy_params file included with the Nginx installation and then we will pass the traffic directly to the Gunicorn socket: /etc/nginx/sites-available/myproject ``` server { listen 80; server_name server_domain_or_IP; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/sammy/myprojectdir; } location / { include proxy_params; proxy_pass http://unix:/run/gunicorn.sock; } } ``` Save and close the file when you are finished. Now, we can enable the file by linking it to the sites-enabled directory: sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled Test your Nginx configuration for syntax errors by typing: sudo nginx -t If no errors are reported, go ahead and restart Nginx by typing: sudo systemctl restart nginx Finally, we need to open up our firewall to normal traffic on port 80. Since we no longer need access to the development server, we can remove the rule to open port 8000 as well: sudo ufw delete allow 8000 sudo ufw allow 'Nginx Full' You should now be able to go to your server’s domain or IP address to view your application. **Troubleshooting Nginx and Gunicorn** sudo tail -F /var/log/nginx/error.log Check the **Nginx process** logs by typing: sudo journalctl -u nginx Check the **Nginx access** logs by typing: sudo less /var/log/nginx/access.log Check the **Nginx error** logs by typing: sudo less /var/log/nginx/error.log Check the **Gunicorn application** logs by typing: sudo journalctl -u gunicorn Check the **Gunicorn socket** logs by typing: sudo journalctl -u gunicorn.socket If you **update your Django application**, you can restart the Gunicorn process to pick up the changes by typing: `sudo systemctl restart gunicorn` If you **change Gunicorn socket or service files**, reload the daemon and restart the process by typing: ``` sudo systemctl daemon-reload sudo systemctl restart gunicorn.socket gunicorn.service ```