Domanda

Ho un'applicazione web Django. Ho anche un server incantesimo scritto usando esecuzione contorto sulla stessa macchina con Django (in esecuzione su localhost:8090). L'idea è quando l'utente fa una certa azione, richiesta arriva a Django che a sua volta si connette a questo server contorto e server invia dati al Django. Infine Django mette questi dati in qualche html template e serve indietro per l'utente.

Ecco dove sto avendo un problema. Nella mia app Django, quando la richiesta arriva a creare un semplice client contorto per la connessione al server contorto eseguito in locale.

...
        factory = Spell_Factory(query) 
        reactor.connectTCP(AS_SERVER_HOST, AS_SERVER_PORT, factory)
        reactor.run(installSignalHandlers=0)
        print factory.results
...

Il reactor.run() sta causando un problema. Dal momento che si tratta di un ciclo di eventi. La prossima volta che lo stesso codice viene eseguito da Django, io sono in grado di connettersi al server. Come si fa a gestire questa situazione?

È stato utile?

Soluzione

I due precedenti risposte sono corrette. Tuttavia, considerando che hai già implementato una grafia server quindi Esegui come uno . Si può iniziare eseguendo sulla stessa macchina come un processo separato - a localhost:PORT. In questo momento sembra avere un'interfaccia molto semplice protocollo binario già -. È possibile implementare un altrettanto semplice client Python utilizzando l'interfaccia socket del lib standard nella modalità di blocco

Tuttavia, vi consiglio di giocare con twisted.web ed esporre una semplice interfaccia web. È possibile utilizzare JSON per serializzare e deserializzare i dati - che è ben supportato da Django. Ecco un esempio molto veloce:

import json
from twisted.web import server, resource
from twisted.python import log

class Root(resource.Resource):
    def getChild(self, path, request):
        # represents / on your web interface
        return self

class WebInterface(resource.Resource):
    isLeaf = True
    def render_GET(self, request):
        log.msg('GOT a GET request.')
        # read request.args if you need to process query args
        # ... call some internal service and get output ...
        return json.dumps(output)

class SpellingSite(server.Site):
    def __init__(self, *args, **kwargs):
        self.root = Root()
        server.Site.__init__(self, self.root, **kwargs)
        self.root.putChild('spell', WebInterface())

E per farlo funzionare è possibile utilizzare il seguente file .tac scheletro:

from twisted.application import service, internet

site = SpellingSite()
application = service.Application('WebSpell')
# attach the service to its parent application
service_collection = service.IServiceCollection(application)
internet.TCPServer(PORT, site).setServiceParent(service_collection)

Il funzionamento del vostro servizio come un altro servizio di prima classe consente di eseguire su un'altra macchina un giorno se si trova la necessità -. Esporre un'interfaccia web rende facile orizzontalmente scalare dietro un bilanciatore di carico proxy inverso troppo

Altri suggerimenti

reactor.run() dovrebbe essere chiamato solo una volta in tutto il programma. Non pensare ad esso come "start questa richiesta che ho", pensare ad esso come "ricominciare tutto di Twisted".

L'esecuzione del reattore in un thread in background è un modo per aggirare il problema; allora l'applicazione Django può utilizzare blockingCallFromThread nell'applicazione Django e utilizzare un'API ritorto come si farebbe con qualsiasi blocco API. Avrete bisogno di un po 'di collaborazione da contenitore WSGI, però, perché è necessario fare in modo che questo contesto filo ritorto viene avviato e arrestato al momento opportuno (quando il vostro interprete viene inizializzato e abbattuto, rispettivamente).

Si potrebbe anche usare ritorto come contenitore WSGI, e quindi non c'è bisogno di avviare o arrestare niente di speciale; blockingCallFromThread sarà solo lavorare immediatamente. Vedere la guida della riga di comando per twistd web --wsgi.

Si dovrebbe smettere reattore dopo aver ottenuto i risultati da server ritorto o qualche errore / timeout accada. Quindi, a ogni richiesta Django che richiede di query il server ritorto è necessario eseguire reattore e poi fermarlo. Ma, non è supportato dalla libreria ritorto - reattore non può essere riavviato. Possibili soluzioni:

  • Usa thread separato per Twisted reattore, ma è necessario distribuire l'applicazione Django con il server, che ha il supporto per l'esecuzione di lunghi fili (non lo faccio ora uno di questi, ma è possibile scrivere il proprio facilmente: -.))

  • Non utilizzare ritorto per l'attuazione protocollo client, basta usare il modulo di socket stdlib pianura.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top