Mysql Laravel文件上载超时-是否向updateOrCreate添加块?
我试图上传一个用户csv文件并将数据传递到数据库中,但由于csv/行的大小,它一直超时。必须检查数据是否已经在数据库中,并进行更新或创建 我已经在CSV上应用了一个块来读取数据,但不知道是否可以在上传到数据库部分添加一个块 这是我的功能Mysql Laravel文件上载超时-是否向updateOrCreate添加块?,mysql,laravel,laravel-5,laravel-excel,Mysql,Laravel,Laravel 5,Laravel Excel,我试图上传一个用户csv文件并将数据传递到数据库中,但由于csv/行的大小,它一直超时。必须检查数据是否已经在数据库中,并进行更新或创建 我已经在CSV上应用了一个块来读取数据,但不知道是否可以在上传到数据库部分添加一个块 这是我的功能 public function import(Request $request) { if($request->file('imported-file')) { $path = $request->file('import
public function import(Request $request) {
if($request->file('imported-file')) {
$path = $request->file('imported-file')->getRealPath();
$data = Excel::filter('chunk')->load($path)->chunk(200, function($results) {
foreach($results as $row) {
if(!empty($row['postcode'])) {
$url = "https://maps.googleapis.com/maps/api/geocode/xml?address=".urlencode($row['postcode'])."®ion=uk&key=";
$tmp = file_get_contents($url);
$xml = simplexml_load_string($tmp);
if((string)$xml->status == 'OK' && isset($xml->result[0])) {
$lat = 0;
$lng = 0;
if(isset($xml->result[0]->geometry->location->lat)) {
$lat = (string)$xml->result[0]->geometry->location->lat;
}
if(isset($xml->result[0]->geometry->location->lng)) {
$lng = (string)$xml->result[0]->geometry->location->lng;
}
}
Import::updateOrCreate(
[
'sitecode' => $row['sitecode']
],
[
'sitecode' => $row['sitecode'],
'sitename' => $row['sitename'],
'address_1' => $row['address_1'],
'address_2' => $row['address_2'],
'address_town' => $row['address_town'],
'address_postcode' => $row['postcode'],
'charity' => $row['charity'],
'latitude' => $lat,
'longitude' => $lng,
'approved' => 1
]
);
} else {
// Postcode not valid!!!
}
} // endforeach
Session::flash('sucess', 'Import was sucessful.');
return redirect()->route('locations');
});
} else {
Session::flash('error', 'Please select a file to upload!');
return back();
}
}
您的问题与服务器的配置有关,您必须了解,在实时执行长时间运行的任务时,许多事情可能会出错 如果您使用的是Nginx/PHP-FPM设置,那么必须查看Nginx、PHP和PHP-FPM配置文件 PHP配置 让我们从PHP开始。打开
/etc/php//fpm/php.ini
文件并搜索最大执行时间
。你应该找到类似的东西
max_execution_time = 30
这意味着每个请求的持续时间不能超过30秒。如果您需要更多时间,请增加此数字,例如
max_execution_time = 300
request_terminate_timeout = 400
5分钟
然后让我们检查一下PHP-FPM配置。打开池配置,如/etc/php//fpm/pool.d/www.conf
,搜索请求\终止\超时时间
。在我的配置中,我禁用了它:
; Default Value: 0
;request_terminate_timeout = 0
默认值为0(已禁用),但如果已启用该值,则应增加该值,例如
max_execution_time = 300
request_terminate_timeout = 400
在PHP-FPM杀死一个子进程之前400秒。如果您给出一个数字,请使用高于max\u execution\u time
的值,否则您的进程将被PHP-FPM终止,忽略最大执行时间
Nginx配置
最后,查看/etc/Nginx/sites available/yoursite.conf
中的Nginx配置。在这里,您应该可以找到一个配置Nginx和PHP-FPM之间通信的部分。您可以在这里找到fastcgi\u read\u timeout
,这是Nginx等待PHP-FPM返回某些数据的最长时间:
location ~ \.php$ {
# ...
fastcgi_read_timeout 300;
# ...
}
如果300秒后PHP-FPM没有返回任何内容,Nginx将终止连接。在您的情况下,在长时间运行的进程之后将数据发送回Web服务器,因此所需时间不会超过300秒。您应该将该数字更改为与您在PHP配置中输入的数字兼容的数字
总结
如果您认为您的处理可能需要30分钟,请使用以下数字:
- 在
中:/etc/php//fpm/php.ini
max_execution_time = 1800 ; 1800 secs = 30 minutes
- 在
中:/etc/php//fpm/pool.d/www.conf
request_terminate_timeout = 0 ; no timeout, or greater than 1800
fastcgi_read_timeout = 2000; # 2000 secs, or at least greater than the previous twos
- 在
中:/etc/nginx/sites available/yoursite.conf
request_terminate_timeout = 0 ; no timeout, or greater than 1800
fastcgi_read_timeout = 2000; # 2000 secs, or at least greater than the previous twos
max_execution_time
将在其他组合中起支配作用,您将知道您的进程有30分钟的运行时间,因为PHP-FPM和Nginx超时应该发生在PHP超时之后
不要忘记客户端
如果您使用的是AJAX上传库,请检查它的配置,因为它可能会对完整的AJAX上传请求施加另一个超时
例如,默认情况下使用30秒超时。您的服务器可能会运行很长时间,但在短时间之后,您的javascript库将终止连接
通常可以更改该值。使用dropzone,您可以使用设置2100秒的超时
var myDropzone = new Dropzone("#uploader", {
// ...
timeout: "2100",
// ...
});
同样,使用比Nginx上的值更高的值
长时间运行的任务:正确的方法
然而,您的方法又快又脏,即使我确信它适合您的情况,最好还是走另一条路:
我希望这能有所帮助:)设置时间限制可能会对@RaymondNijland有所帮助,但仍然没有什么影响。嗨,谢谢你抽出时间写一封冗长的回复。我接受了你的建议,增加了一个工作/队列。我上传CSV,然后分派一个作业并处理CSV,然后从那里上传到数据库。我运行php artisan队列:工作正常!在我的macbook上就是这样。我已经将repo下载到我的imac上,完全相同,但是当我运行work命令时,我只是像一个无限循环一样一遍又一遍地得到它?[2017-11-29 11:48:21]处理:App\Jobs\ProcessCSV[2017-11-29 11:48:22]处理:App\Jobs\ProcessCSV有什么想法吗?可能你正面临工作到期和重审()。队列配置(
config/queue.php
)中有一个默认值为90秒的retry\u after
选项。之后,如果作业没有完成,工人将重新开始。还要确保有一个足够大的worker--timeout
(或者忽略这些选项,我认为默认值是no timeout)。