[LINUX] Eine Methode zum Ersetzen eines Servers, der die Stapelverarbeitung durch cron ohne Ausfallzeiten ausführt

Hintergrund

Es ist eine plötzliche Frage, aber wie verwalten Sie die Jobs, die Sie regelmäßig ausführen? Selbst im Jahr 2018, wenn Serverless beliebt ist, gibt es möglicherweise einige Leute, die immer noch das altmodische "Cron" verwenden.

In diesem Artikel möchte ich eine Möglichkeit vorschlagen, einen Server, auf dem die Stapelverarbeitung ausgeführt wird, durch "cron" ohne Ausfallzeiten zu ersetzen. Außerdem möchte ich erklären, warum dies möglich ist, indem ich auf den Quellcode von "cron" schaue. (Aus Zeitgründen behandeln wir "cronie" nur auf "CentOS7".)

Im tatsächlichen Betrieb sollten Sie ein ordnungsgemäßes Jobverwaltungssystem entwerfen. In diesem Artikel wird jedoch eine schlammige Methode vorgestellt.

TL; DR

Was war Cron?

cron ist ein zeitbasierter Job Scheduler, der in UNIX-basierten Betriebssystemen verwendet wird und zum Planen regelmäßig ausgeführter Aufgaben geeignet ist. Es wird auch zur Systemverwaltung und zur Ausführung von Aufgaben tatsächlicher Dienste verwendet.

Wenn Sie beispielsweise einen Job wie den folgenden mit "crontab -e" registrieren, wird der Aggregationsstapel stündlich mit 0 Minuten ausgeführt.

0 * * * * /bin/bash -l -c '/home/vagrant/bin/execute_hourly_aggregation'

Weitere Informationen finden Sie in den folgenden Wikipedia-Artikeln und in den verschiedenen Dokumenten, die als Referenz dienen.

https://ja.wikipedia.org/wiki/Crontab

Voraussetzungen

Bei dieser vorgeschlagenen Methode möchten wir in einer Umgebung, in der immer ein Stapel ausgeführt wird, beispielsweise einen Stapel, der lange dauert, oder eine große Anzahl von Stapeln, keine Ausfallzeiten verursachen.

Beachten Sie jedoch, dass die vorgeschlagene Methode auf einem Server, auf dem jede Minute neue Jobs gekickt werden, keine strikte Ausfallzeit von Null erreichen kann.

Umweltinformationen

Ich werde in der folgenden Umgebung erklären, die in Vagrant eingerichtet wurde. Die Version unterscheidet sich geringfügig vom zu erklärenden Quellcode, es gibt jedoch keine wesentlichen Änderungen. Ich hoffe, Sie verstehen den Mechanismus.

[vagrant@localhost ~]$ cat /etc/redhat-release
CentOS Linux release 7.5.1804 (Core)
[vagrant@localhost ~]$ yum list installed | grep cron
Failed to set locale, defaulting to C
cronie.x86_64                   1.4.11-19.el7                   @anaconda
cronie-anacron.x86_64           1.4.11-19.el7                   @anaconda
crontabs.noarch                 1.11-6.20121102git.el7          @anaconda

Verfahren

1. Vorbereiten eines neuen Servers mit gestopptem crond

Bereiten wir zunächst einen neuen Server vor. Was die Dateistruktur betrifft, gibt es kein Problem mit der gleichen Dateistruktur wie der alte Server, aber bitte machen Sie es so, dass die folgenden beiden erfüllt sind.

Verwenden Sie beispielsweise in der CentOS7-Serie den Befehl service, um sie zu stoppen.

[vagrant@localhost ~]$ sudo service crond stop
Redirecting to /bin/systemctl stop crond.service
[vagrant@localhost ~]$ service crond status
Redirecting to /bin/systemctl status crond.service
● crond.service - Command Scheduler
   Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Tue 2018-09-11 17:44:33 UTC; 11s ago
  Process: 3406 ExecStart=/usr/sbin/crond -n $CRONDARGS (code=exited, status=0/SUCCESS)
 Main PID: 3406 (code=exited, status=0/SUCCESS)

2. Warten Sie, bis der Job nicht mehr tritt

Warten Sie, bis die Cron-Jobs nicht mehr treten. Das Wichtigste dabei ist nicht, wann der Job abgeschlossen ist, sondern wann der Job nicht mehr gekickt wird. Schauen Sie sich den Prozess unter "crond" mit "ps aux f" usw. an und stellen Sie sicher, dass der letzte Batch-Prozess auf dem alten Server gestartet wurde.

root      3492  0.0  0.3  26096  1704 ?        Ss   17:45   0:00 /usr/sbin/crond -n
root      3921  0.0  0.4  82144  2488 ?        S    18:05   0:00  \_ /usr/sbin/CROND -n
vagrant   3924  0.0  0.3  12992  1568 ?        Ss   18:05   0:00  |   \_ /bin/bash -l -c echo "start at $(date)" && sleep 120 && echo "end at $(date)"
vagrant   3937  0.0  0.0   7764   352 ?        S    18:05   0:00  |   |   \_ sleep 120

3. Stoppen Sie "crond" auf dem alten Server und starten Sie "crond" auf dem neuen Server

Schließlich werden wir mit den Ersatzarbeiten fortfahren. Stoppen Sie zuerst "crond" auf dem alten Server und starten Sie "crond" auf dem neuen Server. Zu diesem Zeitpunkt startet der alte Server keine neuen Stapeloperationen mehr.

4. Beobachten Sie den Batch-Vorgang auf dem alten Server

crond hat aufgehört, aber es gibt immer noch Jobs, die crond gekickt haben. Warten wir, bis der Stapelprozess abgeschlossen ist. Zu diesem Zeitpunkt hat der von crond gekickte Job seinen Hauptelternteil verloren und hängt nun unter / usr / sbin / CROND.

root      4199  0.0  0.4  82144  2488 ?        S    18:18   0:00 /usr/sbin/CROND -n
vagrant   4201  0.0  0.3  12992  1564 ?        Ss   18:18   0:00  \_ /bin/bash -l -c echo "start at $(date)" && sleep 120 && echo "end at $(date)"
vagrant   4214  0.0  0.0   7764   352 ?        S    18:18   0:00  |   \_ sleep 120

5. Stoppen Sie den alten Server vollständig

Warten Sie, bis der endgültige Stapelprozess abgeschlossen ist, und hören Sie dann höflich auf.

Verraten

Warum ist das möglich? Lassen Sie uns den Status des Prozesses zur Laufzeit erneut überprüfen, während wir den Cron-Code für einen Moment lesen.

Zuerst durchläuft "cron" den folgenden Vorgang "während", bis ein Signal von "SIGINT" oder "SIGTERM" empfangen wird.

	while (!got_sigintterm) {
		int timeDiff;
		enum timejump wakeupKind;

		/* ... wait for the time (in minutes) to change ... */
		do {
			cron_sleep(timeRunning + 1, &database);
			set_time(FALSE);
		} while (!got_sigintterm && clockTime == timeRunning);
		if (got_sigintterm)
			break;
		timeRunning = clockTime;
// ~Unterlassung~
		handle_signals(&database);
	}

https://github.com/cronie-crond/cronie/blob/40b7164227a17058afb4f3d837ebb3263943e2e6/src/cron.c#L354-L481

Mit anderen Worten, Sie können sehen, dass der neue Stapel jede (ungefähr) Minute ausgeführt wird, in der diese Prüfung ausgeführt wird.

Der neue Stapel wird von "find_jobs ()" erkannt und als Nachkomme des ursprünglichen "crond" über "job_runqueue ()", "do_command ()", "child_process ()" ausgeführt.

root      3492  0.0  0.3  26096  1704 ?        Ss   17:45   0:00 /usr/sbin/crond -n
root      3921  0.0  0.4  82144  2488 ?        S    18:05   0:00  \_ /usr/sbin/CROND -n
vagrant   3924  0.0  0.3  12992  1568 ?        Ss   18:05   0:00  |   \_ /bin/bash -l -c echo "start at $(date)" && sleep 120 && echo "end at $(date)"
vagrant   3937  0.0  0.0   7764   352 ?        S    18:05   0:00  |   |   \_ sleep 120

Was passiert also, wenn Sie hier mit "SIGTERM" aufhören? Werfen wir einen Blick auf den Code für das letzte Reinigungsteil.


#if defined WITH_INOTIFY
	if (inotify_enabled && (EnableClustering != 1))
		set_cron_unwatched(fd);

	if (fd >= 0 && close(fd) < 0)
		log_it("CRON", pid, "INFO", "Inotify close failed", errno);
#endif

	log_it("CRON", pid, "INFO", "Shutting down", 0);

	(void) unlink(_PATH_CRON_PID);

	return 0;

https://github.com/cronie-crond/cronie/blob/40b7164227a17058afb4f3d837ebb3263943e2e6/src/cron.c#L482-L495

Hast du bemerkt? Anstatt auf den Prozess des Kindes oder Enkels zu warten oder ihn zu töten, ist der Elternteil stillschweigend tot und beauftragt das Kind mit der Bearbeitung des Enkels.

root      4199  0.0  0.4  82144  2488 ?        S    18:18   0:00 /usr/sbin/CROND -n
vagrant   4201  0.0  0.3  12992  1564 ?        Ss   18:18   0:00  \_ /bin/bash -l -c echo "start at $(date)" && sleep 120 && echo "end at $(date)"
vagrant   4214  0.0  0.0   7764   352 ?        S    18:18   0:00  |   \_ sleep 120

Infolgedessen werden neue Jobs nicht gekickt, während bereits geknickte Jobs bis zum Ende abgeschlossen werden können. (Es ist ein wenig schmerzhaft)

Zusammenfassung

Da "crond" sehr einfach implementiert ist, ist es möglich, es selbst bei einer groben Methode wie der vorgeschlagenen Methode durch keine Ausfallzeit zu ersetzen. Natürlich ist es im tatsächlichen Betrieb ein Bereich, der ordnungsgemäß systematisiert werden sollte, aber ich hoffe, dass Sie sich für das vertraute "Cron" interessieren.

Referenz

Recommended Posts

Eine Methode zum Ersetzen eines Servers, der die Stapelverarbeitung durch cron ohne Ausfallzeiten ausführt
Generieren Sie mit apg ein leicht zu merkendes Passwort
Spielen Sie den Server mit zwei PCs
[Mac] Ich möchte einen einfachen HTTP-Server erstellen, auf dem CGI mit Python ausgeführt wird
Ein Server, der POST-Daten mit flask / python wiedergibt
[1 Stunde Herausforderung] Ich habe versucht, eine Wahrsagerseite zu erstellen, die für Python zu geeignet ist
Eine einfache Version der Regierungsstatistik (Einwanderungskontrolle), die mit Jupyter einfach zu handhaben ist