@@ -321,6 +321,73 @@ $ sudoedit /etc/php/8.4/cli/php.ini
321
321
+ memory_limit = -1
322
322
```
323
323
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
+
324
391
### Systemd
325
392
326
393
So far, we're manually executing the application server on the command line and
@@ -355,6 +422,7 @@ Description=ACME server
355
422
[Service]
356
423
ExecStart=/usr/bin/php /home/alice/projects/acme/public/index.php
357
424
User=alice
425
+ LimitNOFILE=100000
358
426
359
427
[Install]
360
428
WantedBy=multi-user.target
@@ -625,7 +693,7 @@ Once the Docker image is built, you can run a Docker container from this image:
625
693
=== "Detached container in background"
626
694
627
695
```bash
628
- $ docker run -d -p 8080:8080 acme
696
+ $ docker run -d --ulimit nofile=100000 - p 8080:8080 acme
629
697
```
630
698
631
699
Once running, you can check your web application responds as expected. Use your
0 commit comments