[Ruby / Rails] Mechanismus zum erneuten Versuch eines Thread-Fehlers

Überblick

Wenn Multithreading mit "Thread.new ()" durchgeführt wurde, trat in Heroku ein Ressourcenmangelfehler auf.

can't create Thread: Resource temporarily unavailable (ThreadError)

Ich habe eine Thread-Fehlerbehandlung und einen Wiederholungsmechanismus erstellt, der Threads nach besten Kräften verwendet.


Übrigens ist die Anzahl der von Heroku ausführbaren Prozessthreads recht begrenzt. Achten Sie daher auf den Unterschied zur lokalen Umgebung.

https://devcenter.heroku.com/articles/limits#processes-threads

Stand 2020/08

free, hobby and standard-1x dynos support no more than 256
standard-2x and private-s dynos support no more than 512
performance-m and private-m dynos support no more than 16384
performance-l and private-l dynos support no more than 32768

Wenn Ihre lokale Umgebung MacOS ist, können Sie den Befehl sysctl kern.num_taskthreads verwenden, um die maximale Anzahl von Threads pro Prozess zu ermitteln.

$ sysctl kern.num_taskthreads
kern.num_taskthreads: 4096

Hinweis

Es besteht eine hohe Wahrscheinlichkeit, dass ein Konstruktionsfehler beim Auslaufen der Gewinde gemacht wird, wenn die Last etwas höher als gewöhnlich ist.

Überlegen Sie zunächst, wie Sie die Anzahl der Threads reduzieren können, die eingerichtet werden müssen, z. B. ob die Verarbeitung an einen anderen Server delegiert werden kann oder ob aufgrund der API-Spezifikationen eine Möglichkeit besteht, mit einer kleinen Anzahl von Anforderungen umzugehen.

Code

def retry_threads(times: 3)
  try = 0
  begin
    try += 1
    Thread.new { yield }
  rescue ThreadError
    sleep(1 * try)
    retry if try < times
    raise
  end
end

Wenn kein Thread verfügbar ist, warten Sie einige Sekunden und versuchen Sie es erneut.

Die Anzahl der Wartesekunden ist variabel, z. B. 1 Sekunde für die erste Wiederholung und 2 Sekunden für die zweite Wiederholung, um Zeitverlust zu vermeiden.

Es gibt auch eine Möglichkeit, Wiederholungsversuche detailliert zu verwalten, indem die Wartezeit auf Mikrosekunden festgelegt wird.


Tatsächliche Nutzung

def heavy_task(url)
  #Schwere Verarbeitung
end

# urls = ["...","...",...]
threads = []
urls.all each do |url|
  threads << retry_threads{ heavy_task(url) }
end
threads.each(&:join)

Benchmark

Wir haben untersucht, um wie viel die Toleranz für das Einfädeln durch diesen Wiederholungsmechanismus tatsächlich erhöht wurde.

Bedingungen

Messcode

def heavy_task
  sleep(10)
end

def retry_threads(times: 3)
  try = 0
  begin
    try += 1
    Thread.new { yield }
  rescue ThreadError
    sleep(1 * try)
    retry if try < times
    p $count
    raise
  end
end

def no_retry_threads()
  begin
    Thread.new { yield }
  rescue ThreadError
    p $count
    raise
  end
end

$count = 0

#Kein erneuter Versuch
loop do
  no_retry_threads{ heavy_task }
  $count += 1
end

#Mit erneutem Versuch
loop do
  retry_threads{ heavy_task }
  $count += 1
end

Ergebnis

Der Wert der Anzahl der Aufgaben, die in der lokalen Umgebung 10 Sekunden gedauert haben (maximale Anzahl der Threads: 4096).

Keine Wiederholungsversuche Mit erneutem Versuch
4094 212888

Referenz

Recommended Posts

[Ruby / Rails] Mechanismus zum erneuten Versuch eines Thread-Fehlers
Testen auf Fehlermeldungen: Rails Tutorial Notes-Kapitel 7
Tipps zur Behandlung von gRPC-Fehlern in Ruby
Erklärung von Ruby auf Schienen für Anfänger ①
[Ruby on Rails] Select2-Einführungsnotiz für Webpacker
[Rails] Verfahren zum Verknüpfen von Datenbanken mit Ruby On Rails
[Ruby on Rails] Individuelle Anzeige von Fehlermeldungen
[Ruby On Rails] Ursachen und Abhilfemaßnahmen für ActionView :: Template :: Error (ActiveStorage :: InvariableError) (Hypothese / Überprüfung)
Schienen nicht initialisierte Konstante Eine einfache Checkliste zur Fehlerbehebung
Problemumgehung für Bundler.require-Fehler beim Ausführen von Ruby mit crontab
Rails / Ruby: So erhalten Sie HTML-Text für Mail
Erklärung von Ruby auf Schienen für Anfänger ⑥ ~ Erstellung der Validierung ~
Erklärung von Ruby on Rails für Anfänger ② ~ Links erstellen ~
Erklärung von Ruby on Rails für Anfänger ⑦ ~ Flash-Implementierung ~
[Hinweis] Rails-Fehlerliste
Informationen zu Ruby-Fehlermeldungen
Catch Rails Routing-Fehler
Kapitel 4 Rails Flavoured Ruby
Abkürzung für Ruby-Methode
Hinweise zu Rubys Thread # [] = Methode
Mac Rails Installationsfehler
Ruby on Rails Elementary
Ruby On Rails Association
[Rails] Problemumgehung für Klassen, die automatisch mit Fehlermeldungen generiert werden
[Verfahren 1 für Anfänger] Ruby on Rails: Aufbau einer Entwicklungsumgebung
Erklärung von Ruby on Rails für Anfänger ③ ~ Erstellen einer Datenbank ~