Skip to content

Commit 8528c9e

Browse files
committed
Documentation for FD limits
1 parent 9b3a8e6 commit 8528c9e

File tree

1 file changed

+69
-1
lines changed

1 file changed

+69
-1
lines changed

docs/best-practices/deployment.md

+69-1
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,73 @@ $ sudoedit /etc/php/8.4/cli/php.ini
321321
+ memory_limit = -1
322322
```
323323

324+
### FD limits
325+
326+
By default, many systems limit the number of file descriptors (FDs) that a
327+
single process can have open at once to 1024, and following the Unix philosophy
328+
that "everything is a file", this also includes network connections. This limit
329+
is usually more than enough for most simple use cases, but if you're running a
330+
high-concurrency server, you may want to handle more connections simultaneously.
331+
No problem – Framework X has you covered.
332+
333+
The `ulimit` command (or its equivalent in your system's service management tool,
334+
like [systemd](#systemd) or [Docker](#docker-containers) flags) allows you to
335+
set soft and hard limits for the maximum number of open files. Increasing these
336+
limits will enable your application to support more concurrent connections:
337+
338+
```bash
339+
ulimit -n 100000
340+
```
341+
342+
Additionally, the default [event loop implementation](https://github.com/reactphp/event-loop#loop-implementations)
343+
in Framework X uses the `select()` system call, which is also limited to 1024
344+
file descriptors on most systems (`PHP_FD_SETSIZE` constant). If you want to use a
345+
higher limit, you need to install one of the supported event loop extensions
346+
from PECL:
347+
348+
* [`ext-ev`](https://pecl.php.net/package/ev) (recommended)
349+
* [`ext-event`](https://pecl.php.net/package/event)
350+
* [`ext-uv`](https://pecl.php.net/package/uv) (beta)
351+
352+
Besides your `ulimit` setting, no further configuration is required – these
353+
extensions will automatically be loaded when available. So, whether your
354+
application needs to handle hundreds or even millions of connections
355+
([C10k problem](https://en.wikipedia.org/wiki/C10k_problem)), Framework X has
356+
you covered.
357+
358+
> **Avoiding misconfigurations**
359+
>
360+
> Make sure to adjust the `ulimit` setting according to your specific needs. If
361+
> you create an outgoing connection for each request (think building a proxy
362+
> server or using isolated database connections), you may temporarily require
363+
> two FDs per request. On the other hand, simple applications may get pretty far
364+
> with just the defaults.
365+
>
366+
> As soon as a file or connection is closed, its FD will become available again
367+
> for future use. Accordingly, many lower-concurrency applications may never hit
368+
> the limit. If you do hit the limit, any operation that opens new files or
369+
> connections may fail with an error message like this:
370+
>
371+
> ```
372+
> Connection to tcp://127.0.0.1:3309 failed: Too many open files (EMFILE)
373+
> ```
374+
>
375+
> If you increase the `ulimit` setting, but fail to install one of the supported
376+
> event loop extensions, your server log may be flooded with the following
377+
> warning because the event loop would fail repeatedly:
378+
>
379+
> ```
380+
> stream_select(): You MUST recompile PHP with a larger value of FD_SETSIZE.
381+
> It is set to 1024, but you have descriptors numbered at least as high as 2048.
382+
> --enable-fd-setsize=2048 is recommended, but you may want to set it
383+
> to equal the maximum number of open files supported by your system,
384+
> in order to avoid seeing this error again at a later date.
385+
> ```
386+
>
387+
> If your system is seeing 100% CPU usage for no apparent reasons, this may be
388+
> the reason why. Follow the instructions above or follow the best practices for
389+
> [Docker](#docker-containers) below.
390+
324391
### Systemd
325392
326393
So far, we're manually executing the application server on the command line and
@@ -355,6 +422,7 @@ Description=ACME server
355422
[Service]
356423
ExecStart=/usr/bin/php /home/alice/projects/acme/public/index.php
357424
User=alice
425+
LimitNOFILE=100000
358426
359427
[Install]
360428
WantedBy=multi-user.target
@@ -625,7 +693,7 @@ Once the Docker image is built, you can run a Docker container from this image:
625693
=== "Detached container in background"
626694

627695
```bash
628-
$ docker run -d -p 8080:8080 acme
696+
$ docker run -d --ulimit nofile=100000 -p 8080:8080 acme
629697
```
630698

631699
Once running, you can check your web application responds as expected. Use your

0 commit comments

Comments
 (0)