扭曲的XMLRPC代理

时间:2014-09-10 15:29:57

标签: twisted

我想使用twisted来制作带平衡器的XMLRPC代理。

[XMLRPC Server 1_1 8.8.8.8:8000] <-->  [----------------------]   <--- Client
                                       [Proxy example.com:8000]   <--- Client
[XMLRPC Server 1_2 9.9.9.9:8000] <-->  [----------------------]   <--- Client

因此有两个XMLRPC实例代表相同的方法。我需要在这些实例和客户端之间使用xmlrpc-proxy。还有一件事 - 这个代理也应该接受JSON调用(http://example.com:8000/RPC2种类,http://example.com:8000/JSON)。

现在我正在尝试实现XMLRPC代理调用。虽然sendLine()正在调用,但我无法接收回客户的答案。

import argparse

from twisted.internet import protocol, reactor, defer, threads
from twisted.web import xmlrpc
from twisted.internet.task import LoopingCall
from twisted.internet.defer import DeferredQueue, Deferred, inlineCallbacks
from twisted.protocols.basic import LineReceiver

import configfile
from bcsxmlrpc import xmlrpc_request_parser, xmlrpc_marshal
from customlogging import logging

logging.getLogger().setLevel(logging.DEBUG)


class ProxyClient(xmlrpc.Proxy):

    def __init__(self, proxy_uri, user, timeout=30.0):
        self.proxy_uri = proxy_uri
        xmlrpc.Proxy.__init__(self, url=proxy_uri, user=user, connectTimeout=timeout)

    @inlineCallbacks
    def call_api(self, name, *args):
        logging.debug(u"Calling API: %s" % name)
        result = yield self.callRemote(name, *args)
        proxy_pool.add(self.proxy_uri)
        defer.returnValue(result)


class Request(object):
    def __init__(self, method, params, deferred):
        self.method = method
        self.params = params
        self.deferred = deferred


class ProxyServer(LineReceiver):

    def dataReceived(self, data):
        logging.pr(data)
        params, method = xmlrpc_request_parser(data)  # got method name and arguments

        d = Deferred()
        d.addCallbacks(self._send_reply, self._log_error)
        logging.debug(u"%s%s added to queue" % (method, params))
        queue.put(Request(method, params, d))

    def _send_reply(self, result):
        logging.ps(result)
        self.sendLine(str(result))

    def _log_error(self, error):
        logging.error(error)

    def connectionMade(self):
        logging.info(u"New client connected")

    def connectionLost(self, reason):
        logging.info(u"Client connection lost: %s" % reason.getErrorMessage())


class ProxyServerFactory(protocol.Factory):
    protocol = ProxyServer

    def buildProtocol(self, addr):
        return ProxyServer()


@inlineCallbacks
def _queue_execute_job():
    if queue.pending and proxy_pool:
        proxy = proxy_pool.pop()
        request = yield queue.get()
        result = yield ProxyClient(proxy, "").call_api(request.method, *list(request.params))
        request.deferred.callback(result)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Run configuration")
    parser.add_argument('--config', help=u"Configuration file name/path")
    config = configfile.ProxyConfig(parser.parse_args().config)

    global proxy_pool
    proxy_pool = set()
    for proxy_server in config.servers:
        proxy_pool.add(proxy_server)

    global queue
    queue = DeferredQueue()

    lc2 = LoopingCall(_queue_execute_job)
    lc2.start(1)

    logging.info(u"Starting Proxy at port %s" % config.port)
    reactor.listenTCP(config.port, ProxyServerFactory())
    reactor.run()

0 个答案:

没有答案