2009-04-30 9 views
4

Ma question est: quel framework python dois-je utiliser pour construire mon serveur?Python "Task Server"

Notes:

  • Ce pourparlers de serveur HTTP avec ses clients: GET et POST (via PyAMF)
  • clients "soumettre" "tâches" pour le traitement et, puis, quelque temps plus tard, récupérer les associés " task_result »
  • soumettre et de récupérer peuvent être séparés par jours - différentes connexions HTTP
  • La « tâche » est un morceau de XML décrivant un problème à résoudre, et un « task_result » est un morceau de XML décrivant une réponse.
  • Lorsqu'un serveur obtient une "tâche", il la met en file d'attente pour traitement
  • Le serveur gère cette file d'attente et, lorsque les tâches arrivent en haut, organise leur traitement.
  • le traitement est effectué par un programme externe de longue durée (via un sous-processus) qui alimente la tâche XML et produit un bloc de données XML "task_result" que le serveur récupère et stocke (pour récupération ultérieure du client)).
  • il sert quelques pages HTML de base indiquant l'état de file d'attente et de traitement (fins d'administration uniquement)

Je l'ai expérimenté avec twisted.web, en utilisant SQLite comme la base de données et les fils pour gérer les longs processus en cours .

Mais je ne peux m'empêcher de penser qu'il me manque une solution plus simple. Suis-je? Si vous étiez confronté à cela, quelle combinaison de technologies utiliseriez-vous?

Répondre

0

Il semble que tout cadre web python répondra à vos besoins. Je travaille quotidiennement avec un système similaire et je peux vous dire que votre solution avec des threads et SQLite pour le stockage des files d'attente est à peu près aussi simple que vous le ferez.

En supposant que l'ordre n'a pas d'importance dans votre file d'attente, les threads devraient être acceptables. Il est important de vous assurer que vous ne créez pas de conditions de concurrence avec vos files d'attente ou, par exemple, que deux types de travail identiques s'exécutent simultanément. Si c'est le cas, je suggérerais une seule application threadée pour faire les éléments de la file d'attente un par un.

1

Je suggère ce qui suit. (Puisque c'est ce que nous faisons.)

Un serveur WSGI simple (wsgiref ou werkzeug). Les requêtes HTTP entrant formeront naturellement une file d'attente. Aucune autre file d'attente nécessaire. Vous obtenez une requête, vous générez le sous-processus en tant qu'enfant et attendez qu'il se termine. Une simple liste d'enfants est à peu près tout ce dont vous avez besoin.

J'ai utilisé une modification de la boucle principale "serve forever" dans wsgiref pour interroger périodiquement tous les enfants pour voir comment ils vont. Une base de données SQLite simple peut suivre l'état de la demande. Même cela peut être exagéré parce que vos entrées et résultats XML peuvent simplement rester dans le système de fichiers.

C'est tout. Les files d'attente et les threads n'y entrent pas vraiment. Un seul processus externe de longue durée est trop complexe pour être coordonné. C'est plus simple si chaque requête est un processus séparé, autonome.

Si vous recevez d'immenses paquets de requêtes, vous pouvez avoir besoin d'un simple gouverneur pour empêcher la création de milliers d'enfants.Le gouverneur pourrait être une simple file d'attente, construite en utilisant une liste avec append() et pop(). Chaque demande est acceptée, mais seules les demandes qui correspondent à certaines limites du nombre maximal d'enfants sont supprimées.

+0

"Un seul processus externe de longue durée est trop complexe à coordonner"? Coordonnée avec quoi? En fait, l'idée d'avoir un travailleur externe est d'éviter tout besoin de coordination et de pouvoir facilement contrôler le parallélisme. Comme vous l'avez noté, les processus de génération sont en effet un problème lorsque vous attendez des rafales de requêtes, et vous avez vraiment besoin de plus de coordination. J'ai l'habitude de mettre en place plusieurs travailleurs sur plusieurs machines, et les superviser en utilisant supervord (http://supervisord.org/) – thesamet

+0

Comment obtenez-vous le travail de et vers ce processus de longue durée? Il semble plus simple de simplement fourrer le travail en tant que sous-processus plutôt que de l'engager encore un autre exercice de CIP pour coordonner avec ces travailleurs externes. –

+0

Vous utilisez un framework de file d'attente qui gère ces détails techniques pour vous (voir ma réponse). Je suis d'accord sur le fait que l'approche des sous-processus est plus simple et qu'il y a moins d'infrastructure à s'inquiéter, et c'est un bon choix pour certaines applications.Mais pour tout ce que je cours dans la production, je préférerais quelque chose qui offre plus de contrôle sur le parallélisme, et la mise en place d'un nombre fixe de travailleurs externes fait exactement cela. – thesamet

2

Je vous recommande d'utiliser une file d'attente de messages existante. Il y a beaucoup de choix (voir ci-dessous), et ils varient en complexité et en robustesse.

Aussi, évitez les discussions: (pourquoi ont-ils à courir dans le serveur web) laissez vos tâches de traitement exécutées dans un processus différent

En utilisant une file d'attente de message existant, il vous suffit de vous soucier de la production de messages (dans votre serveur web) et les consommer (dans vos tâches de longue durée). Au fur et à mesure que votre système se développera, vous pourrez augmenter votre taille en ajoutant simplement des serveurs Web et des consommateurs, et vous vous soucierez moins de votre infrastructure de mise en file d'attente.

Certaines implémentations de python populaires de files d'attente de messages:

+1

Un autre basé sur rabbitmq/amqp: http://pypi.python.org/pypi/carrot/0.3.3 –

+0

Vous cherchez vraiment une file d'attente de messages. J'ai eu de la chance avec beanstalkd et j'ai entendu de bonnes choses à propos de http://www.rabbitmq.com/ et http://www.zeromq.org/, et il y a aussi toujours gearman: http: // www. danga.com/gearman/. On dirait que vous êtes plus intéressé par les tâches à exécution longue que par l'invocation à haute fréquence, donc à peu près n'importe quelle file d'attente fonctionnera pour vous. – Parand

1

Ma réaction est de proposer Twisted, mais vous avez déjà regardé ce. Pourtant, je m'en tiens à ma réponse. Sans connaître vos points de douleur personnels, je peux au moins partager certaines choses qui m'ont aidé à réduire presque toute la folie différée qui survient lorsque vous avez plusieurs actions dépendantes et bloquantes que vous devez effectuer pour un client.

Les rappels en ligne (légèrement documentés ici: http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.defer.html) fournissent un moyen de rendre les longues chaînes de caractères différés beaucoup plus lisibles (au point de ressembler à du code en ligne droite). Voici un excellent exemple de réduction de la complexité: http://blog.mekk.waw.pl/archives/14-Twisted-inlineCallbacks-and-deferredGenerator.html

Vous n'avez pas toujours besoin d'intégrer votre traitement de masse à Twisted. Parfois, il est plus facile de décomposer une grande partie de votre programme en un outil de ligne de commande autonome, facilement testable/modifiable/implémentable et Twisted invoque cet outil dans un autre processus. Le ProcessProtocol de Twisted fournit une manière assez flexible de lancer et d'interagir avec des programmes auxiliaires externes. En outre, si vous décidez soudainement que vous souhaitez cloudify votre application, il n'est pas si difficile d'utiliser un ProcessProtocol pour simplement exécuter votre traitement en bloc sur un serveur distant (instances EC2 aléatoires peut-être) via ssh, en supposant que vous avez les clés sont déjà configurées.

+0

Vous pouvez utiliser https://launchpad.net/ampoule pour rendre la vie un peu plus facile sur le plan des processus de frai. – Glyph

1

Vous pouvez jeter un oeil à céleri

Questions connexes