Решение по рефакторингу: библиотека очереди сообщений, синхронизация звонящих или разгрузка, создание выделенных потоков чтения / записи в библиотеке - PullRequest
1 голос
/ 30 декабря 2010

Я занимаюсь рефакторингом проекта, который я не проектировал.Он написан на C / C ++ для Linux.В проекте есть основной клиентский компонент, который выглядит следующим образом:

Клиент -> Библиотека очереди вывода (OQL) -> Контроллер

Клиент

  • Грязный полусложный код, плохо спроектированный (мешанина ООП-приближений с использованием синглетонов / пространств имен, просто странно во многих местах - но это работает)
  • Реализация пользовательского протокола (не мой протокол, не может изменить)
  • Общая библиотека
  • Многопоточный
    • Несколько потоков вызывают API-интерфейсы OQL, то есть вывод нескольких потоков
  • Принимает команды от контроллера через API
  • Создает массивный неупорядоченный вывод, который не обязательно напрямую (и определенно не 1: 1) зависит от входа контроллера)

Библиотека очереди вывода (OQL)

  • Простой чистый код, на самом деле не предназначенный для текущей рабочей нагрузки (никогда не предназначался для очереди, изначально он просто записывал в stdout, а затем помещалась в очередь сообщений)
  • Общая библиотека
  • Однопоточный
  • Предоставляет API, который принимает многие типы данных от клиента и создает текстовые представления этих данных
  • Вставляет данные в сообщение sys Vочередь

Контроллер

  • Исполняемый файл
  • Однопоточный
  • Элегантный, отказоустойчивый C ++, который широко использует boost
  • Написанный мной с нуля, единственная часть проекта, которую мне было позволено полностью «исправить», так сказать
  • Взаимодействует с клиентской библиотекой через API для установления соединения с сервером
    • Сохраняет данные, полученные клиентом, и считывает их из OQL в базу данных на другом уровне

Таким образом, проблема сводится к тому, что контроллер является однопоточным и вызывает много функций API вклиентская библиотека.Сценарии, возникающие из-за того, что контроллер вызывает клиентский API.

  1. Обычный (98% +)
    1. Контроллер вызывает функцию клиентского API
    2. Функция клиентского API выполняет магию внутренне
    3. API-функция возвращает true
    4. Клиент получает данные в результате магии на шаге 2, в другом потоке выполнения и вызывает функцию OQL put из вторичного потока
    5. OQL записывает данные в очередь сообщенийочередь либо блокирует, либо не блокирует, но это не имеет значения, поскольку основной поток выполнения контроллера работает и обрабатывает данные.
    6. Success!
  2. Сценарий проблемы
    1. Контроллер вызывает функцию API клиента
    2. Функция API клиента немедленно дает результат, и ДО возврата вызовов вызов функции OQL из основного потока выполнения в Контроллере
    3. OQL записывает данные в очередь сообщений и одинпроисходит следующее:
      1. Очередь сообщений не заполнена, не блокируется, все возвращается и продолжениеролик обрабатывает новые данные в очереди сообщений, и жизнь продолжается счастливо
      2. Сценарий проблемы Очередь сообщений заполнена и блок DOES

Теперь я уверен, что вы можете видеть в проблемном сценарии, который является редким, основной поток выполнения блокирует полную очередь сообщений, а также данные не обрабатываются с другого концаочередь, так как контроллер однопоточный ...

Так что да, это немного беспорядок, и нет, я не доволен дизайном, но я должен найти лучший способ решить это безпереписывая все эти взаимодействия.

Я пытаюсь выбрать между:

  1. Копание в клиенте, синхронизация всех потоков в один поток ввода-вывода, которыйвзаимодействует с OQL

    • У меня практически нет веры в то, что кто-то после меня не зайдет и не сломает это в будущем, не внесет значительных ошибок и не сможет понять, почему
  2. Введение потока записи в OQL

    • Принимает простой класс и значительно усложняет его
    • Вводит смешные проблемы
      • Не нужна очередьочередь в этот момент?Поскольку данные должны переноситься в поток писателя

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

Ответы [ 2 ]

2 голосов
/ 30 декабря 2010

Изменить клиента, чтобы он возвращал ошибку при заполнении Q, чтобы контроллер мог принять разумное решение о том, как продолжить.

0 голосов
/ 30 декабря 2010

Вы можете изменить контроллер, чтобы использовать второй поток для чтения из очереди сообщений (и просто отправить данные в гораздо больший буфер, внутренний для контроллера, для чтения основным потоком контроллера).

...