一、前言

前两天在 Laravel china  发现了一个包,叫 Laravel-S ,这个包基于 Swoole ,将 Laravel  框架预加载到 内存,加之 Swoole 一系列的黑科技,可以将 Laravel  加速到非常快的地步。在给自己的项目加上这个包的过程中,遇到了一些问题,记录在此,以示后来。

二、正文

1.Laravel Datatables 适配问题

如果你在项目里用到了 Laravel datatables  这个包, 那么如果你直接用的话对表格操作了一定的次数(比如连续翻页了大于等于 Worker  的进程数后)就出错了,观察之后发现是 draw 的数不对,这个数目是 datatables   用于防 CSRF 的。仔细阅读源码发现,是 datatables.request 这个单例一直存在,同时 swoole 的分发模式是1,也就是轮询,一遍翻页之后每个 Worker  都被“污染”了。

所以,要将其在每次请求结束的时候清除掉。

EventServiceProvider

Event::listen('laravels.generated_response', function (\Illuminate\Http\Request $req, \Symfony\Component\HttpFoundation\Response $rsp, $app) {
            if (class_exists('\Yajra\DataTables\DataTablesServiceProvider', false)) {
                $app->forgetInstance('datatables.request');
                Facade::clearResolvedInstance('datatables.request');
            }
        });

2.Laravel passport 签发 Token  的内容格式问题

当你使用 Laravel passport  这个包的时候,如果你请求 /oauth/token 这个接口尝试请求签名,内容格式是 json 的时候,就会提示你参数非法,好像没输入参数一样,但当使用 form-data 的时候就没问题。再研读源码发现应该是 Laravel  的 请求转换为 PSR-7 请求时出现了问题,再来看看 Laravel-S  的请求处理,在 json 那块是直接置 null,让 Laravel  来解析了,确实直接用转换后的结果是可以的,但如果像上面这样再次转换可就有问题了。

修复方法在此处提了个 PR,当然我觉得可能有更优雅的方案。

if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/json')
            && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('POST', 'PUT', 'DELETE', 'PATCH'))
        ) {
            $data = json_decode($request->getContent(), true);
            if($data != NULL) {
                $request->request = new ParameterBag($data);

                $json = $reflection->getProperty('json');
                $json->setAccessible(true);
                $json->setValue($request, $request->request);
            }
        }

3.Laravel passport  配置参数污染问题

这个问题花了我差不多一天来排查。一开始是页面会莫名的退出登录,然后再次尝试登录的时候就出错了。查看日志提示是 AuthManager  的某个方法未定义。

Method attempt does not exist. {“exception”:”[object] (BadMethodCallException(code: 0): Method attempt does not exist.

这就有点奇怪了,明明在 php-fpm  下啥事都没有。更加邪门的是,这个在正式环境下才有问题,测试环境下一点问题都没有。后来仔细排查,阅读了这部分的所有相关源码之后,发现 Auth driver  加载的居然是 api 的,然而这个是 web 的路由呀。仔细追查下去,发现是 Laravel passport  在加载时改写了 config,在调用 shouldUse 方法时,如果是 api 路由,就把默认的 driver 改成他自己了,这样在 api 路由当然没问题,可老铁。。。如果处理这个请求的 Worker 后来又去请求 web 了,默认的 driver 就一直是 api 了,所以才会出现上面这张情况。

知道是什么原因了,解决就好说了,把 config 给重置下,可怎么重置也略有点蛋疼。。。因为 Laravel  没给外部的方法,最终我的解决方法在这,每次请求完就重置下 config,虽然不大优雅,但也解决了问题。暂时还没提交 PR,之后加上,因为如果使用其他的包也会有这种问题,毕竟没考虑到这种情况。

commit 在此:https://github.com/glzjin/laravel-s/commit/82d16c71abc11fdf8aebd7083aa5de7dd381fa54

加载配置文件的方法来源于此:https://laracasts.com/discuss/channels/general-discussion/dynamic-config-files-loading-in-laravel-5

4. https 下混合内容问题

你如果用了 https 并且用了 assets  这个助手方法来调用资源的话会发现有混合内容,这个问题很好解决,强制指定一下吧。

AppServiceProvider boot 方法加一句

\URL::forceScheme('https');

 

三、效果

最直接的,加载时间减半了。

php-fpm

Laravel-S(Swoole)

 

欢迎留言交流~