2017-02-17 3 views
0

С моей текущей настройкой я запускаю сервер с Django, и я пытаюсь автоматизировать резервное копирование в облаке всякий раз, когда действие POST/PUT сделал. Чтобы обойти задержку (Ping на сервер колеблется около 100 мс, и действие может достигнуть вверх из 10 предметов, отправленных сразу), я решил создать отдельный объект с клиентом requests и просто иметь этот дескриптор для всех резервных функций.Как убедиться, что данные по UNX Sockets отправляются в порядке, используя Twisted Python

Для этого у меня есть сущность, прослушивающая через UNX с помощью twisted, и я отправляю ей строку через нее всякий раз, когда попадаю в конечную точку. Проблема состоит в том, что если слишком много конечных точек сразу вызываются или вызывается быстро, данные, отправленные по сокету, больше не приводятся в порядок. Есть ли способ предотвратить это? Код ниже:

UNX Сервер:

class BaseUNXServerProtocol(LineOnlyReceiver): 

    rest_client = RestClient() 

    def connectionMade(self): 
     print("UNIX Client connected!") 

    def lineReceived(self, line): 
     print("Line Received!") 

    def dataReceived(self, data): 
     string = data.decode("utf-8") 
     jstring = json.loads(data) 
     if jstring['command'] == "upload_object": 
      self.rest_client.upload(jstring['model_name'], jstring['model_id']) 

Unix Клиент:

class BaseUnixClient(object): 

path = BRANCH_UNX_PATH 
connected = False 

def __init__(self): 
    self.init_vars() 
    self.connect() 

def connect(self): 
    if os.path.exists(self.path): 
     self.client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 
     self.client.connect(self.path) 
     self.connected = True 
    else: 
     print("Could not connect to path: {}".format(self.path)) 

def call_to_upload(self, model_class, model_id, upload_type): 
     self.send_string(_messages.branch_upload_message(model_class, model_id, upload_type)) 

Endpoint perform_create: (По существу, крюк, который вызывается всякий раз, когда новый объект публикуемую)

def perform_create(self, serializer): 
    instance = serializer.save() 

    # Call for upload/notify 
    UnixClient().call_to_upload(model_class=type(instance).__name__, model_id=instance.id, upload_type="create") 

ответ

1

SOCK_STREAM соединения всегда заказываются. Данные по одному соединению выходит в том же порядке, в котором он находился (или разрывает соединение).

Только очевидная проблема с кодом, которым вы поделились, заключается в том, что вы не должны переопределять dataReceived на подклассе LineOnlyReceiver. Вся ваша логика принадлежит lineReceived.

Это не вызовет проблем с нестандартными данными, но это может привести к проблемам с кадрированием (например, обрабатываемые частичные сообщения JSON или объединение нескольких сообщений), что, вероятно, приведет к тому, что json.loads поднимет исключение.

Итак, чтобы ответить на ваш вопрос: данные доставляются по порядку. Если вы видите операцию вне порядка, это происходит потому, что данные отправляются в другом порядке, чем вы ожидаете, или потому, что существует расхождение между порядком доставки данных и порядком наблюдаемых побочных эффектов. Я не вижу никакого способа дать дополнительный диагноз, не видя больше вашего кода.

Увидев ваш код отправки, проблема в том, что вы используете новое соединение для каждой операции perform_create. Существует нет гарантия о доставке через разные соединений. Даже если ваша программа делает:

  • установить связи с этим
  • отправить данные о связи с этим
  • установить соединение б
  • передачи данных по соединению б
  • тесной связи с этим
  • тесная связь б

Получатель может решить обработать данные о соединении b перед данными о подключении a.Это связано с тем, что основная система уведомлений о событиях (select, epoll_wait и т. Д.), Насколько мне известно, не сохраняет информацию о заказе событий, о которых она сообщает. Вместо этого результаты выводятся в псевдослучайном порядке или в скучном детерминированном порядке (например, по возрастанию по номеру дескриптора файла).

Чтобы устранить проблему с заказом, сделайте один UnixClient и используйте его для всех ваших звонков perform_create.

+0

Эй, Жан! Спасибо за совет! Однако моя проблема связана с данными, отправляемыми в правильном порядке, но полученными в беспорядочном порядке. Я могу заверить вас, что он отправляется прямо в том, что 'perform_create' вызывается каждый раз, когда попадает конечная точка. Вызов одной и той же конечной точки несколько раз должен привести к отправке идентификаторов по порядку, но, увы, это не так. На стороне заметки, когда сообщения были объединены, это была незначительная проблема. Тот, который мне пришлось обходить через небольшой парсер, чтобы это помогло. Благодаря! – Lorenzo

Смежные вопросы