Skip to content

Flight work with Adapterman (Workerman) #613

@joanhey

Description

@joanhey

Is your feature request related to a problem? Please describe.
I'm trying that this framework work with Adapterman, but only work the first URL.
I'm using the Techempower benchmark to test the frameworks with the async event driven Workerman, that it's working with similar frameworks.

Describe the solution you'd like
I want that work when we bootstrap the app only 1 time, not only for Adapterman but for any platform (swoole, php-runtime,...).
Also I can help to have better performance when it's used like a persistent app.

I write here because one user send me a issue to Adapterman: joanhey/AdapterMan#87

Describe alternatives you've considered
As work the first URL call, and only fail the next URL calls, it seems that it's not cleared the routes or other property of the framework.

Additional context
As you run also the Techempower benchmark, i'll send you the files to reproduce.

Actually

flight-workerman: Adapterman v0.6.1 OK
flight-workerman: Workerman[server.php] start in DEBUG mode
flight-workerman: ------------------------------------------- WORKERMAN --------------------------------------------
flight-workerman: Workerman version:4.2.1          PHP version:8.3.14           Event-Loop:\Workerman\Events\Event
flight-workerman: -------------------------------------------- WORKERS ---------------------------------------------
flight-workerman: proto   user            worker               listen                 processes    status           
flight-workerman: tcp     root            AdapterMan-Flight    http://0.0.0.0:8080    32            [OK]            
flight-workerman: --------------------------------------------------------------------------------------------------
flight-workerman: Press Ctrl+C to stop. Start success.
flight-workerman: Verifying framework URLs
--------------------------------------------------------------------------------
VERIFYING DB                                                                                                                                                   
--------------------------------------------------------------------------------
Accessing URL http://tfb-server:8080/db:                                                                                                                       
Accessing URL http://tfb-server:8080/db: 
--------------------------------------------------------------------------------
VERIFYING QUERY COUNT FOR http://tfb-server:8080/db                                                                                                            
--------------------------------------------------------------------------------
New configuration template added to /home/ubuntu/.siege                                                                                                        
Run siege -C to view the current settings in that file
** SIEGE 4.0.7
** Preparing 512 concurrent users for battle.
The server is now under siege...
Transactions:                    512 hits
Availability:                 100.00 %
Elapsed time:                   0.24 secs
Data transferred:               0.00 MB
Response time:                  0.15 secs
Transaction rate:            2133.33 trans/sec
Throughput:                     0.00 MB/sec
Concurrency:                  317.13
Successful transactions:         512
Failed transactions:               0
Longest transaction:            0.22
Shortest transaction:           0.02
 

   PASS for http://tfb-server:8080/db
     Executed queries: 520/512
   PASS for http://tfb-server:8080/db
     Rows read: 511/512
--------------------------------------------------------------------------------
VERIFYING JSON                                                                                                                                                 
--------------------------------------------------------------------------------
Accessing URL http://tfb-server:8080/json:                                                                                                                     
   FAIL for http://tfb-server:8080/json
     Empty response
     See https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#specific-test-requirements
{'Content-Type': 'text/html;charset=utf-8', 'Server': 'workerman', 'Date': 'Mon, 16 Dec 2024 11:54:50 GMT', 'Content-Length': '0'}
--------------------------------------------------------------------------------
VERIFYING QUERY                                                                                                                                                
--------------------------------------------------------------------------------
...

The files that I use:
index.php

<?php
require_once 'vendor/autoload.php';

error_reporting(-1);

Flight::register('db', PDO::class, [ 'mysql:host=tfb-database;port=3306;dbname=hello_world', 'benchmarkdbuser', 'benchmarkdbpass', [ \PDO::ATTR_PERSISTENT => TRUE ] ]);

// JSON test
Flight::route('/json', function() {
	Flight::json(['message' => 'Hello, World!']);
});

// Plaintext test
Flight::route('/plaintext', function() {
	Flight::response()
		->header('Content-Type', 'text/plain')
		->write('Hello, World!')
		->send();
});

// DB test
Flight::route('/db', function() {
	$id = mt_rand(1, 10000);
	$db = Flight::db();
	$stmt = $db->prepare('SELECT * FROM World WHERE id = ?');
    $stmt->execute([ $id ]);
    $world = $stmt->fetch();
    // Cast fields to int so they don't get wrapped with quotes
	$world = [
		'id' => (int) $world['id'],
		'randomNumber' => (int) $world['randomNumber']
	];
	Flight::json($world);
});

// DB multiple test
Flight::route('/db-multiple', function () {
	$queries = Flight::request()->query['queries'];
    if (is_numeric($queries)) {
        $queries = max(1, min($queries, 500));
    } else {
        $queries = 1;
    }

	$db = Flight::db();
	$stmt = $db->prepare('SELECT * FROM World WHERE id = ?');
    $worlds = [];
    for ($i = 0; $i < $queries; ++$i) {
		$random_id = mt_rand(1, 10000);
        $stmt->execute([ $random_id ]);
        $world = $stmt->fetch();
        // Cast fields to int so they don't get wrapped with quotes
        $world = [
			'id' => (int) $world['id'],
			'randomNumber' => (int) $world['randomNumber']
		];
        $worlds[] = $world;
    }
    Flight::json($worlds);
});

// DB Update Test
Flight::route('/updates', function () {
    $queries = Flight::request()->query['queries'];
    if (is_numeric($queries)) {
        $queries = max(1, min($queries, 500));
    } else {
        $queries = 1;
    }

	$db = Flight::db();

    $select_stmt = $db->prepare('SELECT id FROM World WHERE id = ?');
    $update_stmt = $db->prepare('UPDATE World SET randomNumber = ? WHERE id = ?');

    $worlds = [];
    for ($i = 0; $i < $queries; ++$i) {
        $id = mt_rand(1, 10000);
        $random_number = mt_rand(1, 10000);
        $select_stmt->execute([$id]);
        $world = $select_stmt->fetch();
		$world = [
			'id' => (int) $world['id'],
			'randomNumber' => $random_number
		];

        $update_stmt->execute([ $random_number, (int) $world['id'] ]);

        $worlds[] = $world;
    }

	Flight::json($worlds);
});

// Fortunes Test
Flight::route('/fortunes', function() {
	$db = Flight::db();
    $fortunes = $db->query('SELECT * FROM Fortune')->fetchAll(PDO::FETCH_KEY_PAIR);

    $fortunes[0] = 'Additional fortune added at request time.';
    asort($fortunes);

    Flight::render('fortunes.php', [ 'fortunes' => $fortunes ]);
});

//Flight::start() ;

// Workerman
function run()
{
    ob_start();
    Flight::start();
    header(HeaderDate::$date); // To pass the bench, nginx auto add it
    return ob_get_clean();
}

server.php

<?php
require_once __DIR__.'/vendor/autoload.php';

use Adapterman\Adapterman;
use Workerman\Lib\Timer;
use Workerman\Worker;

Adapterman::init();

$http_worker        = new Worker('http://0.0.0.0:8080');
$http_worker->count = (int) shell_exec('nproc') * 4;
$http_worker->name  = 'AdapterMan-Flight';

$http_worker->onWorkerStart = static function () {
    HeaderDate::init();
    require __DIR__.'/index.php';
};

$http_worker->onMessage = static function ($connection) {

    $connection->send(run());
};

Worker::runAll();

class HeaderDate
{
    const NAME = 'Date: ';

    /**
     * Date header
     *
     * @var string
     */
    public static $date;

    public static function init(): void
    {
        self::$date = self::NAME.gmdate('D, d M Y H:i:s').' GMT';
        Timer::add(1, static function () {
            self::$date = self::NAME.gmdate('D, d M Y H:i:s').' GMT';
        });
    }
}

flight-workerman.dockerfile

FROM ubuntu:24.04

ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null
RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php
RUN apt-get update -yqq > /dev/null && \
    apt-get install -yqq nginx git unzip php8.3 php8.3-common php8.3-cli php8.3-fpm php8.3-mysql  > /dev/null

COPY deploy/conf/* /etc/php/8.3/fpm/

WORKDIR /flight
COPY . .

ENV FLIGHT_DIR="/flight/src"

COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer

RUN apt-get install -y php-pear php8.3-dev libevent-dev php8.3-xml > /dev/null
RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.3/cli/conf.d/event.ini

RUN composer require joanhey/adapterman:^0.6
RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet

RUN sed -i "s|Flight::start() ;|//Flight::start() ;|g" index.php

RUN chmod -R 777 /flight

EXPOSE 8080

CMD php -c deploy/conf/cli-php.ini \
    server.php start

It'll be easier for you to find the problem. As the bench don't report any error, only empty response.
I'm at your disposition for any extra info or help.

Thank you.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions