Quartznet: Prise en charge asynchrone/en attente

CrĂ©Ă© le 30 mars 2015  Â·  27Commentaires  Â·  Source: quartznet/quartznet

Ce serait formidable si Quartz.net prend en charge les travaux asynchrones.

De plus, j'ai trouvé le fil de discussion correspondant dans la liste de diffusion : http://quartz.10975.n7.nabble.com/quartznet-3668-using-Tasks-in-quartz-jobs-td10753.html

Tous les 27 commentaires

Merci pour la demande, nous pouvons étudier les possibilités avec la version 3.0.

Je vais deuxiĂšmement ceci - ce serait formidable que Quartz prenne en charge async/wait.

Avons-nous une idée d'un calendrier pour la version 3.0 ?

J'ai commencĂ© le travail de rĂ©vision async/wait et c'est toute une entreprise. Je ne donnerai pas d'Ă©chĂ©ancier pour ne pas vous dĂ©cevoir, mais je vous tiendrai au courant. Il y aura certainement des versions alpha et bĂȘta Ă  tester.

J'ai apporté des modifications massives aux API et aux composants internes pour mieux prendre en charge async/wait avec commit https://github.com/quartznet/quartznet/commit/f78cf38e3f3ed6b76f044b9b0aa78e66dc6c5b62 . Cela devrait offrir une meilleure efficacité interne lorsqu'il s'agit de faire fonctionner l'infrastructure Quartz.

Les emplois rĂ©els restent problĂ©matiques. Si nous voulons que les travaux prennent en charge les tĂąches asynchrones, cela signifierait Ă©galement abandonner l'utilisation actuelle du pool de threads. Les threads de travail ne peuvent pas ĂȘtre ressaisis correctement lorsque l'attente est en cours d'utilisation - cela briserait les garanties d'avoir autant de travaux en cours d'exĂ©cution qu'il y a de threads de pool de threads en cours d'exĂ©cution.

Prendre en charge async/wait au niveau du travail signifierait s'appuyer sur le pool de threads .NET et une plus grande séparation du flux d'exécution. J'hésite un peu à faire ce changement...

Pouvez-vous suggĂ©rer un modĂšle alternatif pour me permettre d'invoquer des opĂ©rations en attente dans les travaux, si ce travail ne va pas ĂȘtre entrepris?

Pour parler spécifiquement de la rupture de la promesse de ne pas avoir plus de travaux qu'il n'y a de threads dans le pool de threads : ne pas rompre cette promesse n'est-il pas l'un des arguments pour faire ce travail en premier lieu ? Lorsqu'il y a beaucoup d'E/S en cours, nous ne voulons pas bloquer les threads en mode utilisateur en attendant l'achÚvement des E/S car cela signifie que nous avons beaucoup de planification préemptive des threads pour interroger l'achÚvement et l'épuisement des E/S. limites de thread malgré le fait qu'il n'y a aucun travail CPU utile sur eux. Donc, si nous voulons maximiser l'utilisation du processeur et des E/S, pourquoi ne pas autoriser plus de tùches que le nombre maximal de pools de threads, si cela signifie que nous pouvons laisser bon nombre de ces tùches en attente de congestion des E/S et ne pas essayer de thread.

@mleyb Je n'ai pas encore abandonnĂ© tout espoir, je continue de jouer avec des alternatives de mise en Ɠuvre ...

@Jawvig Le mĂ©lange du pool de threads Quartz et du pool de threads .NET CLR a des consĂ©quences qui peuvent ĂȘtre difficiles Ă  communiquer.

Nous pourrions effectivement autoriser le dĂ©marrage de milliers de travaux en mĂȘme temps lorsque nous avons une taille de pool de threads de 10. Tous les travaux dĂ©marrent et dĂ©marrent des opĂ©rations asynchrones, ainsi le thread de travail est renvoyĂ© et de nouveaux travaux peuvent dĂ©marrer.

Nous pourrions avoir besoin d'un pool de threads spécial (basé sur TaskScheduler) pour le travail basé sur asynchrone qui se déclenchera du travail, mais cela devient alors intéressant. Cela m'amÚne à penser que ce pool de threads spécial ne devrait pas permettre la configuration de la taille car "cela dépend".

Je dirais que cela pourrait ĂȘtre bien jusqu'au moment oĂč l'Ă©puisement du pool de threads CLR se produit, disons qu'il s'agit d'une application ASP.NET qui a des demandes en file d'attente. Quartz a pu contourner l'Ă©puisement en disposant de son propre pool de threads et en utilisant des tĂąches de synchronisation.

Donc je voulais juste soulever ces points qui pourraient ĂȘtre problĂ©matiques et c'est super que cette discussion ait lieu. Je veux entendre avec impatience toutes les opinions sur les avantages et les inconvĂ©nients sur la question.

Quelques pistes de réflexion :

  • devrions-nous avoir l'interface IAsyncJob, retirer IInteruptableJob et faire en sorte que IJobExcutionContext contienne CancellationToken qui peut ĂȘtre utilisĂ© Ă  la fois pour les tĂąches asynchrones et synchronisĂ©es ?
  • devrions-nous autoriser uniquement IAsyncJobs Ă  s'exĂ©cuter sur un planificateur dont le pool de threads CLR est configurĂ© comme seul pool de threads ?

Re : retrait IInterruptableJob : mĂȘme si nous parlons d'une version majeure, je pense que nous devrions conserver IInterruptableJob pour la rĂ©trocompatibilitĂ©. Je ne peux pas penser aux circonstances dans lesquelles annuler via un CancellationToken et aussi appeler Interrupt serait un problĂšme. Quartz est lĂ©gĂšrement gonflĂ©, mais nous pourrions modifier le document de code pour indiquer que IInterruptableJob pourrait ĂȘtre supprimĂ© dans les futures versions et que l'utilisation de CancellationToken dans IJobExecutionContext est prĂ©fĂ©rable.

Re : interface IAsyncJob : je pense que c'est la bonne chose à faire.

Re : ExĂ©cuter IAsyncJob s sur un planificateur avec des pools de threads hybrides : j'ai l'impression que ce serait une mauvaise idĂ©e. Lorsque le CLR est utilisĂ© pour fournir un ThreadPool rĂ©glĂ© sur lequel TPL peut effectuer ses opĂ©rations, il semblerait erronĂ© de saper les hypothĂšses sur lesquelles il a Ă©tĂ© construit en ayant un ensemble de threads supplĂ©mentaires assis dans le mĂȘme processus dont il n'a aucune visibilitĂ©. . Donc, pour ĂȘtre clair, je serais en faveur d'insister pour autoriser uniquement l'exĂ©cution de IAsyncJob sur un planificateur oĂč le pool de threads CLR est configurĂ© comme le seul pool de threads.

J'ai fait la premiÚre itération avec le concept maintenant, l'exemple 16 a du code pour introduire le IAsyncJob :

https://github.com/quartznet/quartznet/tree/quartznet-3/src/Quartz.Examples/example16

IJobAsync ne serait-il pas la convention de dénomination appropriée qui serait conforme aux autres noms de modÚles asynchrones ?

Le 26 juillet 2015, Ă  6h23, Marko Lahma [email protected] a Ă©crit :

J'ai fait la premiÚre itération avec le concept maintenant, l'exemple 16 a du code pour introduire le IAsyncJob :

https://github.com/quartznet/quartznet/tree/quartznet-3/src/Quartz.Examples/example16

—
RĂ©pondez directement Ă  cet e-mail ou consultez-le sur GitHub.

Je crois que le modÚle commun avec async _methods_ est de postfixer les noms de méthodes avec Async (ce que Quartz ne fait pas actuellement). Je dirais donc qu'avec un nom de classe comme AsyncJob, le message sur l'intention est meilleur.

@lahma

ASP.NET app that has requests queuing up. Quartz has been able to circumvent exhaustion by having its own thread pool and using sync jobs.

Si je ne me trompe pas, vous parlez de "contre-pression". J'ai rencontré ce problÚme de tùche asynchrone mise en file d'attente par un producteur de messages de longueur trÚs rapide et pratiquement infini, qui a mis en file d'attente tant de messages en une minute que le processus manque de mémoire.

J'ai utilisé des extensions réactives à ce moment-là, et le remplacer par le flux de données de Tpl a parfaitement résolu le problÚme. Que diriez-vous d'utiliser ActionBlock :
https://msdn.microsoft.com/en-us/library/hh194684%28v=vs.110%29.aspx

var executor = new ActionBlock<IJobAsync>(async job => await job.ExecuteAsync(), 
    new ExecutionDataflowBlockOptions{
         MaxDegreeOfParallelism = maxTasksLimit,
         BoundedCapacity = 1
    });

 // scheduler
SchduleJob(job) {
     await executor.SendAsync(job)
  1. Nous pouvons limiter l'exécution simultanée de tùches.
  2. La capacité de la mémoire tampon de l'exécuteur est limitée, donc si la limite est atteinte, l'expéditeur "attendra".

@vchekan merci ! J'ai besoin d'étudier cela un peu plus.

ActionBlock est assez pratique. Je l'utilise pour implémenter la limitation par rapport à une API tierce.

Pour tirer parti du commentaire de Vadim, nous aurions probablement besoin de faire plus que await executor.SendAsync(job) afin de mettre en Ɠuvre des stratĂ©gies de ratĂ©s, etc. Nous pourrions Task.Wait(TimeSpan) et traiter cela comme un ratĂ© si le dĂ©lai expire.

Quoi qu'il en soit, Ă  part cela, je voulais commenter les noms des mĂ©thodes API dans l'exemple que vous avez mis en place, Marko. Comme vous l'avez notĂ©, la plupart des mĂ©thodes asynchrones que l'on rencontre sont suffixĂ©es "Async", alors que celles de votre exemple ne l'Ă©taient pas. De plus, de nombreuses mĂ©thodes seront devenues asynchrones sans avoir changĂ© de nom, par exemple IScheduler.Start , IScheduler.Interrupt . Je pense que cela pourrait avoir trop de consĂ©quences imprĂ©vues sur le code existant lors de la mise Ă  niveau. Étant donnĂ© qu'il s'agit de mĂ©thodes void , le code client se compile toujours avec lui et navigue Ă  travers la crĂ©ation de tĂąches sans attendre leur achĂšvement.

Puis-je suggĂ©rer de conserver les mĂ©thodes existantes et d'ajouter de nouvelles mĂ©thodes qui se terminent par "Async" ? Les mĂ©thodes existantes peuvent ĂȘtre implĂ©mentĂ©es en tant que mĂ©thodes synchrones qui appellent les mĂ©thodes Async et .Wait() sur leurs tĂąches. J'ai le sentiment que cela fournira un chemin de mise Ă  niveau beaucoup plus facile pour les personnes sans effets secondaires involontaires.

Toutes mes excuses si je manque quelque chose d'évident à propos de l'intention, ici !

@Jawvig Je suis toujours un peu sur la clĂŽture de l'utilisation du postfix Async. Je ne vois pas l'intĂ©rĂȘt d'avoir Ă  la fois des versions synchronisĂ©es et asynchrones des mĂ©thodes, car async est dĂ©sormais prĂ©fĂ©rĂ©. Avoir une API publique uniquement asynchrone soulĂšve alors la question de savoir s'il est logique d'avoir un suffixe Async. Casser la compilation est bien sĂ»r agrĂ©able pour que le consommateur de l'API sache Ă  quoi se prĂ©parer.

J'ai envoyĂ© un ping au projet MassTransit Ă  ce sujet (ils subissent le mĂȘme changement) et j'ai eu la discussion ici https://github.com/MassTransit/MassTransit/issues/314 .

Il existe un test séparé pour détecter qu'il n'y a pas de méthodes void asynchrones (qui sont les tueurs).

@lahma Je n'aime pas vraiment cingler, mais y a-t-il des plans ou des estimations quand (ou si) cela va ĂȘtre fait et relĂąchĂ© dans la nature ?

d'accord - j'aimerais vraiment commencer Ă  l'utiliser

:+1: pour quelques infos :)

Vous pouvez suivre la progression de la branche quartznet-3 https://github.com/quartznet/quartznet/tree/quartznet-3 , il y a maintenant des versions nocturnes mais l'API a déjà de nombreux changements pour prendre en charge le modÚle.

DĂ©solĂ© d'ĂȘtre un parasite, mais je me demande simplement si vous avez un calendrier pour savoir quand Quartz 3 sera prĂȘt. Mon projet repose sur l'achĂšvement de cette fonctionnalitĂ© pour le moment. Il semble que vous ne puissiez pas exĂ©cuter une requĂȘte HttpClient dans un travail Quartz pour le moment si vous avez besoin d'un comportement synchrone et que vous avez un intervalle infĂ©rieur au temps d'aller-retour de la requĂȘte Http. Quartz n'"attendra" pas la valeur de retour et vos requĂȘtes commenceront Ă  se chevaucher. Je suppose que ce nouveau type de travail asynchrone rĂ©soudrait ce problĂšme ? J'utilise mono et je pense que HttpClient est la seule option et qu'il n'a que des requĂȘtes asynchrones.

Les emplois Asyn eux-mĂȘmes ne sont peut-ĂȘtre pas la solution miracle. Vous pouvez forcer le rĂ©sultat synchrone pour HttpClient en utilisant client.GetAsync(_address).Result qui Ă©value la requĂȘte. Est-ce que ça marche pour toi? Vous avez Ă©galement mentionnĂ© le chevauchement des tĂąches, qui peut ĂȘtre gĂ©rĂ© avec [DisallowConcurrentExecution] si cela aide.

Et oui, j'ai esquivé la question initiale, car je ne veux pas faire de promesses difficiles à tenir.

J'apprĂ©cie votre rĂ©ponse rapide (et honnĂȘte). Pouvez-vous me donner un trimestre oĂč vous espĂ©rez actuellement sortir ? Comme Q3 2016, Q4 2016, Q1 2017 ?

J'ai trouvé une option similaire à celle que vous avez fournie dans les 2 minutes suivant la publication (cela se produit toujours ?). Je l'ai déjà bien fonctionné, donc pas de soucis là-bas.

Je devrais profiter de l'occasion pour exprimer mon amour pour Quartz. Je l'ai utilisĂ© pour construire un microframework pour faciliter la configuration, l'Ă©criture et le dĂ©ploiement de microservices et Quartz en est le cƓur. J'ai eu la chance de tomber dessus avant de rĂ©Ă©crire quelque chose qui Ă©tait Ă  moitiĂ© aussi bon. Merci Ă  tous les contributeurs de l'avoir mis Ă  disposition.

Je pense que nous pouvons commencer Ă  donner de la qualitĂ© alpha dans les deux prochaines semaines. Les bases sont solides (calculs de dĂ©clenchement, gestion des donnĂ©es du magasin d'emplois - ils n'ont pas eu de changements) mais Ă  mesure que le travail Ă©volue autour de l'asynchronisme/attente et des pools de threads et de l'API leur stabilitĂ© ne peut ĂȘtre garanti. La communication Ă  distance sera Ă©galement abandonnĂ©e et devra ĂȘtre rĂ©Ă©crite au-dessus de l'API HTTP/Web afin que le contrĂŽle Ă  distance du planificateur ne fasse pas partie des premiĂšres suppressions.

Une mise Ă  jour pour ceci ?

La construction alpha sans gestion Ă  distance devrait ĂȘtre rĂ©alisable trĂšs bientĂŽt sur le flux nuget.org.

Alpha 1 a atterri sur NuGet, veuillez consulter l' annonce . Il reste encore beaucoup Ă  faire, mais il devrait maintenant ĂȘtre plus facile de botter les pneus.

Je ferme ce sujet pour l'instant, merci pour votre patience !

Des scÚnes incroyables ! Merci - j'ai hùte d'essayer ça

Cette page vous a été utile?
0 / 5 - 0 notes