From a354dfceab313ce89c8739fdb3243183f2bbefbe Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Fri, 23 Aug 2019 11:17:39 +0200 Subject: [PATCH] =?utf8?q?Task-Server=20auf=20unterschiedlichen=20Maschine?= =?utf8?q?n=20laufen=20lassen=20k=C3=B6nnen?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Jede Task-Server-Instanz und jeder Hintergrundjob haben nun ein neues Attribute »node_id«. Darüber kann gesteuert werden, dass bestimmte Jobs nur von einer bestimmten Instanz ausgeführt werden. Die »node_id« eines neu angelegten Jobs ist standardmäßig leer. Das bedeutet, dass ein Job von einer beliebigen Task-Server-Instanz ausgeführt werden kann. Die »node_id« eines Task-Servers ist standardmäßig der Hostname (siehe ausgabe von »perl -MSys::Hostname -le 'print hostname()'«), kann aber in der Konfigurationsdatei überschrieben werden (»[task_server]« → »node_id«). Zusätzlich gibt es den Konfigurationsparameter »[task_server]« → »only_run_tasks_for_this_node«. Ist dieser Parameter gesetzt, so führt der Task-Server nur diejenigen Jobs aus, deren »node_id«-Feld mit der »node_id« der Task-Server-Instanz übereinstimmt. Andernfalls werden auch diejenigen Jobs ausgeführt, deren »node_id«-Feld leer ist. Achtung: es findet momentan keinerlei Locking statt. Das bedeutet, dass es für jede Datenbank nur eine Task-Server-Instanz geben darf, bei der »only_run_tasks_for_this_node« nicht gesetzt ist. Für Load-Balancing eignet sich das also bisher noch nicht. --- SL/BackgroundJob/Test.pm | 4 +++- SL/DB/Manager/BackgroundJob.pm | 19 +++++++++++++++++-- SL/DB/MetaSetup/BackgroundJob.pm | 1 + SL/System/TaskServer.pm | 11 +++++++++++ config/kivitendo.conf.default | 5 +++++ scripts/task_server.pl | 1 + .../add_node_id_to_background_jobs.sql | 5 +++++ 7 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 sql/Pg-upgrade2/add_node_id_to_background_jobs.sql diff --git a/SL/BackgroundJob/Test.pm b/SL/BackgroundJob/Test.pm index c8c76db36..a70b7a3c5 100644 --- a/SL/BackgroundJob/Test.pm +++ b/SL/BackgroundJob/Test.pm @@ -4,11 +4,13 @@ use strict; use parent qw(SL::BackgroundJob::Base); +use SL::System::TaskServer; + sub run { my ($self, $db_obj) = @_; my $data = $db_obj->data_as_hash; - $::lxdebug->message(0, "Test job is being executed."); + $::lxdebug->message(0, "Test job ID " . $db_obj->id . " is being executed on node " . SL::System::TaskServer::node_id() . "."); die "Oh cruel world: " . $data->{exception} if $data->{exception}; diff --git a/SL/DB/Manager/BackgroundJob.pm b/SL/DB/Manager/BackgroundJob.pm index 6212f9416..8b2e99aa8 100644 --- a/SL/DB/Manager/BackgroundJob.pm +++ b/SL/DB/Manager/BackgroundJob.pm @@ -8,6 +8,8 @@ use base qw(SL::DB::Helper::Manager); use SL::DB::Helper::Paginated; use SL::DB::Helper::Sorted; +use SL::System::TaskServer; + sub object_class { 'SL::DB::BackgroundJob' } __PACKAGE__->make_manager_methods; @@ -36,8 +38,21 @@ sub get_all_need_to_run { cron_spec => '', next_run_at => undef, next_run_at => { le => $now } ] ]); - - return $class->get_all(query => [ or => [ @interval_args, @once_args ] ]); + my @node_filter; + + my $node_id = SL::System::TaskServer->node_id; + if ($::lx_office_conf{task_server}->{only_run_tasks_for_this_node}) { + @node_filter = (node_id => $node_id); + } else { + @node_filter = ( + or => [ + node_id => undef, + node_id => '', + node_id => $node_id, + ]); + } + + return $class->get_all(query => [ or => [ @interval_args, @once_args ], @node_filter ]); } 1; diff --git a/SL/DB/MetaSetup/BackgroundJob.pm b/SL/DB/MetaSetup/BackgroundJob.pm index 5b674aae8..ce2ed7e1f 100644 --- a/SL/DB/MetaSetup/BackgroundJob.pm +++ b/SL/DB/MetaSetup/BackgroundJob.pm @@ -15,6 +15,7 @@ __PACKAGE__->meta->columns( id => { type => 'serial', not_null => 1 }, last_run_at => { type => 'timestamp' }, next_run_at => { type => 'timestamp' }, + node_id => { type => 'text' }, package_name => { type => 'varchar', length => 255 }, type => { type => 'varchar', length => 255 }, ); diff --git a/SL/System/TaskServer.pm b/SL/System/TaskServer.pm index e410e7311..a37cd03d1 100644 --- a/SL/System/TaskServer.pm +++ b/SL/System/TaskServer.pm @@ -11,6 +11,7 @@ use Rose::Object::MakeMethods::Generic ( use File::Slurp; use File::Spec::Functions qw(:ALL); use File::Temp; +use Sys::Hostname (); use SL::System::Process; @@ -22,6 +23,8 @@ use constant { use constant PID_BASE => "users/pid"; +my $node_id; + sub status { my ($self) = @_; @@ -63,6 +66,14 @@ sub wake_up { return kill('ALRM', $pid) ? 1 : undef; } +sub node_id { + return $node_id if $node_id; + + $node_id = ($::lx_office_conf{task_server} // {})->{node_id} || Sys::Hostname::hostname(); + + return $node_id; +} + # # private methods # diff --git a/config/kivitendo.conf.default b/config/kivitendo.conf.default index 0715dc087..0d88cfc28 100644 --- a/config/kivitendo.conf.default +++ b/config/kivitendo.conf.default @@ -189,6 +189,11 @@ openofficeorg_daemon_port = 2002 debug = 0 # Chose a system user the daemon should run under when started as root. run_as = +# Task servers can run on multiple machines. Each needs its own unique +# ID. If unset, it defaults to the host name. All but one task server +# must have 'only_run_tasks_for_this_node' set to 1. +node_id = +only_run_tasks_for_this_node = 0 [task_server/notify_on_failure] # If you want email notifications for failed jobs then set this to a diff --git a/scripts/task_server.pl b/scripts/task_server.pl index c9494c8e0..3d2814928 100755 --- a/scripts/task_server.pl +++ b/scripts/task_server.pl @@ -322,6 +322,7 @@ sub gd_run { run_single_job_for_all_clients(); return; } + $::lxdebug->message(LXDebug::INFO(), "The task server for node " . SL::System::TaskServer::node_id() . " is up and running."); while (1) { $SIG{'ALRM'} = 'IGNORE'; diff --git a/sql/Pg-upgrade2/add_node_id_to_background_jobs.sql b/sql/Pg-upgrade2/add_node_id_to_background_jobs.sql new file mode 100644 index 000000000..6fac50e8e --- /dev/null +++ b/sql/Pg-upgrade2/add_node_id_to_background_jobs.sql @@ -0,0 +1,5 @@ +-- @tag: add_node_id_to_background_jobs +-- @description: Spalte 'node_id' in 'background_jobs' +-- @depends: release_3_5_4 +ALTER TABLE background_jobs +ADD COLUMN node_id TEXT; -- 2.20.1