Я создал сценарий электронной почты, который проверяет таблицу MySQL для почты, у которой есть метка времени в прошлом для отправки. Иногда бывает, что в «mailqueue» больше почты, чем я хотел бы отправить за один раз, поэтому я использовал потоки для отправки почты партиями. Иногда, когда нет почты для отправки, система работает стабильно, но в других случаях этот процесс рассылки, который всегда работает (через сценарий bash
, который вызывает его каждые 30 секунд
) убивается, поскольку в системе заканчивается память , Я бы хотел, чтобы «почта» не хватало памяти.Perl mailqueueing with threads 'out of memory'
Я хотел бы попросить кого-нибудь из вас взглянуть на мой код внизу, возможно, я что-то сделаю неправильно.
Заранее спасибо.
~$ htop PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command 5675 root 20 0 969M 528M 3744 S 0.0 14.1 2:33.05 perl /path/mailqueue.pl Server specs: 1 vCPU; 3.75 Gib Memory;
sub start_threads {
my @threads;
# records found
my $found = 0;
my $sth = $dbh->prepare("SELECT mail_queue_id, project_id, type, name, email FROM mail_queue WHERE timestamp < NOW() AND active = 1 ORDER BY timestamp ASC LIMIT 10");
$sth->execute();
while (my $ref = $sth->fetchrow_hashref()) {
# set if records are found
$found = 1;
# set email variables
my $id = $ref->{'mail_queue_id'};
my $project_id = $ref->{'project_id'};
my $type = $ref->{'type'};
my $name = $ref->{'name'};
my $email = $ref->{'email'};
# create array with data
my @select_arr = ($id, $project_id, $type, $name, $email);
# start thread to send mail
my $t = threads->new(\&sendmail, @select_arr);
push(@threads,$t);
}
foreach (@threads) {
# mail_queue_id
my $id = $_->join;
print "set email $id in queue inactive\n";
# set mail_queue record inactive -> MYSQL(event) mailqueue cleanup every 10 minutes
my $sth = $dbh->prepare("UPDATE mail_queue SET active = 0 WHERE mail_queue_id = ? ");
$sth->execute($id);
}
if($found eq 1) { # return rows in mail_queue < 1
sleep(10);
&start_threads;
}
else { # skip thread, wait 1 minut = sleep(1) to select new rows;
sleep(30);
&start_threads;
}
}
# prepare send e-mail
sub sendmail {
my @select_arr = @_;
# queue variables
my $id = $select_arr[0];
my $project_id = $select_arr[1];
my $type = $select_arr[3];
my $name = $select_arr[4];
my $email = $select_arr[5];
print "started sending email " . $id . " \n";
# call function which sends the mail out
my $send = &email(@select_arr);
# if mail is sent
if($send eq 1) {
print "done with sending email " . $id . "\n";
sleep (1);
# return unique id
return $id;
}
}
&start_threads;
Спасибо за вас быстрый ответ. Извините, но я проверил свой код, и мне показалось, что я вызываю этот скрипт каждые 30 секунд с помощью скрипта bash, но это не так. Отвечает ли ваш ответ также, когда я не звоню через сценарий bash? Потому что тогда я не копирую весь процесс? –
Не совсем так плохо, я полагаю, что 'LIMIT' ограничивает его до 10 результатов за раз? Если это так, то вероятным исчерпанием памяти может быть тот список '@ threads', который будет только увеличиваться с течением времени (вы добавляете к нему элементы, но не удаляете их). Вы можете найти 'threads -> list()' лучший способ сделать соединение. – Sobrique