[Ruby / Rails] Mécanisme de nouvelle tentative d'erreur de thread

Aperçu

Lorsque le multithreading a été effectué en utilisant Thread.new (), une erreur de pénurie de ressources s'est produite dans Heroku.

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

J'ai créé une gestion des erreurs de thread et un mécanisme de nouvelle tentative qui utilise les threads au mieux.


Au fait, le nombre de threads de processus pouvant être exécutés par Heroku est assez limité, alors faites attention à la différence avec l'environnement local.

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

À partir de 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

Si votre environnement local est MacOS, vous pouvez utiliser la commande sysctl kern.num_taskthreads pour connaître le nombre maximum de threads par processus.

$ sysctl kern.num_taskthreads
kern.num_taskthreads: 4096

Mise en garde

Il y a une forte possibilité qu'une erreur de conception soit commise lors du processus de manque de threads lorsque la charge est légèrement plus élevée que d'habitude.

Tout d'abord, considérez comment réduire le nombre de threads à configurer, par exemple si le traitement peut être délégué à un autre serveur ou s'il existe un moyen de traiter un petit nombre de requêtes en raison des spécifications de l'API.

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

S'il n'y a pas de thread disponible, attendez quelques secondes et réessayez.

Le nombre de secondes d'attente est variable, par exemple 1 seconde pour la première tentative et 2 secondes pour la deuxième tentative, afin d'éviter une perte de temps.

Il existe également un moyen de gérer les nouvelles tentatives en détail en définissant le temps d'attente en microsecondes.


Utilisation réelle

def heavy_task(url)
  #Traitement lourd
end

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

référence

Nous avons étudié dans quelle mesure la tolérance pour le threading était réellement augmentée par ce mécanisme de nouvelle tentative.

conditions

Code de mesure

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

#Aucune nouvelle tentative
loop do
  no_retry_threads{ heavy_task }
  $count += 1
end

#Avec réessayer
loop do
  retry_threads{ heavy_task }
  $count += 1
end

résultat

La valeur du nombre de tâches qui ont pris 10 secondes dans l'environnement local (nombre maximum de threads: 4096).

Aucune nouvelle tentative Avec réessayer
4094 212888

référence

Recommended Posts

[Ruby / Rails] Mécanisme de nouvelle tentative d'erreur de thread
Test des messages d'erreur: Notes du didacticiel Rails - Chapitre 7
Conseils pour la gestion des erreurs de gRPC dans Ruby
Explication de Ruby sur rails pour les débutants ①
[Ruby on Rails] Mémo d'introduction Select2 pour Webpacker
[Rails] Procédure de liaison de bases de données avec Ruby On Rails
[Ruby on Rails] Affichage individuel des messages d'erreur
[Ruby On Rails] Causes et remèdes pour ActionView :: Template :: Error (ActiveStorage :: InvariableError) (hypothèse / vérification)
Rails constante non initialisée Une simple liste de contrôle pour la résolution des erreurs
Solution de contournement pour l'erreur Bundler.require lors de l'exécution de ruby avec crontab
Rails / Ruby: Comment obtenir du texte HTML pour Mail
Explication de Ruby sur rails pour les débutants ⑥ ~ Création de validation ~
Explication de Ruby on rails pour les débutants ② ~ Création de liens ~
Explication de Ruby on rails pour les débutants ⑦ ~ Implémentation Flash ~
[Note] Liste des erreurs de rails
À propos des messages d'erreur Ruby
Erreur de routage Catch Rails
Rubis aromatisé aux rails
abréviation de la méthode ruby
Remarques sur le fil de discussion Ruby # [] = méthode
Erreur d'installation de Mac Rails
Ruby on Rails élémentaire
Association Ruby On Rails
[Rails] Solution de contournement pour les classes générées automatiquement avec des messages d'erreur de conception
[Procédure 1 pour les débutants] Ruby on Rails: Construction d'un environnement de développement
Explication de Ruby on rails pour les débutants ③ ~ Création d'une base de données ~