我已经积累了超过6000万个会话,这导致了文件描述符耗尽的情况。
通过将会话传输到数据库解决了该问题。
在 Laravel 5.6 上测试。
为了这:
-
准备桌子 https://laravel.com/docs/8.x/session#database
php artisan 会话:表
php 工匠迁移
-
Create Artisan 控制台命令 https://laravel.com/docs/8.x/artisan
在 App\Console\Commands 目录中,创建一个包含以下内容的 SessionMigrate.php 文件:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Auth\SessionGuard;
use Illuminate\Support\Facades\DB;
use Symfony\Component\Console\Helper\ProgressBar;
class SessionMigrate extends Command
{
protected $signature = 'migrate:sessions';
protected $description = 'Migrate sessions from files to database';
protected $files;
protected $table;
protected $connection;
public function __construct(Filesystem $files)
{
parent::__construct();
$this->files = $files;
$this->table = config('session.table');
$this->connection = DB::connection(config('session.connection'));
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$this->info("Obtain session files...");
$dir = config('session.files');
$sessions_count = $this->getSessionsCount($dir);
if(FALSE == $dir_res = opendir($dir))
{
$this->error("Sessions directory open error.");
return 1;
}
$lifetime = config('session.lifetime');
$inserted_count = 0;
$updated_count = 0;
$errors = 0;
$this->info('Found ' . $sessions_count . ' session files');
$bar = $this->output->createProgressBar($sessions_count);
$bar->start();
while (FALSE !== ($file = readdir($dir_res)))
{
$file_path = $dir.'/'.$file;
if (in_array($file, array('.', '..')) || is_dir($file_path))
{
continue;
}
$id = $file;
try
{
$content = file_get_contents($file_path);
$data = @unserialize($content);
if(is_array($data))
{
$login_name = 'login_web_' . sha1(SessionGuard::class);
$user_id = NULL;
if(array_key_exists($login_name, $data))
{
$user_id = $data[$login_name];
}
$exists = $this->checkExists($id);
$last_activity = filemtime($file_path);
if($exists)
{
$this->connection->table($this->table)->whereId($id)->update([
'user_id' => $user_id,
'payload' => base64_encode($content),
'last_activity' => $last_activity
]);
$updated_count++;
}
else
{
$this->connection->table($this->table)->insert([
'id' => $id,
'user_id' => $user_id,
'payload' => base64_encode($content),
'last_activity' => $last_activity
]);
$inserted_count++;
}
}
}
catch(Exception $e)
{
$errors++;
}
$bar->advance();
}
closedir($dir_res);
$bar->finish();
$this->table(
['Total session files', 'Created', 'Updated', 'Errors'],
[
[$sessions_count, $inserted_count, $updated_count, $errors]
]
);
return 0;
}
protected function checkExists($id)
{
return (bool)$this->connection->table($this->table)->whereId($id)->first();
}
protected function getSessionsCount(string $dir)
{
$result = 0;
if(FALSE == $dir_res = opendir($dir))
{
$this->error("Directory open error. ($dir)");
return 0;
}
while (($file = readdir($dir_res)) !== false)
{
if (!in_array($file, array('.', '..')) && !is_dir($dir.$file))
{
$result++;
}
}
closedir($dir_res);
return $result;
}
}
-
运行迁移脚本
php artisan 迁移:会话
-
清除 Laravel 配置缓存
php artisan 配置:缓存
-
Done.
None
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)