Laravel && ( Swoole || Workerman ) to get 10x faster than php-fpm

Related tags

Laravel laravoole
Overview

Laravoole

Laravel on Swoole Or Workerman

10x faster than php-fpm

Latest Stable Version Total Downloads Latest Unstable Version License Build Status Code Coverage

Depends On

php >=5.5.16
laravel/laravel ^ 5.1

Suggests

php >=7.0.0
ext-swoole >=1.7.21
workerman/workerman >=3.0

Install

To get started, add laravoole to you composer.json file and run composer update:

"garveen/laravoole": "^0.5.0"

or just run shell command:

 composer require garveen/laravoole

Once composer done its job, you need to register Laravel service provider, in your config/app.php:

'providers' => [
    ...
    Laravoole\LaravooleServiceProvider::class,
],

Notice: You should NOT use file session handler, because it is not stable at this environement. Use redis or other handler instead.

Usage

php artisan laravoole [start | stop | reload | reload_task | restart | quit]

Migrations

Upgrade to 0.4

Event names has changed:

  • laravoole.on_request => laravoole.requesting
  • laravoole.on_requested => laravoole.requested
  • laravoole.swoole.websocket.on_close => laravoole.swoole.websocket.closing

Config

To generate config/laravoole.php:

php artisan vendor:publish --provider="Laravoole\LaravooleServiceProvider"

Most of things can be configured with .env, and you should use LARAVOOLE_{UPPER_CASE} format, for example,

[
    'base_config' => [
        'host' => '0.0.0.0',
    ]
]

is equals with

LARAVOOLE_HOST=0.0.0.0

Events

You can handle events by editing EventServiceProvider:

public function boot()
{
    parent::boot();
    \Event::listen('laravoole.requesting', function ($request) {
        \Log::info($request->segments());
    });
}
  • laravoole.requesting(Illuminate\Http\Request)
  • laravoole.requested(Illuminate\Http\Request, Illuminate\Http\Response)
  • laravoole.swoole.websocket.closing(Laravoole\Request, int $fd)

base_config

This section configures laravoole itself.

mode

SwooleHttp uses swoole to response http requests

SwooleFastCGI uses swoole to response fastcgi requests (just like php-fpm)

SwooleWebSocket uses swoole to response websocket requests AND http requests

WorkermanFastCGI uses workerman to response fastcgi requests (just like php-fpm)

user defined wrappers

You can make a new wrapper implements Laravoole\Wrapper\ServerInterface, and put its full class name to mode.

pid_file

Defines a file that will store the process ID of the main process.

deal_with_public

When using Http mode, you can turn on this option to let laravoole send static resources to clients. Use this ONLY when developing.

host and port

Default host is 127.0.0.1, and port is 9050

handler_config

This section configures the backend, e.g. swoole or workerman.

Swoole

As an example, if want to set worker_num to 8, you can set .env:

 LARAVOOLE_WORKER_NUM=8

or set config/laravoole.php:

[
    'handler_config' => [
        'worker_num' => 8,
    ]
]

See Swoole's document:

简体中文

English

Workerman

As an example, if want to set worker_num to 8, you can set .env:

 LARAVOOLE_COUNT=8

or set config/laravoole.php:

[
    'handler_config' => [
        'count' => 8,
    ]
]

See Workerman's document:

简体中文

English

Websocket Usage

Subprotocols

See Mozilla's Document: Writing WebSocket server

The default subprotocol is jsonrpc, but has some different: params is an object, and two more properties:

status as HTTP status code

method is the same as request's method

You can define your own subprotocol, by implements Laravoole\WebsocketCodec\CodecInterface and add to config/laravoole.php.

Client Example:

WebSocket Test

WebSocket Test

">
>
<meta charset="utf-8" />
<title>WebSocket Testtitle>
<style>
p{word-wrap: break-word;}
tr:nth-child(odd){background-color: #ccc}
tr:nth-child(even){background-color: #eee}
style>
<h2>WebSocket Testh2>
<table><tbody id="output">tbody>table>
<script>
    var wsUri = "ws://localhost:9050/websocket";
    var protocols = ['jsonrpc'];
    var output = document.getElementById("output");

    function send(message) {
        websocket.send(message);
        log('Sent', message);
    }

    function log(type, str) {
        str = str.replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>');
        output.insertAdjacentHTML('beforeend', '' + type + '

' + htmlEscape(str) + '

'
); } websocket = new WebSocket(wsUri, protocols); websocket.onopen = function(evt) { log('Status', "Connection opened"); send(JSON.stringify({method: '/', params: {hello: 'world'}, id: 1})); setTimeout(function(){ websocket.close() },1000) }; websocket.onclose = function(evt) { log('Status', "Connection closed") }; websocket.onmessage = function(evt) { log('Received', evt.data) }; websocket.onerror = function(evt) { log('Error', evt.data) }; script> html>

Work with nginx

server {
    listen       80;
    server_name  localhost;

    root /path/to/laravel/public;

    location / {
            try_files $uri $uri/ @laravoole;
            index  index.html index.htm index.php;
        }

    # http
    location @laravoole {
        proxy_set_header   Host $host:$server_port;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;

        proxy_pass http://127.0.0.1:9050;
    }

    # fastcgi
    location @laravoole {
        include fastcgi_params;
        fastcgi_pass 127.0.0.1:9050;
    }

    # websocket
    # send close if there has not an upgrade header
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }
    location /websocket {
        proxy_connect_timeout 7d;
        proxy_send_timeout 7d;
        proxy_read_timeout 7d;
        proxy_pass http://127.0.0.1:9050;
        proxy_http_version 1.1;
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

License

MIT

Comments
  •  'Undefined offset: 24670' in /xxxxx/vendor/garveen/laravoole/src/Protocol/FastCGI.php:113

    'Undefined offset: 24670' in /xxxxx/vendor/garveen/laravoole/src/Protocol/FastCGI.php:113

      [Symfony\Component\Debug\Exception\FatalErrorException]                                                                                                                                                            
      Uncaught exception 'ErrorException' with message 'Undefined offset: 24670' in /xxxxx/vendor/garveen/laravoole/src/Protocol/FastCGI.php:113                                                  
      Stack trace:                                                                                                                                                                                                       
      #0 /xxxxx/vendor/garveen/laravoole/src/Protocol/FastCGI.php(113): Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(8, 'Undefined offse...', '/Users/ql/wwwro...', 113, Array)  
      #1 /xxxxx/vendor/garveen/laravoole/src/Wrapper/SwooleFastCGIWrapper.php(33): Laravoole\Wrapper\SwooleFastCGIWrapper->receive(4, '\xE1\x84\xA7\x12e\xBA\x94YRfD\x99\x16e\xB6...')            
      #2 [internal function]: Laravoole\Wrapper\SwooleFastCGIWrapper->onReceive(Object(swoole_server), 4, 0, '\xE1\x84\xA7\x12e\xBA\x94YRfD\x99\x16e\xB6...')                                                            
      #3 /xxxxx/vendor/garveen/laravoole/src/Wrapper/SwooleFastCGIWrapper.php(28): swoole_server->start()                                                                                         
      #4 /xxxxx/vendor/garveen/laravoole/src/Server.php(27): Laravoole\Wrapper\SwooleFastCGIWrapper->start()                                                                                      
      #5 /xxxxx/vendo                                                                                                                                                                             
    
    [2017-01-16 11:03:54 *73301.0]  ERROR   zm_deactivate_swoole (ERROR 103): Fatal error: Uncaught exception 'ErrorException' with message 'Undefined offset: 24670' in /xxxxx/vendor/garveen/laravoole/src/Protocol/FastCGI.php:113
    Stack trace:
    #0 /xxxxx/vendor/garveen/laravoole/src/Protocol/FastCGI.php(113): Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(8, 'Undefined offse...', '/Users/ql/wwwro...', 113, Array)
    #1 /xxxxx/vendor/garveen/laravoole/src/Wrapper/SwooleFas
    [2017-01-16 11:03:54 $73240.0]  WARNING swManager_check_exit_status: worker#0 abnormal exit, status=255, signal=0
    Unexpected FastCGI-record #. Request ID: 4
    Unexpected FastCGI-record #. Request ID: 4
    Unexpected FastCGI-record #. Request ID: 4
    Unexpected FastCGI-record #. Request ID: 4
    Unexpected FastCGI-record #. Request ID: 4
    
    

    大文件上传,用了分片上传,每个分片3M, 只有部分分片能够上传成功, max_request改大了也没用~

    opened by ql2005 14
  • Empty POST data

    Empty POST data

    When I send POST request $request->get('field') is null but in GET request all works fine. Little hack: $data = $request->all(); $data['field'] work. Any ideas?

    opened by OSDDQD 7
  • 服务开启不成功?

    服务开启不成功?

    [2017-07-13 09:46:22 #29484.0] NOTICE Server is shutdown now. [2017-07-13 10:41:23 #30535.0] NOTICE Server is shutdown now. [2017-07-13 10:42:02 #31229.0] NOTICE Server is shutdown now. [2017-07-14 01:40:13 #2603.0] NOTICE Server is shutdown now.

    opened by qiumzh 4
  • PHP Fatal error:  Uncaught exception 'ReflectionException' with message 'Class App\Http\Kernel does not exist'

    PHP Fatal error: Uncaught exception 'ReflectionException' with message 'Class App\Http\Kernel does not exist'

    Hi,

    If I changed Laravel root namespace like php artisan app:name "Passport" Then composer.json

    {
    "autoload": {
        "classmap": [
          "database"
        ],
        "psr-4": {
          "Passport\\": "app/"
        }
      }
    }
    

    But, there is hard code in file Base.php line 208

    $app->singleton(
        \Illuminate\Contracts\Http\Kernel::class,
        \App\Http\Kernel::class
    );
    
    $app->singleton(
        \Illuminate\Contracts\Console\Kernel::class,
        \App\Console\Kernel::class
    );
    
    $app->singleton(
        \Illuminate\Contracts\Debug\ExceptionHandler::class,
        \App\Exceptions\Handler::class
    );
    
    opened by hhxsv5 4
  • 调用了不存在的方法,导致服务启动不起来

    调用了不存在的方法,导致服务启动不起来

    src/Wrapper/SwooleHttpWrapper.php 第18行调用了不存在的方法set if (!empty($this->settings)) { $this->server->set($this->settings); } $this->server的类型是swoole_http_server 可以参考文档:http://wiki.swoole.com/wiki/page/327.html

    opened by gaohuag 4
  • 关于事件名变更问题

    关于事件名变更问题

    Hi, laravoole.on_request更名为laravoole.requesting,因此项目已用于生产,所以此次影响较大,不过现在开始锁版本。

    关于文档中的版本锁定:之前~0.2 表示>=0.2 && <=1.0,导致composer update时直接回升级到0.4.1。

    所以建议使用~0.4.1锁定到三级版本号,>=0.4.1&&<=0.5

    谢谢!

    opened by hhxsv5 3
  • CLI mode

    CLI mode

    Example: Function phpinfo() has different output between cli and cgi. But laravoole is running under CLI mode, so far I think avoiding these functions is the only way.

    opened by hhxsv5 3
  • Is it possible to add some hooks when worker process deal with onReqeust method?

    Is it possible to add some hooks when worker process deal with onReqeust method?

    // vendor/garveen/laravoole/src/Base.php
    ......
    $kernel = $this->kernel;
    
    // do some others action before deal request
    if (isset($this->wrapper_config['on_before_deal_request_cb']) && Arr::accessible($this->wrapper_config['on_before_deal_request_cb'])) {
        $dealActions = $this->wrapper_config['on_before_deal_request_cb'];
        foreach ($dealActions as $action) {
            if (is_callable($action)) {
                call_user_func($action, [$this->app]);
            }
        }
    }
    
    if (!$illuminate_request) {
        $illuminate_request = $this->dealWithRequest($request);
    }
    ......
    

    Is it possible to add some hooks when worker process deal with onReqeust method?

    Thanks author to offer this nice package. Ur... Can you speak Chinese?

    opened by happen-zhang 3
  • 求助,使用SwooleWebSocket怎么配置和响应请求

    求助,使用SwooleWebSocket怎么配置和响应请求

    配置了:

    #laravoole
    LARAVOOLE_MODE=SwooleWebSocket
    

    可以正常启动服务,但是监听不到响应的事件,也不知道如何返回相应的response

            \Event::listen(
                'laravoole.requesting',
                function ($request) {
                    Logger::getLogger('laravoole_dev')->info('11');
                    //                Logger::getLogger('laravoole_dev')->info(PHP_EOL . json_encode($request) . PHP_EOL);
                }
            );
    
            \Event::listen(
                'laravoole.requested',
                function ($request, $response) {
                    Logger::getLogger('laravoole_dev')->info('11');
                    //                Logger::getLogger('laravoole_dev')->info(PHP_EOL . json_encode($request) . PHP_EOL);
                    return $response;
                }
            );
    
    
    opened by zeasly 2
  • feature: customized wrapper class support

    feature: customized wrapper class support

    It's an awesome package! But sometimes I'd like to make some change on a wrapper to satisfy my own requirements (like doing someting before the swoole server started). So I think implement my wrapper might be a good idea. And I also created a pr for this. 😁 #27

    opened by chxj1992 2
  • customized wrapper class support

    customized wrapper class support

    This commit brings up the require autoloader code and makes some changes in the way to load a wrapper class ( fully qualified class name is acceptable), which allows developers to implement there own wrapper

    opened by chxj1992 2
  • SwooleWebSocketWrapper surport laravel 5.5 and newly swoole

    SwooleWebSocketWrapper surport laravel 5.5 and newly swoole

        public function onHandShake(swoole_http_request $request, swoole_http_response $response)
        {
            $protocol = false;
            if (isset($request->header['sec-websocket-protocol'])) {
                $protocols = preg_split('~,\s*~', $request->header['sec-websocket-protocol']);
                foreach ($protocols as $protocol) {
                    if (isset(static::$protocolCodecs[$protocol])) {
                        break;
                    }
                }
                if ($protocol) {
                    $response->header('Sec-WebSocket-Protocol', $protocol);
                }
            }
    
            if (!$protocol) {
                $protocol = $this->defaultProtocol;
            }
    
            $secKey = $request->header['sec-websocket-key'];
            $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
    
            foreach ([
                "Upgrade" => "websocket",
                "Connection" => "Upgrade",
                "Sec-WebSocket-Version" => "13",
                "Sec-WebSocket-Accept" => $secAccept,
            ] as $k => $v) {
                $response->header($k, $v);
            }
            $response->status(101);
            $response->end();
            $laravooleRequest = new Request($request->fd);
            foreach ($request as $k => $v) {
                $laravooleRequest->$k = $v;
            }
            $this->connections[$request->fd] = ['request' => $laravooleRequest, 'protocol' => static::$protocolCodecs[$protocol]];
            $this->unfinished[$request->fd] = '';
            return true;
    
        }``
    

    needs to add "$response->end(); " after "$response->status(101);"

    $response->end();

    opened by PickApig 0
  • In LaravooleCommand.php line 142 Address 127.0.0.1:9051 already in use?

    In LaravooleCommand.php line 142 Address 127.0.0.1:9051 already in use?

    启动一直出现这个错误,用netstat查看发现9051这个端口并没有被占用。在代码中查看后,去掉了LaravooleCommand.php 139行stream_socket_server函数前面的@符号,启动后才发现这个函数被禁用了,不是端口占用的原因,个人觉得去掉这个@符号比较好,还有下面的异常应该抛出stream_socket_server的第三个参数可能比较好点,因为不一定是端口占用

    opened by xnnyeYp 0
  • 0.5.1版本开启服务器后引入autoload.php报错

    0.5.1版本开启服务器后引入autoload.php报错

    PHP Warning:  require(/home/vagrant/code/pilitest/bootstrap/autoload.php): failed to open stream: No such file or directory in /home/vagrant/code/pilitest/vendor/garveen/laravoole/src/Base.php on line 72
    
    PHP Fatal error:  require(): Failed opening required '/home/vagrant/code/pilitest/bootstrap/autoload.php' (include_path='.:/usr/share/php') in /home/vagrant/code/pilitest/vendor/garveen/laravoole/src/Base.php on line 72
    

    我的修改是 将Base.php67行的

            if (file_exists(__DIR__ . '/../vendor/autoload.php')) {
                require __DIR__ . '/../vendor/autoload.php';
    

    直接修改为

            if (file_exists(__DIR__ . '/../../../autoload.php')) {
                require __DIR__ . '/../../../autoload.php';
    

    目前运行正常。 请问这是一个BUG吗?这样修改是否有效?

    opened by chenzeshu 0
Owner
Garveen
Garveen
Laravel Kickstart is a Laravel starter configuration that helps you build Laravel websites faster.

Laravel Kickstart What is Laravel Kickstart? Laravel Kickstart is a Laravel starter configuration that helps you build Laravel websites faster. It com

Sam Rapaport 46 Oct 1, 2022
Collection of the Laravel/Eloquent Model classes that allows you to get data directly from a Magento 2 database.

Laragento LAravel MAgento Micro services Magento 2 has legacy code based on abandoned Zend Framework 1 with really ugly ORM on top of outdated Zend_DB

Egor Shitikov 87 Nov 26, 2022
Get started using SELCOM APIs with Laravel framework

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Bruno 2 Jan 13, 2022
Laravel Setting - Easily save, update and get titles, descriptions, and more. it is very easy to use.

Laravel Setting Easily save, update and get titles, descriptions, and more. it is very easy to use. This is great for storing and receiving general si

Ali Ranjbar 2 Aug 23, 2022
Laravel package for manage your URL redirects in database or other sources to get better SEO results

Laravel 8 and 9 package to manage URL redirections inside your Laravel application using different data sources. It allows a better SEO support for your Laravel site.

Siro Díaz Palazón 51 Sep 21, 2022
This template should help get you started developing with laravel 9 + Vue 3 in Vite + Tailwind

simple-project This template should help get you started developing with laravel 9 + Vue 3 in Vite + Tailwind

Yemeni Open Source 4 Oct 5, 2022
Get estimated read time of an article. Similar to medium.com's "x min read". Multilingual including right-to-left written languages. Supports JSON, Array and String output.

Read Time Calculates the read time of an article. Output string e.g: x min read or 5 minutes read. Features Multilingual translations support. Static

Waqar Ahmed 8 Dec 9, 2022
Gallium is a TALL stack starter kit offering a robust set of options enabling you to get up and running in a snap.

Very short description of the package This is where your description should go. Try and limit it to a paragraph or two, and maybe throw in a mention o

null 1 Nov 20, 2021
This is a solution implementation for the coderbyte question, CLEAN GET REQUEST RESULT.

This is a solution implementation for the coderbyte question, CLEAN GET REQUEST RESULT. Two solutions are proposed, the first is a brute force approach while the other is an improved time complexity solution.

null 3 May 23, 2022
Get the thumbnail of youtube and vimeo videos from the url. The returned information is ID and URL of the thumbnail

Video Thumbnail URL Get the thumbnail of youtube and vimeo videos from the url. The returned information is ID and URL of the thumbnail Installation I

Fernando Valler 2 Jan 22, 2022
An easy way to get vendor and package data from Packagist via API calls

Laravel Packagist Laravel Packagist (LaravelPackagist) is a package for Laravel 5 to interact with the packagist api quickly and easily. Table of cont

Jeremy Kenedy 5 Jul 18, 2022
An abstraction layer to get data from array or a file with dot-notation

Alex Unruh - Config This library is based on the Laravel config concept. It values performance and was built on top of the library Dflydev Dot Access

Alexandre Odair 3 May 20, 2022
Get info from any web service or page

Embed PHP library to get information from any web page (using oembed, opengraph, twitter-cards, scrapping the html, etc). It's compatible with any web

Oscar Otero 1.9k Jan 4, 2023
How to get cookies from users' browser and send the information to your email address and telegram bot

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

MAXWELL 3 Dec 3, 2022
List of 77 languages for Laravel Framework 4, 5, 6, 7 and 8, Laravel Jetstream , Laravel Fortify, Laravel Breeze, Laravel Cashier, Laravel Nova and Laravel Spark.

Laravel Lang In this repository, you can find the lang files for the Laravel Framework 4/5/6/7/8, Laravel Jetstream , Laravel Fortify, Laravel Cashier

Laravel Lang 6.9k Jan 2, 2023
⚡ Laravel Charts — Build charts using laravel. The laravel adapter for Chartisan.

What is laravel charts? Charts is a Laravel library used to create Charts using Chartisan. Chartisan does already have a PHP adapter. However, this li

Erik C. Forés 31 Dec 18, 2022
Laravel User Activity Log - a package for Laravel 8.x that provides easy to use features to log the activities of the users of your Laravel app

Laravel User Activity Log - a package for Laravel 8.x that provides easy to use features to log the activities of the users of your Laravel app

null 9 Dec 14, 2022
laravel - Potion is a pure PHP asset manager for Laravel 5 based off of Assetic.

laravel-potion Potion is a pure PHP asset manager for Laravel based off of Assetic. Description Laravel 5 comes with a great asset manager called Elix

Matthew R. Miller 61 Mar 1, 2022
Laravel mercado pago es un paquete que te ayuda a implementar el sdk de mercado pago para php en laravel

Introducción Laravel mercado pago es un paquete que te ayuda a implementar el sdk de mercado pago para php en laravel. ?? Instalación Para instalar ut

null 7 Sep 23, 2022