diff --git a/README.md b/README.md index 3baecee..588be7e 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,8 @@ docker compose exec -ti client bash # Get a Bash shell in the client container. * [UDP client](https://github.com/deminy/swoole-by-examples/blob/master/examples/clients/udp.php) * [PostgreSQL client](https://github.com/deminy/swoole-by-examples/blob/master/examples/clients/postgresql.php) * miscellaneous topics + * data management in Swoole: globals, persistence, and caching + * [APCu Caching]: APCu caching in Swoole works the same way as in other PHP CLI applications. This example explains it in details. * atomic counters * [implement atomic counters using unsigned 32-bit integers](https://github.com/deminy/swoole-by-examples/blob/master/examples/misc/atomic-counter-unsigned-32-bit.php) * [implement atomic counters using signed 64-bit integers](https://github.com/deminy/swoole-by-examples/blob/master/examples/misc/atomic-counter-signed-64-bit.php) @@ -144,3 +146,5 @@ docker compose exec -ti client bash # Get a Bash shell in the client container. * process pool * pool creation and inter-process communication: Please check previous section `resource pooling` for details. * detach processes from a process pool + +[APCu Caching]: https://github.com/deminy/swoole-by-examples/blob/master/examples/servers/apcu-caching.php diff --git a/docker-compose.yml b/docker-compose.yml index 2bd01b0..3de2d75 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,7 +4,7 @@ services: server: image: deminy/swoole-by-examples:server-5.1 environment: - AUTORELOAD_PROGRAMS: "ddos-protection http1 http1-integrated http2 interruptible-sleep keepalive mixed-protocols-1 pool-msgqueue pool-tcp-socket pool-unix-socket redis rock-paper-scissors tcp1 tcp2 udp websocket websocket-integrated" + AUTORELOAD_PROGRAMS: "apcu-caching ddos-protection http1 http1-integrated http2 interruptible-sleep keepalive mixed-protocols-1 pool-msgqueue pool-tcp-socket pool-unix-socket redis rock-paper-scissors tcp1 tcp2 udp websocket websocket-integrated" DISABLE_DEFAULT_SERVER: 1 ports: - 9801:9801 diff --git a/dockerfiles/client/Dockerfile b/dockerfiles/client/Dockerfile index fcac5ab..f277141 100644 --- a/dockerfiles/client/Dockerfile +++ b/dockerfiles/client/Dockerfile @@ -1,4 +1,4 @@ -# This Dockerfile is to build Docker image "deminy/swoole-by-examples:client". +# This Dockerfile is to build Docker image "deminy/swoole-by-examples:client-5.1". # @see https://hub.docker.com/r/deminy/swoole-by-examples FROM phpswoole/swoole:5.1-php8.2 diff --git a/dockerfiles/server/Dockerfile b/dockerfiles/server/Dockerfile index e490d91..0ffc0e3 100644 --- a/dockerfiles/server/Dockerfile +++ b/dockerfiles/server/Dockerfile @@ -1,13 +1,18 @@ -# This Dockerfile is to build Docker image "deminy/swoole-by-examples:server". +# This Dockerfile is to build Docker image "deminy/swoole-by-examples:server-5.1". # @see https://hub.docker.com/r/deminy/swoole-by-examples FROM phpswoole/swoole:5.1-php8.2 COPY ./rootfilesystem / -# The System V messages support is to run some example in script "./examples/pool/process-pool/client.php". +# 1. The System V messages support is to run the example from script "./examples/pool/process-pool/client.php". +# 2. The APCu extension is to run the example from script "./examples/servers/apcu-caching.php". RUN \ set -ex && \ docker-php-ext-install sysvmsg && \ + pecl channel-update pecl && \ + pecl install apcu-stable && \ + docker-php-ext-enable apcu && \ + echo "apc.enable_cli=1" >> $(php-config --ini-dir)/docker-php-ext-apcu.ini && \ apt-get update && \ apt-get install -y net-tools watch --no-install-recommends && \ rm -rf /var/lib/apt/lists/* diff --git a/dockerfiles/server/rootfilesystem/etc/supervisor/service.d/apcu-caching.conf b/dockerfiles/server/rootfilesystem/etc/supervisor/service.d/apcu-caching.conf new file mode 100644 index 0000000..ef70d18 --- /dev/null +++ b/dockerfiles/server/rootfilesystem/etc/supervisor/service.d/apcu-caching.conf @@ -0,0 +1,12 @@ +[supervisord] +user = root + +[program:apcu-caching] +command = /var/www/servers/apcu-caching.php +user = root +autostart = true +autorestart = true +stdout_logfile=/proc/self/fd/1 +stdout_logfile_maxbytes=0 +stderr_logfile=/proc/self/fd/1 +stderr_logfile_maxbytes=0 diff --git a/examples/pool/process-pool/pool-standalone.php b/examples/pool/process-pool/pool-standalone.php index f109e46..b156ff8 100755 --- a/examples/pool/process-pool/pool-standalone.php +++ b/examples/pool/process-pool/pool-standalone.php @@ -21,7 +21,7 @@ $counter = new Atomic(0); $pool->on('workerStart', function (Pool $pool, int $workerId) use ($counter) { - # For standalone process pool, business logic should be implemented inside this "workerStart" callback. + // For standalone process pool, business logic should be implemented inside this "workerStart" callback. echo "Process #{$workerId} (process ID in the OS: {$pool->getProcess()->pid}) started.", PHP_EOL; // @phpstan-ignore property.nonObject $counter->add(1); }); diff --git a/examples/servers/apcu-caching.php b/examples/servers/apcu-caching.php new file mode 100755 index 0000000..06b5591 --- /dev/null +++ b/examples/servers/apcu-caching.php @@ -0,0 +1,56 @@ +#!/usr/bin/env php +set( + [ + Constant::OPTION_WORKER_NUM => 3, // The number of worker processes to process HTTP requests. + ] +); + +$server->on( + 'request', + function (Request $request, Response $response) use ($server): void { + if ($request->server['request_uri'] === '/summary') { // Show summary of all counters. + $output = ''; + foreach (apcu_cache_info()['cache_list'] as $item) { // @phpstan-ignore foreach.nonIterable + $output .= "{$item['info']}: " . apcu_fetch($item['info']) . PHP_EOL; // @phpstan-ignore-line + } + // The output will be like: + // counter_0: 46 + // counter_1: 16 + // counter_2: 437 + $response->end($output); + } else { // Increase a counter. + apcu_inc("counter_{$server->worker_id}"); + $response->end('OK' . PHP_EOL); + } + } +); + +$server->start();