swoole框架真的比php-fpm要高并发吗? php

之前写了一篇文章,做了一个粗疏的测试.来证明,在慢数据库查询下,swoole跟php-fpm的并发数一样地少.相差无几.经过网友的讨论和指教.我发现我的结论是错误的且有可能误导其他开发者.

所以现在找一个更加贴近现实的生产环境的测试方法.这里先说结论,swoole是真正能解决php项目性能差,并发低的方案之一.

这里首先要说php-fpm的多进程模式,php-fpm的处理方法.只会一个请求一个请求地处理.怎么证明这个事情?可以写一个sleep(30)秒的接口.开2个静态进程.快速请求两次.然后再去请求其他没有阻塞的接口.看看是不是连其他正常的接口也请求不了.如果是,就能说明php-fpm的处理方法.

但php-fpm的进程是独立.严格上说一个进程慢,需要时间处理,是不会影响其他进程的响应时间的.你可以这样试,同样开两个php-fpm进程,请求一次sleep(30)秒的接口.然后同时压测另外正常的接口.QPS还是有可能上千的.但如果慢的接口的请求把所有的php-fpm进程都占用了,就会影响都其他正常接口的响应速度.出现类似 "阻塞" 的现象.

这个情况也一般php项目速度慢的情况.我认为在介绍,swoole的好处时候.说php-fpm开销大,每次载入框架代码这些其实意义不大.因为一个接口用php-fpm写响应速度是 100ms.换成swoole框架能提高 到80ms.意义不是特别大.

压测方法,

写两个接口,一个等待一秒返回,另一个hello world.同时压测.这样的目的是模拟生产环境.有个别的接口特别慢.拖慢了整个项目的请求速度.
php-fpm sleep代码

sleep(1)

hyperf sleep1秒接口


try {
            $Client= new Client();
            $Client->get("https://www.google.com",["timeout"=>1]);
        }catch (\Exception $exception ){

        }

hello world代码

echo "hello word"

thinkphp8 php-fpm 静态模式 2个进程

单独压测hello world接口

wrk -c 100 -t 10 -d 10s http://tp8.localhost/index/index

QPS 1871

sleep接口和hello world接口,同时压.

wrk -c 10 -t 10 -d 10s http://tp8.localhost/sleep/index/

wrk -c 100 -t 10 -d 10s http://tp8.localhost/index/index

hello world接口 QPS 19.97

hyperf 开2个进程

hyperf 不用sleep模拟慢接口,用http请求来模拟.

hello world接口单独压测

wrk -c 100 -t 10 -d 10s http://127.0.0.1:9501/index

QPS 58576

sleep接口和hello world接口,同时压.
wrk -c 10 -t 10 -d 10s http://127.0.0.1:9501/sleep
wrk -c 100 -t 10 -d 10s http://127.0.0.1:9501/index

hello world接口 QPS 56826

hello world接口几乎没有受慢接口影响

得出结论

单个接口请求,php-fpm跟swoole也许有10倍的差距.但是这个不是重点.重点是采用swoole框架写的项目整体不会被慢的接口拖慢.这个比较有意义.

这里说的swoole性能比php-fpm强10倍.不是说一个接口用来用php-fpm请求时间是1秒,改用了swoole框架就变成了0.1秒.
而是说某些情况.swoole的并发数可以比php-fpm高10倍.

为什么php-fpm会出现"阻塞"的情况.和什么情况下才会出现阻塞.
php-fpm进程数是20,一个sleep(1)的接口,每秒并发请求数为20.这样就会把20个进程用占用.而其他接口的请求就会出现"阻塞"的情况.因为没有进程可用了,但如果并发是10去请求慢接口.还有剩下10个进程去处理其他接口的请求.这时候就不会出现"阻塞".

google请求解释

   $Client->get("https://www.google.com",["timeout"=>1]);

解释一下请求google地址,在墙内一定是请求不到的.设置1秒超时.为了代替php-fpm的sleep1秒.

标签: php

xiang 发布于  2023-12-27 16:28 

php+nginx实现最简单的远程调用rpc(微服务) php

nginx配置,负载均衡
如果微服务只能远程调用一个服务端,那就失去意义了.用Nginx可以实现健康检测和负载均衡策略的配置.使得服务端具有扩展性和高可用性.

    upstream userservice {
        server 127.0.0.1:9002; 
        server 127.0.0.1:9003; 
    }
    server {
        listen 80;

        location / {
            proxy_pass http://userservice;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }

微服务端用webmen实现
IndexController

<?php

namespace app\controller;

use support\Request;

class IndexController
{
    public function rpc(Request $request)
    {
        $class_name="app\\service\\".$request->post('class');
        $obj=new $class_name;
        $res=call_user_func_array([$obj,$request->post("method")], $request->post('params'));
        return $res;
    }
}

Service

<?php
namespace app\service;

use app\model\User;
use support\Model;

class My
{
    public function mymethod($name){
        $data="yout input name is ".$name;
         return json_encode(["code"=>0,"message"=>"成功","data"=>$data]);
    }
}

http端口设置9002

<?php
/**
 * This file is part of webman.
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the MIT-LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @author    walkor<walkor@workerman.net>
 * @copyright walkor<walkor@workerman.net>
 * @link      http://www.workerman.net/
 * @license   http://www.opensource.org/licenses/mit-license.php MIT License
 */

return [
    'listen' => 'http://0.0.0.0:9002',
    'transport' => 'tcp',
    'context' => [],
    'name' => 'webman',
    'count' => 32,
    'user' => '',
    'group' => '',
    'reusePort' => false,
    'event_loop' => '',
    'stop_timeout' => 2,
    'pid_file' => runtime_path() . '/webman.pid',
    'status_file' => runtime_path() . '/webman.status',
    'stdout_file' => runtime_path() . '/logs/stdout.log',
    'log_file' => runtime_path() . '/logs/workerman.log',
    'max_package_size' => 10 * 1024 * 1024
];

启动webman

php start.php start -d

复制服务端项目,用9003端口启动一下

客户端用thinkphp 和 GuzzleHttp 实现

<?php
namespace app\rpc_service;

use GuzzleHttp\Client;

class UserService{

    /**
     * @param $class
     * @param $method
     * @param $params
     * @return mixed
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function get($class,$method,$params=[]){
        $client = new Client();
        $res = $client->post("http://127.0.0.1:80/index/rpc",['form_params' => [
            'class' => $class,
            "method"=>$method,
            "params"=>$params
        ]]);

        $json=$res->getBody()->getContents();

        return json_decode($json,true);
    }
}

调用

<?php

namespace app\controller;

use app\BaseController;
use app\rpc_service\UserService;
use GuzzleHttp\Client;

class Index extends BaseController
{
    public function hello()
    {
        $UserService=new UserService();
        $res= $UserService->get("My","mymethod",["name"=>"xiang"]);
        return json_encode($res);
    }
}
{
    "code": 0,
    "message": "成功",
    "data": "yout input name is xiang"
}

性能损耗
thinkphp本地 QPS 6000多
本地远程调用 QPS 4000多

标签: php

xiang 发布于  2023-12-26 13:54