Laravel向API发送大量数据出现504超时和内存耗尽如何解决
代码优化方案
现有代码核心问题
- 一次性加载全量商品+关联数据到内存:1300条商品及关联的图片、多语言数据全部加载到内存,直接触碰128M内存上限
- 临时数组未重置触发内存泄漏:
$images数组未在处理单个商品前清空,导致所有商品的图片数据持续累加;$array_of_products也未在每次批量发送后清空,内存占用随执行持续飙升 - 逻辑冗余&边界错误:手动计算分页起始结束位置,当商品总数不是70的整数倍时会出现数组下标越界错误;逐字符循环拼接图片URL的逻辑执行效率极低
- 同步执行触发网关超时:在HTTP请求链路中同步执行全量推送+API等待逻辑,极易超过Nginx/Apache默认60秒的超时阈值,触发504错误
优化方案
- 改用Laravel分块查询:使用
chunk方法每次仅加载70条商品数据到内存,处理完成后自动释放,避免全量数据占满内存 - 重置临时数组:处理单个商品前清空
$images数组,每次批量发送请求后清空$array_of_products,杜绝内存堆积 - 简化图片拼接逻辑:使用字符串拆分+拼接函数替代逐字符循环,大幅提升执行效率
- 建议异步执行:将推送逻辑移入Laravel队列异步执行,完全规避HTTP请求超时问题,若必须在HTTP入口执行可临时调高网关超时配置
修改后代码
public static function send() { $companyId = ******; // 替换为实际的公司ID // 分块查询 每次仅加载70条商品及关联数据 Product::where('active', 1) ->with(['images', 'lang']) // 预加载关联 比get后load更高效 ->chunk(70, function ($products) use ($companyId) { $arrayOfProducts = []; foreach ($products as $product) { $images = []; // 每次处理新商品前清空图片数组 避免累加 foreach ($product->images as $image) { $id = (string)$image->id_image; // 简化URL拼接 无需逐字符循环 $path = implode('/', str_split($id)); $images[] = "https://somesite.com/img/p/{$path}/{$id}.jpg"; } $arrayOfProducts[] = [ 'code' => $product->reference, 'name' => $product->lang->name, 'price' => round(($product->price) * 13200, -2), 'quantity' => 1, 'description' => $product->lang->description, 'images' => $images, 'url' => "https://avtech.uz/ru/{$product->id_product}-{$product->lang->link_rewrite}.html", ]; } // 发送当前批次数据 $response = Http::withToken('token')->post('https://example.com/upload', [ 'company_id' => $companyId, 'products' => $arrayOfProducts ]); if ($response->failed()) { Log::channel('send_products_to_pc')->info('Failed: ', [$response]); } else { Log::channel('send_products_to_pc')->info('Success: ', [$response]); } // 批次处理完成后自动释放当前批次的商品数据 无需手动清理 }); }
内容的提问来源于stack exchange,提问作者Kamron
相关产品推荐
相关产品推荐

