[已解决]webman+swoole,协程环境中HttpRequest已经做了协程上下文处理了吗

xiaopi

问题描述

1.测试两个请求,第一个请求协程挂起5秒后输出所有请求参数;第二个请求直接输出所有请求参数。如果\Workerman\Protocols\Http\Request没存储上下文的话,第一个请求返回的应该已经被第二个请求污染了啊

2.如果\Workerman\Protocols\Http\Request做了协程上下文处理,那是否意味着在webman控制器中可以不用考虑自己处理请求上下文,可以直接用$request对象?

截图

截图
截图
截图
截图

结论

通过代码得知,Request确实针对swoole、swow、Fiber的协程做了上下文处理
1.通过Webman\App::onMessage()方法可知,当请求进来时,会使用webman\Context设置上下文,发送完毕后会清理上下文
截图
截图

2.通过Webman\Context::getKey()方法得知,会针对不同的协程环境获取协程id作为key保存起来,即区分了不同协程下的request
截图

631 2 1
2个回答

nitron

你上面的代码,每个swTest($request)都是已经实例化的Request,当然不会覆盖,$request->all()又不是Lazy Evaluation

胡桃

每个onMessage事件都会创建一个新的协程(也可能是复用尚未销毁的空闲协程),即使是同一个TCP连接,每个请求(onMessage)也会创建新的协程,每个协程都有独立的调用栈,不存在互相污染的情况,串上下文更是无稽之谈,你能在函数外访问函数的局部变量吗?而所谓的Request/Response就是这个协程的局部变量。
你的问题在文档和源码里都有,不主动去探究将会有无穷无尽的问题。

  • xiaopi 2024-01-13

    感谢,主要是我没搞清$request是局部变量还是全局变量,我做了测试如果是全局变量协程中是互相干扰的,那随后的开发中,只要注意协程中使用全局变量的时候需要上下文就可以了

  • efnic 2024-01-17

    【每个onMessage事件都会创建一个新的协程。】这个代码内没有找到,版本为workerman ^5.0.0-beta.7、webman 1.5.13

  • xiaopi 2024-01-18

    这个协程指的是swoole的协程,不是php8.1的fiber

  • efnic 2024-01-18

    我的意思是,在原版的webman内没看到创建swoole协程的代码。

  • xiaopi 2024-01-18

    有的,workerman内置了swoole event,可以把event-loop改为\Workerman\Events\Swoole::class ,onMessage就是协程了,webman中的config/server.php中的event_loop设置成\Workerman\Events\Swoole::class就行了
    https://www.workerman.net/q/3529

🔝