Skip to content

Commit

Permalink
add new example APCu Caching
Browse files Browse the repository at this point in the history
Signed-off-by: Demin Yin <[email protected]>
  • Loading branch information
deminy committed Mar 6, 2024
1 parent d392e2b commit 0dda90b
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 5 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion dockerfiles/client/Dockerfile
Original file line number Diff line number Diff line change
@@ -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

Expand Down
9 changes: 7 additions & 2 deletions dockerfiles/server/Dockerfile
Original file line number Diff line number Diff line change
@@ -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/*
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion examples/pool/process-pool/pool-standalone.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
Expand Down
56 changes: 56 additions & 0 deletions examples/servers/apcu-caching.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env php
<?php

declare(strict_types=1);

/**
* In this example we use APCu to count number of HTTP requests processed by each worker process in Swoole. From this
* example, we can see that APCu caching in Swoole works the same way as in other PHP CLI applications, even when
* multiple coroutines and multiple processes are involved.
*
* Here is how to run this example:
* 1. First, let's make 499 HTTP requests to the server concurrently:
* docker compose exec -t client ab -n 499 -c 499 http://server:9513/
* With the above command, we make 499 HTTP requests to the server concurrently. The server uses APCu to store the
* number of HTTP requests processed by each worker process.
* 2. Next, let's check the summary of all counters by making another HTTP request to the server:
* docker compose exec -t client curl http://server:9513/summary
* The server has 3 worker processes to process these requests. Hopefully we can see that each worker process
* processes different number of HTTP requests.
*/

use Swoole\Constant;
use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\Http\Server;

apcu_clear_cache(); // Clear APCu caches.

$server = new Server('0.0.0.0', 9513);
$server->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();

0 comments on commit 0dda90b

Please sign in to comment.