Adding 'Sending Shutdown Signals' section.
All checks were successful
Deploy Greenlight API / deploy (push) Successful in 1m2s

This commit is contained in:
Maxime Delporte
2025-11-19 14:39:15 +01:00
parent 83bb7294db
commit f88edf082e

View File

@@ -396,6 +396,72 @@ So, to get around this, we'll need to synchronize access to the map of rate limi
If you're using HAProxy or Nginx as a load balancer or reverse proxy, both of these have built-in functionality for rate limiting that it would probably be sensible to use. Alternatively, you could use a fast database like Redis to maintain a request count for clients, running on a server which all your application servers can communicate with. If you're using HAProxy or Nginx as a load balancer or reverse proxy, both of these have built-in functionality for rate limiting that it would probably be sensible to use. Alternatively, you could use a fast database like Redis to maintain a request count for clients, running on a server which all your application servers can communicate with.
### Sending Shutdown Signals
When our application is running, we can terminate it at any time by sending it a specific signal. A common way to do this, which you've probably been using, is by pressing **Ctrl+C** on your keyboard to send an interrupt signal - also known as a **SIGINT**.
But this isn't the only type of signal which can stop our application. Some of the other common ones are:
| Signal | Description | Keyboard shortcut | Catchable |
|---------|--------------------------------------|-------------------|-----------|
| SIGINT | Interrupt from keyboard | Ctrl + C | Yes |
| SIGQUIT | Quit from keyboard | Ctrl + C | Yes |
| SIGKILL | Kill process (terminate immediately) | - | No |
| SIGTERM | Terminate process in orderly manner | - | Yes |
It's important to explain upfront that some signals are _catchable_ and others are not. Catchable signals can be intercepted by our application and either ignored, or used to trigger a certain action (such as a graceful shutdown). Other signals, like **SIGKILL**, are not catchable and cannot be intercepted.
Let's take a quick look at these signals in action. First, run :
```bash
$ go run ./cmd/api
time=2023-09-10T10:59:13.722+02:00 level=INFO msg="database connection pool established"
time=2023-09-10T10:59:13.722+02:00 level=INFO msg="starting server" addr=:4000 env=development
```
Doing this should start a process with the name **api** on your machine. You can use the pgrep command to verify that this process exists, like so:
```bash
$ pgrep -l api
4414 api
```
In my case, I can see that the **api** process is running and has the _process ID_ **4414** (your process ID will most likely be different).
Once that's confirmed, go ahead and try sending a **SIGKILL** signal to the **api** process using the pkill command like so:
```bash
$ pkill -SIGKILL api
```
If you go back to the terminal window that is running the API application, you should see that it has been terminated and the final line in the output stream is **signal: killed**. Similar to this :
```bash
$ go run ./cmd/api
time=2023-09-10T10:59:13.722+02:00 level=INFO msg="database connection pool established"
time=2023-09-10T10:59:13.722+02:00 level=INFO msg="starting server" addr=:4000 env=development
signal: killed
```
Feel free to repeat the same process, but sending a SIGTERM signal instead:
```bash
$ pkill -SIGTERM api
```
This time, you should see the line **signal: terminated** at the end of the output, like so :
```bash
$ go run ./cmd/api
time=2023-09-10T10:59:13.722+02:00 level=INFO msg="database connection pool established"
time=2023-09-10T10:59:13.722+02:00 level=INFO msg="starting server" addr=:4000 env=development
signal: terminated
```
You can also try sending a **SIGQUIT** signal — either by pressing **Ctrl+\\** on your keyboard or running **pkill -SIGQUIT api**. This will cause the application to exit with a stack dump.
We can see that these signals are effective in terminating our application - but the **problem** we have is that they all cause our application to **exit immediately**.
### Performance ### Performance
**json.MarshalIndent()** takes 65% longer to run and uses around 30% more memory than **json.Marshal()**, as well as making two more heap allocations. Those figures will change depending on what you're encoding, but they're fairly indicative of the performance impact. **json.MarshalIndent()** takes 65% longer to run and uses around 30% more memory than **json.Marshal()**, as well as making two more heap allocations. Those figures will change depending on what you're encoding, but they're fairly indicative of the performance impact.