Skip to content
This repository was archived by the owner on Mar 24, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 21 additions & 138 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,148 +1,32 @@
# Laravel-Swoole

![php-badge](https://img.shields.io/badge/php-%3E%3D%205.5.9-8892BF.svg)
![php-badge](https://img.shields.io/badge/php-%3E%3D%207.1-8892BF.svg)
[![packagist-badge](https://img.shields.io/packagist/v/swooletw/laravel-swoole.svg)](https://packagist.org/packages/swooletw/laravel-swoole)
[![Total Downloads](https://poser.pugx.org/swooletw/laravel-swoole/downloads)](https://packagist.org/packages/swooletw/laravel-swoole)
[![travis-badge](https://api.travis-ci.org/swooletw/laravel-swoole.svg?branch=master)](https://travis-ci.org/swooletw/laravel-swoole)

This package provides a high performance HTTP server to speed up your laravel/lumen application based on [Swoole](http://www.swoole.com/).

## Version Compatibility

| PHP | Laravel | Lumen | Swoole |
|:-------:|:-------:|:-----:|:-------:|
| >=5.5.9 | ~5.1 | ~5.1 | >=1.9.3 |
| >=7.1 | ~5.1 | ~5.1 | >=1.9.3 |

## Installation
## Features

Require this package with composer by using the following command:
* Run **Laravel/Lumen** application on top of **Swoole**.
* Outstanding performance boosting up to **30x**.
* Sandbox mode to isolate app container.
* Support running websocket server in **Laravel**.
* Support `Socket.io` protocol.
* Support Swoole table for cross-process data sharing.

```
$ composer require swooletw/laravel-swoole
```

> This package relies on Swoole. Please make sure your machine has been installed the Swoole extension. Using this command to install quickly: `pecl install swoole`. Visit the [official website](https://wiki.swoole.com/wiki/page/6.html) for more information.

Then, add the service provider:

If you are using Laravel, add the service provider to the providers array in `config/app.php`:

```php
[
'providers' => [
SwooleTW\Http\LaravelServiceProvider::class,
],
]
```

If you are using Lumen, append the following code to `bootstrap/app.php`:

```php
$app->register(SwooleTW\Http\LumenServiceProvider::class);
```

## Configuration

If you want to change the default configurations, please run the following command to generate a configuration file `http.php` in directory `config/`:

```
$ php artisan vendor:publish
```
## Documentation

`server.host`: The swoole_http_server host.
Please see [Wiki](https://github.com/swooletw/laravel-swoole/wiki)

`server.port`: The swoole_http_server port.

`server.options`: The configurations for `Swoole\Server`. To get more information about swoole server, please read [the official documentation](https://wiki.swoole.com/wiki/page/274.html).

For example, if you want to set the 'max_request':

```php
[
'server' => [
'options' => [
'max_request' => 1000,
],
]
]
```

## Command

> The swoole_http_server can only run in cli environment, and this package provides convenient artisan commands to manage it.
> By default, you can visit your site at http://127.0.0.1:1215

Start the swoole_http_server:

```
$ php artisan swoole:http start
```

Stop the swoole_http_server:

```
$ php artisan swoole:http stop
```

Restart the swoole_http_server:

```
$ php artisan swoole:http restart
```

Reload the swoole_http_server:

```
$ php artisan swoole:http reload
```

Now, you can run the following command to start the **swoole_http_server**.

```
$ php artisan swoole:http start
```

## Nginx Configuration

> The support of swoole_http_server for Http is not complete. So, you should configure the domains via nginx proxy in your production environment.

```nginx
server {
listen 80;
server_name your.domain.com;
root /path/to/laravel/public;
index index.php;

location = /index.php {
# Ensure that there is no such file named "not_exists"
# in your "public" directory.
try_files /not_exists @swoole;
}

location / {
try_files $uri $uri/ @swoole;
}

location @swoole {
set $suffix "";

if ($uri = /index.php) {
set $suffix "/";
}

proxy_set_header Host $host;
proxy_set_header SERVER_PORT $server_port;
proxy_set_header REMOTE_ADDR $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# IF https
# proxy_set_header HTTPS "on";

proxy_pass http://127.0.0.1:1215$suffix;
}
}
```

## Performance Reference
## Benchmark

Test with clean Lumen 5.5, using MacBook Air 13, 2015.
Benchmarking Tool: [wrk](https://github.com/wg/wrk)
Expand Down Expand Up @@ -177,20 +61,19 @@ Requests/sec: 8717.00
Transfer/sec: 1.55MB
```

## Notices

1. Please reload or restart the swoole_http_server after released your code. Because the Laravel program will be kept in memory after the swoole_http_server started. That's why the swoole_http_server has high performance.
2. Never use `dd()`, `exit()` or `die()` function to print your debug message. It will terminate your swoole worker unexpectedly.
3. You should have basic knowledge of multi-process programming and swoole. If you still write your code with a single-process conception, your app might have unexpected bugs.

## Support

Bugs and feature request are tracked on [Github](https://github.com/swooletw/laravel-swoole-http/issues).
Bugs and feature request are tracked on [Github](https://github.com/swooletw/laravel-swoole/issues).

## Credits

The original author of this package: [Huang-Yi](https://github.com/huang-yi)
[Huang-Yi](https://github.com/huang-yi)

## License

The Laravel-Swoole-Http package is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT).
The Laravel-Swoole package is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT).

## Support on Beerpay
Hey dude! Help me out for a couple of :beers:!

[![Beerpay](https://beerpay.io/swooletw/laravel-swoole/badge.svg?style=beer-square)](https://beerpay.io/swooletw/laravel-swoole) [![Beerpay](https://beerpay.io/swooletw/laravel-swoole/make-wish.svg?style=flat-square)](https://beerpay.io/swooletw/laravel-swoole?focus=wish)
21 changes: 16 additions & 5 deletions config/swoole_websocket.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@
*/
'handler' => SwooleTW\Http\Websocket\SocketIO\WebsocketHandler::class,

/*
|--------------------------------------------------------------------------
| Default frame parser
| Replace it if you want to customize your websocket payload
|--------------------------------------------------------------------------
*/
'parser' => SwooleTW\Http\Websocket\SocketIO\SocketIOParser::class,

/*
|--------------------------------------------------------------------------
| Websocket route file path
Expand All @@ -18,18 +26,21 @@

/*
|--------------------------------------------------------------------------
| Default websocket driver
| Default middleware for on connect request
|--------------------------------------------------------------------------
*/
'default' => 'table',
'middleware' => [
// SwooleTW\Http\Websocket\Middleware\DecryptCookies::class,
// SwooleTW\Http\Websocket\Middleware\StartSession::class,
// SwooleTW\Http\Websocket\Middleware\Authenticate::class,
],

/*
|--------------------------------------------------------------------------
| Default frame parser
| Replace it if you want to customize your websocket payload
| Default websocket driver
|--------------------------------------------------------------------------
*/
'parser' => SwooleTW\Http\Websocket\SocketIO\SocketIOParser::class,
'default' => 'table',

/*
|--------------------------------------------------------------------------
Expand Down
9 changes: 9 additions & 0 deletions routes/websocket.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php

use Illuminate\Http\Request
use SwooleTW\Http\Websocket\Facades\Websocket;

/*
Expand All @@ -11,6 +12,14 @@
|
*/

Websocket::on('connect', function ($websocket, Request $request) {
// called while socket on connect
});

Websocket::on('close', function ($websocket) {
// called while socket on close
});

Websocket::on('example', function ($websocket, $data) {
$websocket->emit('message', $data);
});
Expand Down
35 changes: 19 additions & 16 deletions src/Server/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class Application
*/
protected $resolves = [
'view', 'files', 'session', 'session.store', 'routes',
'db', 'db.factory', 'cache', 'cache.store', 'config',
'db', 'db.factory', 'cache', 'cache.store', 'config', 'cookie',
'encrypter', 'hash', 'router', 'translator', 'url', 'log'
];

Expand Down Expand Up @@ -247,22 +247,27 @@ public function getFramework()
*/
public function run(Request $request)
{
ob_start();
$shouldUseOb = $this->application['config']->get('swoole_http.ob_output', true);

if ($shouldUseOb) {
ob_start();
}

// handle request with laravel or lumen
$method = sprintf('run%s', ucfirst($this->framework));
$response = $this->$method($request);

// prepare content for ob
$content = '';
$shouldUseOb = $this->application['config']->get('swoole_http.ob_output', true);
if ($response instanceof StreamedResponse ||
$response instanceof BinaryFileResponse) {
$shouldUseOb = false;
} elseif ($response instanceof SymfonyResponse) {
$content = $response->getContent();
} else {
$content = (string) $response;
if ($shouldUseOb) {
if ($response instanceof StreamedResponse ||
$response instanceof BinaryFileResponse) {
$shouldUseOb = false;
} elseif ($response instanceof SymfonyResponse) {
$content = $response->getContent();
} else {
$content = (string) $response;
}
}

// process terminating logics
Expand All @@ -273,7 +278,9 @@ public function run(Request $request)
$response->setContent(ob_get_contents());
}

ob_end_clean();
if ($shouldUseOb) {
ob_end_clean();
}

return $response;
}
Expand Down Expand Up @@ -372,11 +379,7 @@ protected function terminateLaravel(Request $request, $response)
// clean laravel session
if ($request->hasSession()) {
$session = $request->getSession();
if (method_exists($session, 'clear')) {
$session->clear();
} elseif (method_exists($session, 'flush')) {
$session->flush();
}
$session->flush();
}

// clean laravel cookie queue
Expand Down
14 changes: 2 additions & 12 deletions src/Server/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ public function onWorkerStart(HttpServer $server)
$this->bindToLaravelApp();

// set application to sandbox environment
if ($this->isSandbox) {
if ($this->isSandbox || $this->isWebsocket) {
$this->sandbox = Sandbox::make($this->getApplication());
}

Expand Down Expand Up @@ -466,16 +466,6 @@ protected function setProcessName($process)
*/
protected function logServerError(Exception $e)
{
$logFile = $this->container['config']->get('swoole_http.server.options.log_file');

try {
$output = fopen($logFile ,'w');
} catch (Exception $e) {
$output = STDOUT;
}

$prefix = sprintf("[%s #%d *%d]\tERROR\t", date('Y-m-d H:i:s'), $this->server->master_pid, $this->server->worker_id);

fwrite($output, sprintf('%s%s(%d): %s', $prefix, $e->getFile(), $e->getLine(), $e->getMessage()) . PHP_EOL);
$this->app[ExceptionHandler::class]->report($e);
}
}
Loading