PHP+Swoole搭建web服务(接入slim)

一、Swoole 安装

下载源码编译安装( pecl install swoole安装易失败):

#下载源码
git clone https://github.com/swoole/swoole-src.git
#如果clone不下来可以选择: git clone ttps://gitee.com/swoole/swoole.git
#进入源码目录并选择最新tag
cd swoole-src
git checkout v4.3.3
#或 cd swoole
#git checkout v4.3.2
phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make && make install
#配置php.ini 添加:
extension=swoole.so
#执行php -m 查看拓展是否安装成功

二、Swoole 搭建Http服务器

1、简单服务搭建

<?php
    //(1)创建swool的http服务器对象
    $serv = new swoole_http_server('0.0.0.0',8000);
    //(2)当浏览器链接点这个http服务器的时候,向浏览器发送helloworld
    $serv->on('request',function($request,$response){
        //(2.1)$request包含这个请求的所有信息,比如参数
        //(2.2)$response包含返回给浏览器的所有信息,比如helloworld
        var_dump($request);
        var_dump($response);
        //(2.3)向浏览器发送helloworld
        $response->end("hello world");
    });
    //(3)启动http服务器
    $serv->start();
?>
#执行测试
php sw_http.php 
curl http://127.0.0.1:8000

2、原理解析

启动swoole的时候会启动Manager进程和Master进程。对于Manager进程,用于管理Worker进程(我们业务层的逻辑代码一般放在这里)和Task进程(用于在某个特定的时间或者条件下执行的代码)。对于Master进程,用于底层的开发,后面详细介绍.如下图:
线程和进程的模型
1. 在这个swoole服务器启动后,会创建三个进程
    * Manager
    * Worker
    * Task
2.这个Manager进程是Worker进程的守护进程,在这个Worker进程意外结束后,这个Manager进程会重新启动Workder进程,Manager进程只有一个,而这个Worker可以有多个。
3.Worker进程通过给这个Task进程发送任务,可以把一些计算量大的任务转移到Task进程,这样我们的Worker进程就可以高速处理客户端的请求,提高并发量。
4.reactor线程是swoole底层处理高并发,最大限度的调用底层资源。
swoole执行过程

image.png

3、简单的swoole http 服务器实例

<?php
/**
 * 简单的swoole http 服务器实例
 * User: guola
 * Date: 2019/5/10
 * Time: 18:12
 */
use Swoole\Http\Server as http_server;
$setting = [
    'reactor_num' => 1,
    'worker_num' => 2,
    'max_request' => 1000,
    'task_worker_num' => 1,
    'task_tmpdir' => '/tmp',
    'daemonize' => 0,
    'log_file' => __DIR__.'/swlog.txt',
    'pid_file' => __DIR__.'/swhttpserver.pid',
];
function startSwHttpServer($setting){
    $webserver = new http_server('0.0.0.0', '8881', SWOOLE_PROCESS, SWOOLE_SOCK_TCP);//如果ssl SWOOLE_SOCK_TCP | SWOOLE_SSL
    $webserver->set($setting);

    /**
     * start回调
     */
    $webserver->on('Start', function(http_server $server) {
        echo 'Start...',"\n";
        // 重新设置进程名称
        swoole_set_process_name('swhttp-master');
    });

    /**
     * managerstart回调
     */
    $webserver->on('ManagerStart', function(http_server $server) {
        echo 'manager start...',"\n";
        // 重新设置进程名称
        swoole_set_process_name('swhttp-manager');
    });

    /**
     * managerstop回调
     */
    $webserver->on('ManagerStop', function(http_server $server) {
        echo 'manager stop...',"\n";
    });

    /**
     * 启动worker进程监听回调,设置定时器
     */
    $webserver->on('WorkerStart', function(http_server $server, $worker_id) use($setting) {
        // 设置worker的进程
        if($worker_id >= $setting['worker_num']) {
            swoole_set_process_name("swhttp-task".$worker_id);
        }else {
            swoole_set_process_name("swhttp-worker".$worker_id);
        }
        // 延迟绑定
        onWorkerStart($server, $worker_id);

    });

    /**
     * worker进程停止回调函数
     */
    $webserver->on('WorkerStop', function(http_server $server, $worker_id) {
        echo 'worker stop...',"\n";

    });

    /**
     * 接受http请求
     */
    $webserver->on('request', function(Request $request, Response $response) {
        try{
            onRequest($request, $response);
            return true;
        }catch(\Exception $e) {
            echo $e;
        }
    });

    $webserver->on('task', function(http_server $server, $task_id, $from_worker_id, $data) {
        try{
            $task_data = unserialize($data);
            onTask($server, $task_id, $from_worker_id, $task_data);
        }catch(\Exception $e) {
            echo $e;
        }

    });
    $webserver->start();



}
//请求处理即传统web/MVC框架启动处
function onRequest($request, $response){
    echo 'onRequest...',"\n";
}
function onWorkerStart($server, $worker_id){
    echo 'onWorkerStart...',"\n";
}

function onTask($server, $task_id, $from_worker_id, $task_data){
    echo 'onTask...',"\n";
}
startSwHttpServer($setting);


//在onRequest方法中启动执行MVC框架

4、接入Slim框架

1、composer create-project slim/slim-skeleton ss
2、cd ss
3、创建脚本SlimSwooleHttpServier.php 脚本如下:
<?php
    use Slim\Http\Environment;
    class SlimSwooleHttpServier{
        public $host='0.0.0.0';
        public $port=6666;
        public $http="";
        public function __construct()
        {
            $this->http = new Swoole\Http\Server($this->host, $this->port);
            $this->http->set([
                //'daemonize'=>1,
                'worker_num'=>4
            ]);
            $this->http->on('Start',[$this,'MasterStart']);
            $this->http->on('ManagerStart',[$this,'ManagerStart']);
            $this->http->on('WorkerStart',[$this,'WorkerStart']);
            $this->http->on('request',[$this,'request']);
            $this->http->start();
        }
        public function MasterStart(){
             swoole_set_process_name('sshttp-master');
        }
        public function ManagerStart(){
             swoole_set_process_name('sshttp-manager');
        }
        public function WorkerStart($server,$worker_id){
            define("ROOT",__DIR__);
            define('APP', ROOT . '/src');
            swoole_set_process_name('sshttp-worker');
            require ROOT . '/vendor/autoload.php';
            echo $worker_id."\n";
        }
        public function request($request,$response){

            $config = require APP . '/settings.php';
            $config['environment'] = function () use($request) {
                $_SERVER = [];
                foreach ($request->server as $key => $value) {
                    $_SERVER[strtoupper($key)] = $value;
                }
                return new Environment($_SERVER);
            };
            $_GET=[];
            if(isset($request->get)){
                $_GET = $request->get;
            }
            $_POST=[];
            if(isset($request->post)){
                $_POST = $request->post;
            }
            $app = new \Slim\App($config);
            require APP . '/dependencies.php';
            require APP . '/routes.php';

            // Register middleware
            $middleware = require APP  . '/middleware.php';
            $middleware($app);
            // Register routes
            $routes = require APP   . '/routes.php';
            $routes($app);
            // Run app
            $slimResponse = $app->run(true);
            $headers = $slimResponse->getHeaders();
            foreach ($headers as $name => $values) {
                $response->header($name, implode(", ", $values));
            }
            $response->header("X-Powered-By", "Salamander");
            $response->end($slimResponse->getBody());
        }
    }
    new SlimSwooleHttpServier();
?>
4、添加路由:vim src/routes.php 添加路由:
$app->get('/hello/{name}', function (Request $request, Response $response, array $args) {
    $name = $args['name'];
    $response->getBody()->write("Hello, $name\n");

    return $response;
});
5、执行php  SlimSwooleHttpServier.php
6、测试:curl -i http://127.0.0.1:6666/hello/123
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
X-Powered-By: Salamander
Server: swoole-http-server
Connection: keep-alive
Date: Tue, 21 May 2019 01:31:46 GMT
Content-Length: 10

Hello, 123
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容