Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

使用workerman加速任意项目 #818

Open
guanhui07 opened this issue Dec 20, 2022 · 2 comments
Open

使用workerman加速任意项目 #818

guanhui07 opened this issue Dec 20, 2022 · 2 comments

Comments

@guanhui07
Copy link
Owner

guanhui07 commented Dec 20, 2022

项目地址
https://github.com/joanhey/AdapterMan

看源码原理:
第一、禁止 php 自带函数的同时编写新的函数。
第二、提供新的启动入口使用workerman,同时把框架的核心加载代码,稍作修
改。这样就完美的接替了 php-fpm 。代码常驻内存,性
能提升还是肉眼可见的。当然这个里面的替换思路还是很有意思的。
第三、装上 event扩展 ,性能提升一个量级 , I/O 通知机制有效地安排基于 I/O、时间和信号的事件, epoll linux内核支持 io多路复用

https://pecl.php.net/package/event
event扩展安装 此处忽略

php.ini 通过 disable_functions 禁用一些函数

disable_functions =header,header_remove,http_response_code,
setcookie,session_create_id,session_id,session_name,
session_save_path,session_status,session_start,
session_write_close,session_regenerate_id,set_time_limit

start.php 启动文件

<?php

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

use Adapterman\Adapterman;
use Workerman\Worker;

Adapterman::init();

$http_worker                = new Worker('http://0.0.0.0:8080');
$http_worker->count         = 8;
$http_worker->name          = 'AdapterMan';

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

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

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

Worker::runAll();

AdapterMan 源码
https://github.com/joanhey/AdapterMan/blob/master/src/AdapterFunctions.php#L10

<?php

use Workerman\Protocols\Http;

/**
 * Send a raw HTTP header
 * 
 * @link https://php.net/manual/en/function.header.php
 */
function header(string $content, bool $replace = true, ?int $http_response_code = null): void
{
    Http::header($content, $replace, $http_response_code);
}

/**
 * Remove previously set headers
 *
 * @param string $name  The header name to be removed. This parameter is case-insensitive.
 * @return void
 * 
 * @link https://php.net/manual/en/function.header-remove.php
 */
function header_remove(string $name): void
{
    Http::headerRemove($name);  //TODO fix case-insensitive
}

/**
 * Get or Set the HTTP response code
 *
 * @param integer $code [optional] The optional response_code will set the response code.
 * @return integer      The current response code. By default the return value is int(200).
 * 
 * @link https://www.php.net/manual/en/function.http-response-code.php
 */
function http_response_code(int $code = null): int
{ // int|bool
    return Http::responseCode($code); // Fix to return actual status when void
}

/**
 * Send a cookie
 *
 * @param string $name
 * @param string $value
 * @param integer $expires
 * @param string $path
 * @param string $domain
 * @param boolean $secure
 * @param boolean $httponly
 * @return boolean
 * 
 * @link https://php.net/manual/en/function.setcookie.php
 */
function setcookie(string $name, string $value = '', int $expires = 0, string $path = '', string $domain = '', bool $secure = FALSE, bool $httponly = FALSE): bool
{
    return Http::setcookie($name, $value, $expires, $path, $domain, $secure, $httponly);
}

function session_create_id(string $prefix = ''): string
{
    return Http::sessionCreateId();  //TODO fix to use $prefix
}

function session_id(string $id = ''): string
{
    return Http::sessionId($id);   //TODO fix return session name or '' if not exists session
}

function session_name(string $name = ''): string
{
    return Http::sessionName($name);
}

function session_save_path(string $path = ''): string
{
    return Http::sessionSavePath($path);
}

function session_status(): int
{
    if (Http::sessionStarted() === false) {
        return PHP_SESSION_NONE;
    }
    return PHP_SESSION_ACTIVE;
}

function session_start(array $options = []): bool
{
    return Http::sessionStart();   //TODO fix $options
}

function session_write_close(): void
{
    Http::sessionWriteClose();
}

/**
 * Update the current session id with a newly generated one
 *
 * @param bool $delete_old_session
 * @return bool
 * 
 * @link https://www.php.net/manual/en/function.session-regenerate-id.php
 */
function session_regenerate_id(bool $delete_old_session = false): bool
{
    return Http::sessionRegenerateId($delete_old_session);
}

function set_time_limit(int $seconds): bool
{
    // Disable set_time_limit to not stop the worker
    // by default CLI sapi use 0 (unlimited)
    return true;
}

/* function exit(string $status = ''): void {  //string|int
    Http::end($status);
} // exit and die are language constructors, change your code with an empty ExitException
 */

把session,cookies等使用封装函数代替了,是个不错的想法,但是不能全部直接移植使用,估计还需要更改一些东西

swoole4 是通过 hook 原生函数的方式去兼容各种库代码

AdapterMan
https://github.com/joanhey/AdapterMan/blob/master/src/Adapterman.php#L39

<?php

namespace Adapterman;

use Exception;

class Adapterman
{
    public const VERSION = "0.5.3";

    public const NAME = "Adapterman v". self::VERSION;
    
    private const FUNCTIONS = ['header', 'header_remove', 'http_response_code', 'setcookie', 'session_create_id', 'session_id', 'session_name', 'session_save_path', 'session_status', 'session_start', 'session_write_close', 'session_regenerate_id', 'set_time_limit'];

    public static function init(): void
    {
        try {
            self::checkVersion();
            self::checkFunctionsDisabled();
            
            // OK initialize the functions
            require __DIR__ . '/AdapterFunctions.php';

        } catch (Exception $e) {
            fwrite(STDERR, self::NAME . ' Error:' . PHP_EOL);
            fwrite(STDERR, $e->getMessage());
            exit;
        }
        
        fwrite(STDOUT, self::NAME . ' OK' . PHP_EOL);
    }

    /**
     * Check PHP version 
     *
     * @throws Exception
     * @return void
     */
    private static function checkVersion(): void
    {
        if (\PHP_MAJOR_VERSION < 8) {
            throw new Exception("* PHP version must be 8 or higher." . PHP_EOL . "* Actual PHP version: " . \PHP_VERSION . PHP_EOL);
        }
    }

    /**
     * Check that functions are disabled in php.ini
     *
     * @throws Exception
     * @return void
     */
    private static function checkFunctionsDisabled(): void
    {
 
        foreach (self::FUNCTIONS as $function) {
            if (\function_exists($function)) {
                throw new Exception("Functions not disabled in php.ini." . PHP_EOL . self::showConfiguration());
            }
        }
    }

    private static function showConfiguration(): string
    {
        $inipath = \php_ini_loaded_file();
        $methods = \implode(',', self::FUNCTIONS);

        return "Add in file: $inipath" . PHP_EOL . "disable_functions=$methods" . PHP_EOL;
    }
}

必须php8以上项目
用上workerman常驻内存 性能能提升一个量级

下图为laravel8 提升,其他项目比如thinkphp lumen Yii2 Slim 等 都可用此项目基础于 workerman 加速。
image

参考
workerman社区
https://www.workerman.net/q/9831

@Tinywan
Copy link

Tinywan commented Jan 2, 2023

厉害

Repository owner deleted a comment Feb 2, 2024
Repository owner deleted a comment Feb 2, 2024
Repository owner deleted a comment from rnoh96 Mar 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants
@guanhui07 @Tinywan and others