Добавление методов простым сервером RPC в чистоте и разделенном виде

StackOverflow https://stackoverflow.com/questions/3197988

Вопрос

Я создал простой RPC. Сервер для выполнения определенных задач, общих для наших команд, но которые называются разными сетями. Сервер выглядит так (я не включаю обработку ошибок для краткости):

from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor
import json

class MyProtocol(Protocol):
    def dataReceived(self, data):
        req = json.loads(data) # create a dictionary from JSON string
        method = getattr(self, req['method']) # get the method
        method(req['params']) # call the method

    def add(self, params):
        result = {} # initialize a dictionary to convert later to JSON
        result['result'] = sum(params) 
        result['error'] = None 
        result['id'] = 1
        self.transport.write(json.dumps(result)) # return a JSON string
        self.transport.loseConnection() # close connection

factory = Factory()
factory.protocol = MyProtocol
reactor.listenTCP(8080, factory)
reactor.run()

Это очень просто: сервер получает запрос JSON RPC от клиента, ищет метод и вызывает метод, передающий параметры. Сам метод является возврата ответа JSON RPC. Для менее знакомого, JSON RPC. выглядит примерно так:

request:
{"method":"my_method", "params":[1,2,3], "id":"my_id"}
response:
{"result":"my_result", "error":null, "id":"my_id"}

Сервер RPC, так как у меня есть, он очень хорошо обслуживает мои текущие цели (как вы можете себе представить, моя задача очень проста). Но мне нужно будет продолжать добавлять методы, так как сложность задачи увеличивается.

Я не хочу открывать основной файл и добавить еще один def method3(...) и, через две недели добавить def method4(...) и так далее; Код будет расти слишком быстро, и обслуживание будет сложнее и сложнее.

Итак, мой вопрос: Как я могу создать архитектуру, которая позволяет мне регистр Методы на сервер. Отказ Бонус будет иметь отдельную папку, удерживающую один файл на метод, чтобы они могли легко обделить и поддерживать. Эта «архитектура» также позволит мне отложить поддержание некоторых методов для кого-то другого, независимо от их понимания скрученных.

Мне все равно, если мне нужно будет перезапустить сервер каждый раз, когда новый метод зарегистрирован, но очевидный плюс будет, если я нет есть тоже :).

Спасибо.

Это было полезно?

Решение

Немного вкусного порядка;) Но вот несколько начальных шагов для вас (очень сильно издевается, витая специфики, отмените в примерах):

# your twisted imports...
import json

class MyProtocol(object): # Would be Protocol instead of object in real code

    def dataReceived(self, data):
        req = json.loads(data) # create a dictionary from JSON string
        modname, funcname = req['method'].split('.')
        m = __import__(modname)
        method = getattr(m, funcname) # get the method
        method(self, req['params']) # call the method

Предполагая, что вы пробуете его, как будто мы выполнили это:

mp = MyProtocol()
mp.dataReceived('{"method":"somemod.add", "params":[1,2,3]}')

У вас есть модуль somemod.py в том же каталоге, что и пример со следующим содержимым (отражает ваш примерный метод .add() над):

import json

def add(proto, params):
    result = {} # initialize a dictionary to convert later to JSON
    result['result'] = sum(params)
    result['error'] = None
    result['id'] = 1
    proto.transport.write(json.dumps(result)) # return a JSON string
    proto.transport.loseConnection() # close connection

Это позволяет вам использовать один модуль на метод. То method(.. Вызов выше всегда будет проходить ваш MyProtocol экземпляр для обслуживания Callable. (Если вы действительно хотите методы экземпляра, вот инструкции о том, как добавить методы с помощью Python: http://rirepupavel.com/documents/python/instancemethod/ )

Вам понадобится много обработки ошибок. Например, вам нужно много проверок ошибок на split() Вызов на линии 2 dataReceived().

С этим вы можете иметь отдельные файлы с одной функцией в них для каждого метода, необходимого для поддержки. Ни в коем случае не полный пример, но это может выйти, поскольку вы ищете довольно сложное.

Для более официальной регистрации я бы порекомендовал dict в MyProtocol С именами методов, которые вы поддерживаете, вдоль линий:

# in MyProtocol's __init__() method:
self.methods = {}

И метод регистра ..

def register(self, name, callable):
    self.methods[name] = callable

..Модифицировать dataReceived()..

def dataReceived(self, data):
    # ...
    modname, funcname = self.methods.get(req['method'], False)
    # ..continue along the lines of the dataReceived() method above

Краткое резюме слишком длинного поста: __import__ функция ( http://docs.cython.org/library/functions.html. ) наверняка будет ключевой частью вашего решения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top