国产+高潮+在线,国产 av 仑乱内谢,www国产亚洲精品久久,51国产偷自视频区视频,成人午夜精品网站在线观看

使用workerman 壓力測試結(jié)果,很滿意

CiChenMan



Nginx Server 與 WorkerMan Server For PHP 壓測報告
測試要求:
1.相同環(huán)境 (linux debian12)
2.相同配置 (4c 8v 40G)
3.相同輸出內(nèi)容 ({"code":200,"msg":"\u6210\u529f","data":
[{"id":1,"name":"cichenman","age":26,"tip":"\u5185\u5b58\u6570\u636e"}]})
4.內(nèi)網(wǎng)測試 (本地 127.0.0.1)
5.AB 壓測 (參數(shù):50W 請求 1000 并發(fā) 開啟 Keep-Alive)
測試模式:

  1. nginx + 純靜態(tài) 輸出固定文本
  2. nginx + php 輸出固定文本
    3.workerman 輸出固定文本

具體代碼貼在了評論區(qū)

均采用:4 個進程,8G 內(nèi)存,千兆內(nèi)網(wǎng)環(huán)境測試,測試數(shù)據(jù)僅供參考,每種測試模式測試 10 次

1565 15 2
15個評論

six

你這個壓測有問題, 4核服務(wù)器 靜態(tài)輸出 workerman 不可能才4萬 QPS, 至少10萬 +
這是我剛壓測的4核騰訊云服務(wù)器, 14萬QPS
截圖

代碼

<?php

use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('http://0.0.0.0:8787');
$worker->count = 4;
$worker->onMessage = function (TcpConnection $connection, Request $request) {
    $connection->send('{"code":200,"msg":"\u6210\u529f","data":[{"id":1,"name":"cichenman","age":26,"tip":"\u5185\u5b58\u6570\u636e"}]}');
};
Worker::runAll();
  • CiChenMan 2024-12-02

    可能是我本地環(huán)境問題
    1.我win電腦開的vm虛擬機24核心
    2.電腦后臺掛了很多軟件
    3.虛擬機安裝了寶塔,nginx,mysql
    4.ab測試也是在虛擬機內(nèi)部直接壓測
    5.實際壓測程序內(nèi)部結(jié)構(gòu)很復(fù)雜,寫了啟動類,緩存類,數(shù)據(jù)庫類,并都啟動實例化了,
    6.輸出形式可能不同,ng是直接返回一個靜態(tài)文本,php是echo,workerman是調(diào)用各種安全檢測判斷后輸出

    感覺問題在我自己,并不是程序問題,應(yīng)該用一個純凈linux機器安裝我寫的腳本,并把無用的實例注釋掉。

    然后用另一臺電腦測試,這樣性能應(yīng)該上去了

  • CiChenMan 2024-12-02

    我用的e5-2673 v3本地電腦,內(nèi)存頻率2133mz

  • CiChenMan 2024-12-02

    你的服務(wù)器配置是不是吊打我

  • six 2024-12-02

    我的就是普通的騰訊云的服務(wù)器,4核 4G,還是競價實例,一小時3分錢那種,用完就關(guān)

  • CiChenMan 2024-12-02

    好吧,正在優(yōu)化代碼中,現(xiàn)在已經(jīng)將代碼的并發(fā)處理到了9萬。用了gzip壓縮數(shù)據(jù),太占用資源

  • CiChenMan 2024-12-02

    Benchmarking 127.0.0.1 (be patient)
    Completed 100000 requests
    Completed 200000 requests
    Completed 300000 requests
    Completed 400000 requests
    Completed 500000 requests
    Completed 600000 requests
    Completed 700000 requests
    Completed 800000 requests
    Completed 900000 requests
    Completed 1000000 requests
    Finished 1000000 requests

    Server Software: workerman
    Server Hostname: 127.0.0.1
    Server Port: 80

    Document Path: /
    Document Length: 10 bytes

    Concurrency Level: 1000
    Time taken for tests: 10.324 seconds
    Complete requests: 1000000
    Failed requests: 0
    Keep-Alive requests: 1000000
    Total transferred: 171000000 bytes
    HTML transferred: 10000000 bytes
    Requests per second: 96861.28 [#/sec] (mean)
    Time per request: 10.324 [ms] (mean)
    Time per request: 0.010 [ms] (mean, across all concurrent requests)
    Transfer rate: 16175.08 [Kbytes/sec] received

    Connection Times (ms)
    min mean[+/-sd] median max
    Connect: 0 0 0.6 0 27
    Processing: 0 10 5.9 9 53
    Waiting: 0 10 5.9 9 53
    Total: 0 10 5.9 10 53

    Percentage of the requests served within a certain time (ms)
    50% 10
    66% 12
    75% 13
    80% 14
    90% 17
    95% 21
    98% 26
    99% 30
    100% 53 (longest request)

CiChenMan

重新在天翼云的2核心業(yè)務(wù)服務(wù)器上進行了測試
環(huán)境2C 4G
安裝軟件:由于是業(yè)務(wù)服務(wù)器安裝了MySQL,bt面板,等
壓測參數(shù):ab -n 500000 -c 1000 -k http://127.0.0.1/

  • 暫無評論
CiChenMan

run.php

<?php
use Workerman\Config\StartUp;
use Workerman\Lib\FileMonitor\FileMonitorstart;
require_once __DIR__ . '/../vendor/autoload.php';
//new FileMonitorstart();
startUp::$ip       = "http://0.0.0.0";
startUp::$port     = 80;
startUp::$count    = 2;
startUp::$name     = "http";
startUp::run();
  • 暫無評論
CiChenMan

startUp.php

<?php
namespace Workerman\Config;
use Workerman\Worker;
use Workerman\Lib\MemoryCache\McServer;
use Workerman\Connection\TcpConnection;
use Workerman\Timer;
class StartUp {
    public static $ip;
    public static $port;
    public static $count;
    public static $name;
    // 構(gòu)造函數(shù),可進行一些默認參數(shù)賦值等初始化操作
    public function __construct() {
    }
    // 實際運行服務(wù)的私有實例方法
    public static function run() {
        $MC = new McServer("0.0.0.0",2207);
        // 創(chuàng)建一個Worker監(jiān)聽指定端口,使用http協(xié)議通訊
        $worker = new Worker(self::$ip. ":". self::$port);
        // 啟動指定數(shù)量的進程對外提供服務(wù)
        $worker->count = self::$count;
        // 進程名字
        $worker->name = self::$name;
        // 調(diào)用類的靜態(tài)方法。
        $worker->onWorkerStart = array('\Workerman\Config\Main', 'onWorkerStart');
        $worker->onConnect     = array('\Workerman\Config\Main', 'onConnect');
        $worker->onMessage     = array('\Workerman\Config\Main', 'onMessage');
        $worker->onClose       = array('\Workerman\Config\Main', 'onClose');
        $worker->onWorkerStop  = array('\Workerman\Config\Main', 'onWorkerStop');
        //啟動
        Worker::runAll();
    }
}
  • 暫無評論
CiChenMan

Main.php

<?php
namespace Workerman\Config;
use Workerman\Protocols\Http\Response;
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Lib\Sql\Pdo;
use Workerman\Config\ConfigGlobal\Config;
use Workerman\Lib\MemoryCache\McClient;
use Workerman\Lib\MemoryCache\MCLIB;
use Workerman\Lib\Data\TypeConversion;
use Workerman\Config\Route;
class Main {
    public function __construct() {
    }
    //子進程調(diào)用PDO實例化
    public static function PDO() {
        # 實例化數(shù)據(jù)庫類
        try {
            return new Pdo(Config::Paramete("MySql")->Host,Config::Paramete("MySql")->User,Config::Paramete("MySql")->Pwd,Config::Paramete("MySql")->DB,50);
        }
        catch(\Exception $e) {
            return ($e->getMessage());
        }
    }
    private static function xlh_json($data) {
        return new Response(200, [
                    'Content-Type' => 'application/json',
                    'Content-Encoding'=>'gzip'
                ], gzencode(json_encode($data),6));
    }
    private static function xlh_plain($data) {
        return new Response(200, [
                    'Content-Type' => $data['type'],
                    'Content-Encoding'=>'gzip',
                    'Cache-Control'=>'max-age=86400'
                ],$data['body']);
    }
    private static function xlh_httperror($data) {
        return new Response($data['code'], [
                    'Content-Encoding'=>'gzip'
                ], gzencode($data['msg'],6));
    }
    //子進程調(diào)用MC客戶端實例化 - 鏈接MC服務(wù)端 
    public static function Mclient() {
        return new McClient('0.0.0.0:2207');
    }
    //子進程內(nèi)部獨立的緩存器
    public static function Mc() {
        return new MCLIB();
    }
    public static function onWorkerStart(Worker $worker) {
        if (function_exists('opcache_reset')) {
            opcache_reset();
        }
        //加載路由表
        require_once(__DIR__.'/RouteConfig.php');
        global $PDO,$McClient,$Mc;
        $PDO = self::PDO();
        $McClient = self::Mclient();
        $Mc = self::Mc();
    }
    public static function onConnect(TcpConnection $connection) {
        //設(shè)置當前鏈接緩沖區(qū)大小
        $connection->maxSendBufferSize = 5*1024*1024;

    }
    public static function onMessage(TcpConnection $connection, $request) {
        global $PDO,$McClient,$Mc;
        $connection->PDO = $PDO;
        $connection->McClient = $McClient;
        $connection->Mc = $Mc;
        $get = $request->get();
        $post = $request->post();
        $headers = $request->header();
        $cookies = $request->cookie();
        $files = $request->file();
        $host = $request->host(true);
        $method = $request->method();
        $uri = $request->uri();
        $path = $request->path();
        $query_string = $request->queryString();
        $version = $request->protocolVersion();
        $sid = $request->sessionId();
        $data = [
                    "GET" => $get,
                    "POST" => $post,
                    "HEADERS" => $headers,
                    "COOKIES" => $cookies,
                    "FILES" => $files,
                    "HOST" => $host,
                    "METHOD" => $method,
                    "URL" => $uri,
                    "PATH" => $path,
                    "query_string" => $query_string,
                    "version" => $version,
                    "session" => $sid
                ];
        $connection->data = TypeConversion::StdClass($data);
        $d = Route::Verify($connection);
        //處理直接返回文本字符串的情況
        if(is_string($d)) {
            $d = [
                     "type"=>"text/html",
                     "body"=>gzencode($d,6)
                 ];
        }
        //處理httperror情況
        if(isset($d['httperror'])) {
            return $connection->send(self::xlh_httperror($d['httperror']));
        }
        //處理返回接口json但未聲明情況
        if(!isset($d['type']) || empty($d['type'])) {
            return $connection->send(self::xlh_json($d));
        }
        //處理靜態(tài)方式返回情況
        $connection->send(self::xlh_plain($d));
        // $connection->close();
    }
    public static function onClose(TcpConnection $connection) {
    }
    public static function onWorkerStop(Worker $worker) {
    }
}
  • 暫無評論
CiChenMan

Route.php

<?php
namespace Workerman\Config;
use Workerman\Config\RouteConfig;
use Workerman\Lib\FileTypeDetection\FileTypeDetection;
class Route {
    //路由加載狀態(tài)
    private static $load = false;
    //是否加載默認路由
    private static $autoroute = true;
    //路由表
    private static $routes = [
        // //指定具體方法路由
        "/" => ["App\Controllers\Defaults","index"],
    ];

    public function __construct() {}
    //設(shè)置是否加載默認路由
    public static function SetAutoRoute($status) {
        self::$autoroute = $status;
    }
    //安全站點
    private static $WebHost = [];
    //校驗是否符合通行后綴
    private static function IsProhibitSuffix($name) {
        //禁止訪問的文件后綴
        $ProhibitSuffix = [
                    "php",
                    "git",
                ];
        $url = $name;
        $path = parse_url($url, PHP_URL_PATH);
        $pathInfo = pathinfo($path);
        $extension = isset($pathInfo['extension'])?$pathInfo['extension']:"plain";
        if(in_array($extension,$ProhibitSuffix)) {
            return true;
        }
        return $extension;
    }
    //獲取文件實際地址完整的
    private static function StaticFile($path) {
        if($path === "/") {
            return __DIR__ ."/../../../StaticFiles".$path."index.html";
        }
        return __DIR__ ."/../../../StaticFiles".$path;
    }
    //錯誤定義
    public static function CODEERROR(int $code,$msg="<center><h3 style='color:#f30;'>訪問的資源不存在</h3><hr/>Workerman</center>") {
        $data = is_string($msg)?$msg:json_encode($msg);
        return [
                    'httperror'=>[
                        'code'=>$code,
                        'msg' =>$msg
                    ]    
                ];
    }
    //以靜態(tài)資源形式訪問
    public static function StaticFiles($connection) {
        $path = self::StaticFile($connection->data->PATH);
        //校驗請求文件合法性
        $anquan = self::IsProhibitSuffix($path);
        if($anquan===true) {
            return self::CODEERROR(403,"安全防火墻:".$connection->data->PATH." - 禁止訪問 - 命中攔截規(guī)則".PHP_EOL);
        }
        //校驗文件存在否
        if (file_exists($path)) {
            $d = $connection->Mc->Get($path);
            if(!$d) {
                $d = [
                        "type"=> FileTypeDetection::GetMIME($anquan),
                        "body"=>gzencode(file_get_contents($path), 6)
                    ];
                $connection->Mc->Add($path,$d,time()+864000);
            }
            return $d;
        } else {
            return self::CODEERROR(404);
        }
    }
    //添加路由
    public static function AddRoute($path="",$array=[]) {
        if(!self::$load && self::$autoroute) {
            self::$load = true;
        }
        self::$routes[$path] = $array;
    }
    //添加安全站點
    public static function AddWebHost(Array $data=[]){
        if(count($data)>0){
            foreach ($data as $value) {
                // code...
                self::$WebHost[] = $value;
            }
        }
    }
    //校驗安全站點
    public static function IsWebHost(String $host){
        if(in_array($host,self::$WebHost)){
            return true;
        }
        return false;
    }
    # 校驗路由規(guī)則
    public static function Verify($connection) {
        if(!self::IsWebHost($connection->data->HOST)){
            return self::CODEERROR(500,"<center><h3 style='color:#f30;'>未知站點</h3><hr/>Workerman</center>");
        }
        //請求路徑
        $path = $connection->data->PATH;
        // echo "請求路徑".$path.PHP_EOL;
        $parts = explode('/', $path);
        $count = count($parts);
        //獲取最終的動作名
        $name = $parts[$count-1];
        //還原路由鍵值結(jié)構(gòu)
        $routekey = "";
        foreach ($parts as $index => $value) {
            if($count>2) {
                // code...
                if($value) {
                    if($index == $count-1) {
                        $routekey.="/{name}";
                    } else {
                        $routekey.="/".$value;
                    }
                }
            } else {
                // code...
                if($value) {
                    $routekey.="/".$value;
                }
            }
        }
        if(!$routekey) {
            $routekey = "/";
        }
        if(!isset(self::$routes[$routekey])) {
            $routekey = $path;
        }
        if(isset(self::$routes[$routekey])) {
            //路由存在
            $gz = self::$routes[$routekey];
            // code...
            $stdclass = new $gz[0]();
            $methodName = isset($gz[1])?$gz[1]:$name;
            if (method_exists($stdclass, $methodName)) {
                return $stdclass->$methodName($connection);
                //動作存在
            } else {
                return self::CODEERROR(404);
            }
        } else {
            //路由不存在
            //嘗試以靜態(tài)文件形式訪問
            return self::StaticFiles($connection);
        }
    }
}
  • 暫無評論
CiChenMan

RouteConfig.php

<?php
use Workerman\Config\Route;

//添加安全站點,只有安全站點可以通過訪問
Route::AddWebHost(["www.wlot.top"]);

//默認路由功能
Route::SetAutoRoute(true);

//添加業(yè)務(wù)路由
Route::AddRoute("/testurl",["App\Controllers\Home","userdata"]);
Route::AddRoute("/testurl/{name}",["App\Controllers\Home"]);
Route::AddRoute("/testurl/v1/userdata",["App\Controllers\Home","userdata"]);
Route::AddRoute("/testurl/v1/userdata/{name}",["App\Controllers\Home"]);
  • 暫無評論
CiChenMan

Home.php

<?php
namespace App\Controllers;
use Workerman\Protocols\Http\Response;
use Workerman\Lib\Console\Log;
class Home {
    public function __construct() {
    }
    //開始編寫業(yè)務(wù)代碼
    public function userdata($connection) {
        return [
                    "code"=>200,
                    "msg"=>"OK",
                    "data"=>[
                        "nickname"=>"CiChenMan"
                    ],
                    "time"=>time(),
                    "other"=>$connection->data
                ];
    }
    public function userdatav1($connection) {
        return 123;
    }
    public function test($connection) {
        $sql = md5("select * from user;");
        $d = $connection->McClient->Get($sql);
        if(!$d) {
            # 獲取用戶信息
            $d = $connection->PDO->selects( "select * from user;");
            $connection->McClient->Add($sql,$d,time()+864000);
        }
        return $d;
    }
}
  • 暫無評論
CiChenMan

FileTypeDetection.php

<?php
namespace Workerman\Lib\FileTypeDetection;

class FileTypeDetection{
    //  初始化
    public function __construct(){}

    //常見后綴
    private static $MIME = [
        // 文本文件類型
        'html' => 'text/html',
        'htm' => 'text/html',
        'css' => 'text/css',
        'js' => 'application/javascript',
        'txt' => 'text/plain',
        'xml' => 'application/xml',

        // 圖像文件類型
        'jpg' => 'image/jpeg',
        'jpeg' => 'image/jpeg',
        'png' => 'image/png',
        'gif' => 'image/gif',
        'svg' => 'image/svg+xml',

        // 音頻文件類型
        'mp3' => 'audio/mpeg',
        'wav' => 'audio/wav',
        'ogg' => 'audio/ogg',

        // 視頻文件類型
        'mp4' => 'video/mp4',
        'avi' => 'video/x-msvideo',
        'flv' => 'video/x-flv',
        'webm' => 'video/webm',

        // 腳本文件類型
        'php' => 'application/x-httpd-php',
        'py' => 'text/x-python',
        'rb' => 'application/x-ruby',

        // 壓縮文件類型
        'zip' => 'application/zip',
        'rar' => 'application/x-rar-compressed',
        'gz' => 'application/gzip',

        // 其他文件類型
        'pdf' => 'application/pdf',
        'json' => 'application/json',
        'ico' => 'image/x-icon',

        // 默認未知的
        'plain' => 'text/plain'
    ];

    //獲取后綴
    public static function GetMIME($name='plain'){
        return self::$MIME[$name];
    }
}
  • 暫無評論
CiChenMan

PDO.php

<?php
namespace Workerman\Lib\Sql;
use Workerman\Timer;
use Workerman\Lib\Console\Log;
// 垃圾的封裝,優(yōu)化空間很大,記得優(yōu)化
class Pdo {
    private $pdo;
    #賬號
            private $user;
    #密碼
            private $password;
    #主機 
            private $host;
    #數(shù)據(jù)庫
            private $db;
    #心跳
            private $m;
    #日志
            public $callback = array();
    #構(gòu)造參數(shù)——初始化使用
            public function __construct(string $host="",string $user="",string $password="",string $db="",$m=5) {
        $this -> user = $user;
        $this -> password = $password;
        $this -> host = $host;
        $this -> db = $db;
        $this -> m = $m;
        try {
            $this->pdo =  new \PDO("mysql:host=".$this->host.";dbname=".$this->db, $this->user, $this->password,array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION));
            $this->pdo->exec('SET NAMES utf8mb4');
            if(class_exists('\Workerman\Timer')) {
                $this->Timer();
            }
        }
        catch(\PDOException $e) {
            throw new \Exception(Log::log(300));
        }
        ;
    }
    //常駐內(nèi)存時?;?    private function Timer() {
        // 定時任務(wù)
        Timer::add($this->m, function() {
            $this->selects("show tables");
        }
        );
    }
    ### 進階sql操作                        ###
            ### sql語句模板預(yù)處理                  ###
            ### 更謹慎的封裝,調(diào)用單個或多個方法   ###
            ### 實現(xiàn)便捷的數(shù)據(jù)管理                 ###
            ### 支持增刪改查,事務(wù),提交,回滾      ###
            ### 添加一個隊列方式,將來可能會用     ###
            ### 多語句查詢事務(wù)封裝                 ###
            ### 根據(jù)業(yè)務(wù)需求自行修改庫             ###
            //1.預(yù)處理查詢數(shù)據(jù) 數(shù)據(jù)為空返回[]數(shù)組,有返回[...]
    public function selects(string $sql,Array $arr = array()) {
        try {
            $sth = $this->pdo->prepare($sql);
            $sth->execute($arr);
            $a = $sth->fetchAll(\PDO::FETCH_ASSOC);
            $arr = array();
            foreach ($a as $index => $val) {
                $arr[$index] = $val;
            }
            ;
            return $arr;
        }
        catch(\PDOException $e) {
            throw new \Exception(Log::log(301));
        }
        ;
    }
    //2.預(yù)處理增加數(shù)據(jù) 增加成功返回true 否 false(false時:可能修改的數(shù)據(jù)玉源數(shù)據(jù)相同,或者元數(shù)據(jù)不存在)
    public function insets(string $sql,Array $arr = array()) {
        try {
            $sth = $this->pdo->prepare($sql);
            $sth->execute($arr);
            $a = $sth->rowCount();
            $newid = $this->pdo->lastInsertId();
            return $newid;
        }
        catch(\PDOException $e) {
            // print_r($e);
            throw new \Exception(Log::log(301));
        }
        ;
    }
    //3.預(yù)處理刪除數(shù)據(jù) 成功成功返回true 否false (false時可能元數(shù)據(jù)不存在或者sql有問題)
    public function deletes(string $sql,Array $arr = array()) {
        try {
            $sth = $this->pdo->prepare($sql);
            $sth->execute($arr);
            $a = $sth->rowCount();
            return $a;
        }
        catch(\PDOException $e) {
            throw new \Exception(Log::log(301));
        }
        ;
    }
    //4.預(yù)處理修改數(shù)據(jù) 成功成功返回true 否false (false時可能元數(shù)據(jù)不存在或者sql有問題)
    public function updates(string $sql,Array $arr = array()) {
        try {
            $sth = $this->pdo->prepare($sql);
            $sth->execute($arr);
            return $sth->rowCount();
        }
        catch(\PDOException $e) {
            print_r($e);
            throw new \Exception(Log::log(301));
        }
        ;
    }
    ### 事務(wù)相關(guān)   ###
            //1.接受一個多預(yù)處理模板事務(wù)數(shù)據(jù)集 全部執(zhí)行成功返回true 狗則 false
    public function start_begin(Array $object) {
        try {
            /* 開始一個事務(wù),關(guān)閉自動提交 */
            $this->pdo->beginTransaction();
            //設(shè)置一個記錄日志
            $log = [];
            //循環(huán)遍歷處理預(yù)處理數(shù)據(jù)
            foreach ($object as $index => $sql) {
                $sth = $this->pdo->prepare($sql['sql']);
                $sth->execute($sql['arr']);
                //將每次預(yù)處理的結(jié)果(受到影響的行數(shù))記錄到log中,方便查詢具體運行日志
                $log[$index] = $sth->rowCount();
            }
            ;
            //提交
            $this->pdo->commit();
            return $log;
        }
        catch(\PDOException $e) {
            //file_put_contents("sql",$e);
            //回滾
            $this->pdo->rollBack();
            throw new \Exception(Log::log(303));
        }
        ;
    }
    //開啟事務(wù)
    public function beginTransaction() {
        $this->pdo->beginTransaction();
    }
    //執(zhí)行提交
    public function commit() {
        $this->pdo->commit();
    }
    //回滾
    public function rollBack() {
        $this->pdo->rollBack();
    }
}
  • 暫無評論
CiChenMan

MCLIB.php

<?php
// 
//  基于workerman 的常駐內(nèi)存緩存器
//  
// 
// 
namespace Workerman\Lib\MemoryCache;
use Workerman\Timer;
class MCLIB {
    //  基本配置參數(shù)信息
    private  $info = [
            "name" => "MC內(nèi)存緩存器",
            "describe" => "一個基于 workerman 的常駐內(nèi)存緩存器,快速的在多進程間訪問全局共享數(shù)據(jù)!",
            "version" => "1.0.0",
            "author" => "CiChenMan",
            "email" => "1570442495@qq.com",
            "wechat" => "cichenman",
            "tel" => "18265556279"
        ];
    public function GetInfo() {
        return $this->info;
    }
    //  默認增加緩存時間  例如查詢到緩存后為了更持久的使用,自動增加的變量時間
    private static $AutoTime = 864000;
    //  存儲塊大小信息配置
    private  $StorageBlockSize = [
            // 最大 1G 的內(nèi)存存儲塊,超出后會自動清理一些訪問較少的存儲塊,數(shù)據(jù)很大時/內(nèi)存寬裕時可以適當調(diào)整
    "MaxSize"   =>      1 * (1024*1024*1024*1024),
            // 是否開啟自動刪除多余內(nèi)存模式
    "AutoDel"   =>      false,
        ];
    //  存儲塊索引
    private  $StorageBlockIndex = [
            //存儲條目數(shù)量
    "DataLen" => 0,
            //存儲占用大小(總量)
    "DataSize"=> 0,
            //存儲索引基本信息 數(shù)組數(shù)據(jù)對應(yīng)索引
    "DataList"=> [
                "Key" => [
                    // "test"
    ],
                "Value" => [
                    // "test" => [
    //     "Visits"=>122,
    //     "Index"=>0,
    //     //大小
    //     "Size"=>567,
    //     //過期時間
    //     "FailureTime"=> 1701062400
    // ]
    ]
            ] 
        ];
    //  存儲塊
    private  $StorageBlock = [];
    //  初始化
    public function __construct($AutoDel=false) {
        $this->StorageBlockSize['AutoDel'] = $AutoDel;
        if($this->StorageBlockSize['AutoDel']) {
            Timer::add(30, function() {
                $this->AutoDel();
            }
            );
        }
    }
    //大小轉(zhuǎn)換
    private function formatSize($sizeInBytes) {
        $units = array('B', 'KB', 'MB', 'GB', 'TB');
        $index = 0;
        while ($sizeInBytes >= 1024 && $index < count($units) - 1) {
            $sizeInBytes /= 1024;
            $index++;
        }
        return round($sizeInBytes, 2). $units[$index];
    }
    //  清理一些訪問較少的存儲塊
    public  function AutoDel() {
        $visitsArray = [];
        $dataList = $this->StorageBlockIndex['DataList']['Value'];
        foreach ($dataList as $key => $value) {
            $visitsArray[$key] = $value['Visits'];
        }
        array_multisort($visitsArray, SORT_DESC, $dataList);
        //echo "-------------------------------------------";
        // print_r($dataList);
        $d = [
                    "緩存條數(shù)" => $this->StorageBlockIndex['DataLen'],
                    "緩存占用內(nèi)存" => $this->formatSize($this->StorageBlockIndex['DataSize']),
                ];
        // print_r($d);
    }
    //  增加新數(shù)據(jù) 
    //  $Key    索引
    //  $Value  數(shù)據(jù)
    //  $Time   過期時間
    public  function Add(string $Key, $Value,int $Time = 0) {
        if(!$Key || !$Value) {
            return [
                            "Status"    =>  "FAILL",
                            "MessAge"   =>  "請檢查存儲數(shù)據(jù)時傳入的參數(shù)是否正確。"
                        ];
        }
        ;
        if(isset($this->StorageBlockIndex['DataList']['Value'][$Key])) {
            return [
                            "Status"    =>  "FAILL",
                            "MessAge"   =>  "添加數(shù)據(jù)的索引在MC中已經(jīng)存在,無需重復(fù)添加。"
                        ];
        }
        //獲取字節(jié)大小
        $strlen = strlen(serialize($Value));
        if($this->StorageBlockIndex['DataSize'] + $strlen > $this->StorageBlockSize['MaxSize']) {
            return [
                            "Status"    =>  "FAILL",
                            "MessAge"   =>  "累計存儲內(nèi)容超過設(shè)置最大限制,無法存入緩存。"
                        ];
        }
        //寫入數(shù)據(jù)
        $this->StorageBlockIndex['DataSize'] = $this->StorageBlockIndex['DataSize'] + $strlen;
        ++$this->StorageBlockIndex['DataLen'];
        $this->StorageBlockIndex['DataList']['Key'][] = $Key;
        $this->StorageBlockIndex['DataList']['Value'][$Key] = [
                    "Visits"=>0,
                    //下標
        "Index"=>count($this->StorageBlockIndex['DataList']['Key']) - 1,
                    //大小
        "Size"=>$strlen,
                    //過期時間
        "FailureTime"=> $Time
                ];
        $this->StorageBlock[$Key] = serialize($Value);
        return true;
    }
    //  刪除數(shù)據(jù)
    //  $Key    索引
    public  function Del(string $Key) {
        if(!$Key) {
            return [
                            "Status"    =>  "FAILL",
                            "MessAge"   =>  "請檢查存儲數(shù)據(jù)時傳入的參數(shù)是否正確。"
                        ];
        }
        ;
        //寫入數(shù)據(jù)
        $this->StorageBlockIndex['DataSize'] = $this->StorageBlockIndex['DataSize'] - $this->StorageBlockIndex['DataList']['Value'][$Key]['Size'];
        --$this->StorageBlockIndex['DataLen'];
        $index = $this->StorageBlockIndex['DataList']['Value'][$Key]['Index'];
        unset($this->StorageBlockIndex['DataList']['Key'][$Key][$index]);
        unset($this->StorageBlockIndex['DataList']['Value'][$Key]);
        unset($this->StorageBlock[$Key]);
        return true;
    }
    //修改數(shù)據(jù)
    //  $Key    索引
    //  $Value  數(shù)據(jù)
    //  $Time   過期時間
    public  function UpData(string $Key, $Value,int $Time = 0) {
        if(!$Key || !$Value) {
            return [
                            "Status"    =>  "FAILL",
                            "MessAge"   =>  "請檢查存儲數(shù)據(jù)時傳入的參數(shù)是否正確。"
                        ];
        }
        ;
        //獲取新數(shù)據(jù)字節(jié)大小
        $newstrlen = strlen(serialize($Value));
        //獲取舊數(shù)據(jù)字節(jié)大小
        if(!isset($this->StorageBlockIndex['DataList']['Value'][$Key])) {
            return [
                            "Status"    =>  "FAILL",
                            "MessAge"   =>  "傳入修改數(shù)據(jù)的索引在MC中不存在,請檢查。"
                        ];
        }
        $oldstrlen = $this->StorageBlockIndex['DataList']['Value'][$Key]['Size'];
        if($this->StorageBlockIndex['DataSize'] - $oldstrlen + $newstrlen > $this->StorageBlockSize['MaxSize']) {
            return [
                            "Status"    =>  "FAILL",
                            "MessAge"   =>  "修改數(shù)據(jù)時,累計存儲內(nèi)容超過設(shè)置最大限制,無法存入緩存,修改失敗。"
                        ];
        }
        $this->StorageBlockIndex['DataSize'] = $this->StorageBlockIndex['DataSize'] - $oldstrlen + $newstrlen;
        $this->StorageBlockIndex['DataList']['Value'][$Key]['Size'] = $newstrlen;
        $this->StorageBlockIndex['DataList']['Value'][$Key]['FailureTime'] = $Time;
        $this->StorageBlock[$Key] = serialize($Value);
        return true;
    }
    //獲取數(shù)據(jù)
    public  function Get(string $Key,$AutoData = "") {
        if(!isset($this->StorageBlockIndex['DataList']['Value'][$Key])) {
            if($AutoData) {
                return $AutoData;
            } else {
                return null;
            }
        }
        //如果過期了就刪除
        if($this->StorageBlockIndex['DataList']['Value'][$Key]['FailureTime']-time()<0) {
            //echo "過期刪除";
            $this->Del($Key);
            return $AutoData;
        }
        $t = $this->StorageBlockIndex['DataList']['Value'][$Key]['FailureTime'];
        if($t - self::$AutoTime < self::$AutoTime) {
            $this->StorageBlockIndex['DataList']['Value'][$Key]['FailureTime'] = $t + self::$AutoTime;
        }
        ++$this->StorageBlockIndex['DataList']['Value'][$Key]['Visits'];
        return unserialize($this->StorageBlock[$Key]) ;
        // return $this->StorageBlockIndex['DataList']['Value'][$Key]['Visits'];
    }
}
  • 暫無評論
CiChenMan

McClient.php - 基于官方的共享組件客戶端

<?php
namespace Workerman\Lib\MemoryCache;
/**
 *  Global data client.
 *  @version 1.0.3
 */
class McClient {
    /**
     * Timeout.
     * @var int
     */
    public $timeout = 5;
    /**
     * Heartbeat interval.
     * @var int
     */
    public $pingInterval = 25;
    /**
     * Global data server address.
     * @var array
     */
    protected $_globalServers = array();
    /**
     * Connection to global server.
     * @var resource
     */
    protected $_globalConnections = null;
    /**
     * Cache.
     * @var array
     */
    protected $_cache = array();
    /**
     * Construct.
     * @param array | string $servers
     */
    public function __construct($servers) {
        if(empty($servers)) {
            throw new \Exception('servers empty');
        }
        $this->_globalServers = array_values((array)$servers);
    }
    /**
     * Connect to global server.
     * @throws \Exception
     */
    protected function getConnection($key) {
        $offset = crc32($key)%count($this->_globalServers);
        if($offset < 0) {
            $offset = -$offset;
        }
        if(!isset($this->_globalConnections[$offset]) || !is_resource($this->_globalConnections[$offset]) || feof($this->_globalConnections[$offset])) {
            $connection = stream_socket_client("tcp://{$this->_globalServers[$offset]}", $code, $msg, $this->timeout);
            if(!$connection) {
                throw new \Exception($msg);
            }
            stream_set_timeout($connection, $this->timeout);
            if(class_exists('\Workerman\Timer') && php_sapi_name() === 'cli') {
                $timer_id = \Workerman\Timer::add($this->pingInterval, function($connection)use(&$timer_id) {
                    $buffer = pack('N', 8)."ping";
                    if(strlen($buffer) !== @fwrite($connection, $buffer)) {
                        @fclose($connection);
                        \Workerman\Timer::del($timer_id);
                    }
                }
                , array($connection));
            }
            $this->_globalConnections[$offset] = $connection;
        }
        return $this->_globalConnections[$offset];
    }
    /**
     * Add.
     * @param string $key
     * @throws \Exception
     */
    // public function add($key)
    // {
    //     $connection = $this->getConnection($key);
    //     $this->writeToRemote(array(
    //             'cmd' => 'add',
    //             'key' => $key
    //     ), $connection);
    //     return $this->readFromRemote($connection);
    // }
    ##################################################################
            public function Add(string $Key, $Value,int $Time = 0) {
        $connection = $this->getConnection($Key);
        $this->writeToRemote(array(
                                'FUN'   =>  'Add',
                                'Key'   =>  $Key,
                                'Value' =>  $Value,
                                'Time'  =>  $Time
                        ), $connection);
        return $this->readFromRemote($connection);
    }
    public function Del(string $Key) {
        $connection = $this->getConnection($Key);
        $this->writeToRemote(array(
                                'FUN'   =>  'Del',
                                'Key'   =>  $Key
                        ), $connection);
        return $this->readFromRemote($connection);
    }
    public function UpData(string $Key, $Value,int $Time = 0) {
        $connection = $this->getConnection($Key);
        $this->writeToRemote(array(
                                'FUN'   =>  'UpData',
                                'Key'   =>  $Key,
                                'Value' =>  $Value,
                                'Time'  =>  $Time
                        ), $connection);
        return $this->readFromRemote($connection);
    }
    public function Get(string $Key,$AutoData = "") {
        $connection = $this->getConnection($Key);
        $this->writeToRemote(array(
                                'FUN'   =>  'Get',
                                'Key'   =>  $Key,
                                'AutoData' =>  $AutoData
                        ), $connection);
        return $this->readFromRemote($connection);
    }
    public function AutoDel() {
        $connection = $this->getConnection('AutoDel');
        $this->writeToRemote(array(
                                'FUN'   =>  'AutoDel'
                        ), $connection);
        return $this->readFromRemote($connection);
    }
    ###################################################################
    /**
     * Write data to global server.
     * @param string $buffer
     */
    protected function writeToRemote($data, $connection) {
        $buffer = json_encode($data);
        //serialize($data);
        $buffer = pack('N',4 + strlen($buffer)) . $buffer;
        $len = fwrite($connection, $buffer);
        if($len !== strlen($buffer)) {
            throw new \Exception('writeToRemote fail');
        }
    }
    /**
     * Read data from global server.
     * @throws Exception
     */
    protected function readFromRemote($connection) {
        $all_buffer = '';
        $total_len = 4;
        $head_read = false;
        while(1) {
            $buffer = fread($connection, 8192);
            if($buffer === '' || $buffer === false) {
                throw new \Exception('readFromRemote fail');
            }
            $all_buffer .= $buffer;
            $recv_len = strlen($all_buffer);
            if($recv_len >= $total_len) {
                if($head_read) {
                    break;
                }
                $unpack_data = unpack('Ntotal_length', $all_buffer);
                $total_len = $unpack_data['total_length'];
                if($recv_len >= $total_len) {
                    break;
                }
                $head_read = true;
            }
        }
        return unserialize(substr($all_buffer, 4));
    }
}
  • 暫無評論
CiChenMan

McServer.php - 基于官方共享組件服務(wù)端

<?php
namespace Workerman\Lib\MemoryCache;
use Workerman\Worker;
use Workerman\Lib\MemoryCache\MCLIB;
/**
 * Global data server.
 */
class McServer {
    /**
     * Worker instance.
     * @var worker
     */
    protected $_worker = null;
    // 實例化MC插件
    protected $MC;
    /**
     * Construct.
     * @param string $ip
     * @param int $port
     */
    public function __construct($ip = '0.0.0.0', $port = 2207) {
        $worker = new Worker("frame://$ip:$port");
        $worker->count = 1;
        $worker->name = "MC內(nèi)存緩存器(1.0.0)";
        $worker->onWorkerStart = array($this,'onWorkerStart');
        $worker->onMessage = array($this, 'onMessage');
        $worker->reloadable = false;
        $this->_worker = $worker;
    }
    public function onWorkerStart($worker) {
        // 實例化MC內(nèi)存緩存器
        $this->MC = new MCLIB(true);
    }
    /**
     * onMessage.
     * @param TcpConnection $connection
     * @param string $buffer
     */
    public function onMessage($connection, $buffer) {
        if ($buffer === 'ping') {
            return;
        }
        $data = json_decode($buffer,true);
        if (!$buffer ||!isset($data['FUN']) ||!isset($data['Key'])) {
            return $connection->close(serialize('錯誤的數(shù)據(jù)'));
        }
        $FUN = $data['FUN'];
        $key = $data['Key'];
        // print_r($data);
        switch ($FUN) {
            case 'Get':
                            $cachedData = $this->MC->Get($data['Key'],$data['AutoData']);
            if ($cachedData!== null) {
                return $connection->send(serialize($cachedData));
            }
            $connection->send('N;');
            break;
            case'UpData':
                            $result = $this->MC->UpData($data['Key'],$data['Value'],$data['Time']);
            if($result===true) {
                return $connection->send('b:1;');
            }
            $connection->send(serialize($result));
            break;
            case 'Add':
                            $result = $this->MC->Add($data['Key'],$data['Value'],$data['Time']);
            if ($result === true) {
                return $connection->send('b:1;');
            }
            $connection->send(serialize($result));
            break;
            case 'Del':
                            $this->MC->Del($data['Key']);
            $connection->send('b:1;');
            break;
            case 'AutoDel':
                            $this->MC->AutoDel();
            $connection->send('b:1;');
            break;
            default:
                            $connection->close(serialize('不符合規(guī)范的調(diào)用'));
        }
    }
}
shiroi

雖然但是不是很懂你想表達什么

lsmir2

不明覺厲.這得是什么場景啊?

  • CiChenMan 2024-12-17

    網(wǎng)站

  • lsmir2 2024-12-18

    你的緩存類 如果多進程的情況下,是不是會有問題.他不是共享緩存.

  • CiChenMan 2024-12-24

    是共享的,類是實現(xiàn)存儲,官方不是有一個全局共享組件嘛,我在服務(wù)端實例化這個類,改了官方的。

    1使用官方數(shù)據(jù)共享組件服務(wù)端實例化類
    2onworkerstart中實例化
    兩種,1用來跨進程,2用來緩存當前進程數(shù)據(jù)

  • CiChenMan 2024-12-24

    這個就是workerman寫的

  • wocall 2025-01-08

    總之,牛逼

CiChenMan

220
積分
0
獲贊數(shù)
0
粉絲數(shù)
2024-11-25 加入
??