laravel 使用异步队列,context带的上下文造成反序列化出问题
2025年5月8日17:03:44
如果你是单个应用,异步递交任务,是在应用内部使用,一般不会发生这样的问题
但是现在app项目是 app是一个应用,admin是一个应用,app吧为了接口性能吧异步任务丢给admin去执行,如果两个应用的。就会出现部分使用
Context::add('laravel_unique_job_key', 4444);Context::addHidden('eeee', 333333);$tokenInfo = new TokenInfo();Context::add('tokenInfo', $tokenInfo);
如果 增加的 储存在上下文的value部分有对象的值的时候,比如 TokenInfo
的在发送 dispatchJob($job);
就会吧 Context里面 data
和 hidden
部分会带入 payload
{"displayName": "App\\Jobs\\Job","job": "Illuminate\\Queue\\CallQueuedHandler@call","maxTries": 3,"maxExceptions": null,"failOnTimeout": false,"backoff": null,"timeout": null,"retryUntil": null,"data": {"commandName": "App\\Jobs\\Job","command": "O:27:\"App\\Jobs\\Job\":1:{s:7:\"orderId\";i:221;}"},"illuminate:log:context": {"data": {"tokenInfo": "O:40:\"App\\Http\\TokenInfo\":2:{s:4:\"uuid\";s:0:\"\";s:2:\"id\";i:0;}","zx": "i:11111;"},"hidden": {"eeee": "i:333333;"}}
}
如果admin 没有 TokenInfo
的对象就会报错,
RuntimeException: Value is incomplete class: {"__PHP_Incomplete_Class_Name":"App\\Http\\TokenInfo","uuid":"","id":0}
解决方案:
1,在上游分发异步任务的时候,就不要有 Context 相关的使用 对象类型的数据
2,在下游执行任务的项目,吧存储的对象也复制一份
3,自己封装一个分发方法
if (!function_exists('dispatchJob')) {function dispatchJob(mixed $job){//需要排除的key,这些key可能会影响队列的部分功能,需要先排除$excludeKey = ['laravel_unique_job_cache_store', 'laravel_unique_job_key'];$stay = $all = Context::all();$stayHidden = $allHidden = Context::allHidden();// 判断是否有上下文,如果没有直接 分发jobif (empty($all) && empty($allHidden)) {dispatch($job);} else {//先 forget 所有比不需要的key,dispatch 之后在还给 Context//需要删除的 context key$filterKey = Arr::except($all, $excludeKey);$filterHiddenKey = Arr::except($allHidden, $excludeKey);$keys = array_keys($filterKey);$hiddenKeys = array_keys($filterHiddenKey);// 删除不必要的keyif (!empty($keys)) {foreach ($keys as $key) {Context::forget($key);}}// 删除不必要的隐藏keyif (!empty($hiddenKeys)) {foreach ($hiddenKeys as $hiddenKey) {Context::forgetHidden($hiddenKey);}}//分发任务dispatch($job);//归还上下文if (!empty($keys)) {foreach ($keys as $key) {Context::add($key, $all[$key]);}}if (!empty($hiddenKeys)) {foreach ($hiddenKeys as $hiddenKey) {Context::addHidden($hiddenKey, $allHidden[$hiddenKey]);}}}}
}