文档章节

实现FastCGI协议替代PHP-FPM提高Laravel接口性能50倍

ChefXu
 ChefXu
发布于 2016/04/05 19:24
字数 941
阅读 1150
收藏 5

关于Stone

Stone是一个基于swoole的php应用,目的是为了提高基于laravel实现的接口性能。当然, 理论上适用于任何框架。 目前这个项目有特定的应用场景限制, 主要适用于无状态的接口调用的场景。能在继续使用Laravel优雅代码的前提下得到极大的性能提升。

其实,包含视图和Session请求也可以通过这个手段来优化, 只是涉及到很多修改laravel的地方, 有点过于复杂。 对此感兴趣的朋友可以参考一个叫LaravelFly的项目。

我特意写了一个基于laravel5.2的例子, 性能对比大概是120QPS vs. 7600QPS。 详情请看:https://github.com/chefxu/stone-laravel-example

原理说明

  1. 本项目可以理解为一个胶水项目,把swoole和laravel较好的揉和起来,既享受Laravel优雅的编码体验又享受swoole的高性能。
  2. 通过swoole将应用常驻内存, 避免每次请求前都需要初始化框架代码,请求后都需要销毁框架代码,大大提高接口的性能。
  3. 实现fastcgi协议, 主要是为了继续使用成熟的nginx,也能保持架构的简单。
  4. 简单来说就是 nginx+stone(swoole+fastcgi) 替换 nginx+PHP-FPM。

性能对比

测试内容为输出一个简单的json数组, 具体测试:https://github.com/chefxu/stone-laravel-example#performance

  1. nginx + stone + laravel5.2

     Server Software:        stone
     Server Hostname:        192.168.1.10
     Server Port:            7412
    
     Document Path:          /server/workbench/listdata
     Document Length:        211 bytes
    
     Concurrency Level:      100
     Time taken for tests:   1.305 seconds
     Complete requests:      10000
     Failed requests:        0
     Total transferred:      3400000 bytes
     HTML transferred:       2110000 bytes
     Requests per second:    7662.11 [#/sec] (mean)
     Time per request:       13.051 [ms] (mean)
     Time per request:       0.131 [ms] (mean, across all concurrent requests)
     Transfer rate:          2544.06 [Kbytes/sec] received
    
  2. nginx + php-fpm + laravel5.2

     Server Software:        nginx
     Server Hostname:        192.168.1.10
     Server Port:            7412
    
     Document Path:          /workbench/listdata
     Document Length:        211 bytes
    
     Concurrency Level:      30
     Time taken for tests:   8.335 seconds
     Complete requests:      1000
     Failed requests:        0
     Total transferred:      1185252 bytes
     HTML transferred:       211000 bytes
     Requests per second:    119.97 [#/sec] (mean)
     Time per request:       250.054 [ms] (mean)
     Time per request:       8.335 [ms] (mean, across all concurrent requests)
     Transfer rate:          138.87 [Kbytes/sec] received
    

使用说明

本项目仅为学习交流使用, 不建议在生成环境下使用,如因在生成环境下使用带来的损失, 本人一概不负责任。

  1. composer安装包 composer require qufenqi/stone

  2. 引入artisan管理脚本, app/Console/Kernel.php 添加一行

     protected $commands = [
         Commands\Inspire::class,
         \Qufenqi\Stone\Console\Commands\StoneServer::class,
     ];
    
  3. 引入ServiceProvider,config/app.php添加一行

     Illuminate\Validation\ValidationServiceProvider::class,
     Illuminate\View\ViewServiceProvider::class,
     Qufenqi\Stone\StoneServiceProvider::class,
    
  4. 自定义handler类

    每一次请求需要有一个handler去处理,因为处理请求属于业务的一部分, 所以交由业务层去处理。 要求实现RequestHandler接口。

     <?php namespace App\Servers;
    
     use Qufenqi\Stone\Contracts\RequestHandler;
     use App;
     use Log;
     use Exception;
    
     class Handler implements RequestHandler
     {
         public function process($url, $params = [])
         {
             list($class, $method) = $this->route($url);
    
             if (!class_exists($class)) {
                 return $this->output(['code' => -1, 'message' => $class . '不存在', 'data' => null]);
             }
    
             $instance = App::make($class);
    
             if (!method_exists($instance, $method)) {
                 return $this->output(['code' => -1, 'message' => $method . '不存在', 'data' => null]);
             }
    
             try {
                 $data = call_user_func_array([$instance, $method], $params);
             } catch (Exception $e) {
                 Log::error($e);
                 return $this->output(['code' => -1, 'message' => '系统繁忙', 'data' => null]);
             }
    
             return $this->output($data);
         }
    
         public function output($data)
         {
             return json_encode($data);
         }
    
         public function route($url)
         {
             $path = parse_url($url, PHP_URL_PATH);
             $path = explode('/', $path);
             $class = $method = '';
    
             if (!empty($path[2])) {
                 $class = 'App\\Servers\\' . ucfirst(camel_case($path[2] . '_server'));
             }
    
             if (!empty($path[3])) {
                 $method = camel_case($path[3]);
             }
    
             return [$class, $method];
         }
     }
    
  5. 新增自定义配置 config/stone.php

     <?php
     return [
         'handler' => 'App\Servers\Handler', // 设置具体的业务处理类
         'user' => 'apple', // 设置运行的用户
         'group' => 'apple', // 设置运行的组
         'port' => 9101, // 监听的端口
     ];
    
  6. 管理服务

     sudo php ./artisan stone:server --start --stop --reload
    
  7. 调试模式

     sudo php ./artisan stone:server --start --debug
    
  8. 修改nginx配置

     location /server/ {
         fastcgi_pass 127.0.0.1:9101;
         fastcgi_split_path_info ^(.+\.php)(/.+)$;
         fastcgi_index index.php;
         include fastcgi.conf;
     }
    

© 著作权归作者所有

ChefXu
粉丝 12
博文 6
码字总数 11518
作品 0
海淀
程序员
私信 提问

暂无文章

阿里P8架构师谈:如何打造一份高并发编程知识体系

1.问题 1、什么是线程的交互方式? 2、如何区分线程的同步/异步,阻塞/非阻塞? 3、什么是线程安全,如何做到线程安全? 4、如何区分并发模型? 5、何谓响应式编程? 6、操作系统如何调度多线...

小刀爱编程
18分钟前
1
0
比特币:如何用地址查询交易?

在比特币应用开发中,一个常见的问题就是,在知道比特币地址的情况下,如何查询这个地址上发生的所有交易?或者类似的说法,如何查询一个指定的比特币地址发生的所有交易? 本文将给出这一问...

汇智网教程
21分钟前
1
0
Spring Boot 下,敏感词及特殊字符过滤处理方式

背景: 技术采用的是 Spring Boot ,请求方法主要为 POST, 请求使用较多的注解为 @RequestBody 交付测试人员进行测试,测试人员在对模糊搜索模块进行了各种特殊字符的搜索,以至于敏感词和特...

Ryan-瑞恩
25分钟前
7
0
使用 Jenkins X 渐进式交付

本文首发于:Jenkins 中文社区 这是渐进式交付系列的第二篇文章,第一篇请看:Kubernetes 中的渐进式交付:蓝绿部署和金丝雀部署。 我使用的我的 Croc Hunter 示例项目评估了 Jenkins X 中金...

Jenkins中文社区
32分钟前
2
0
零基础学算法->PI

本文章是介绍几种计算PI的方法 1.概率法计算PI(又称蒙特卡罗法) 1.1 定义,过程 在半径为1的圆1/4的区域,通过随机函数产生横纵坐标值x,y;当x*x+y*y<=1时,满足条件。 1.2 结果: 因为是随机...

tedzheng
36分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部