Предложения по разработке клиента сообщений на основе TCP / IP - PullRequest
0 голосов
/ 18 февраля 2011

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

Моя клиентская библиотека в настоящее время написана на Java, но я думаю переписать ее как на C #, так и на Java, чтобы разные клиенты имели доступ к одному и тому же внутреннему интерфейсу.

Сообщения начинаются с ключевого слова, имеют количество байтов метаданных и затем некоторые данные.Сообщения всегда заканчиваются символом конца сообщения.

Связь между клиентом и сервером дуплексная, обычно принимает форму запроса от клиента, что вызывает несколько ответов от сервера, но может быть уведомлением.Сообщения помечены как включенные:

C: команда

P: Ожидание (сервер все еще обрабатывает запрос)

D: данные данных в ответ на

R: Ответ

B: Занят (Сервер слишком занят для обработки ответа)

N: Уведомление

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

Дуплексные сообщения, как правило, имеют следующий формат сообщения: Клиент -> Сервер: Командный сервер -> Клиент: Ожидающий (необязательно) Сервер -> Клиент: Данные (необязательно) Сервер -> Клиент: Ответ (2-я запись в данных сообщения обозначает, является ли этоэто ошибка или нет)

Я использую протокол более года и никогда не видел сообщения о занятости, но это не значит, что они не происходят.

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

Некоторые сообщения уведомления будут поступать как часть последовательности сообщенийНапример,

NotificationName M00001 NotificationName M00001 NotificationName M00000

Строка M0000X означает, что либо имеется больше данных, либо это конец сообщений.

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

Учитывая это действительно плохо написанное описание того, как работает система, как бы вы пошли о написании транспортного кода на стороне клиента?

У метаданных нет номера сообщения, и я не контролирую базовый протокол, так как он предоставляется поставщиком.

Ответы [ 3 ]

1 голос
/ 18 февраля 2011

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

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

Listener -> event queue -> processing thread -> output queue -> output thread

В .NET подобные вещи довольно легко реализовать, используя BlockingCollection для обработки очередей. Я не знаю, есть ли что-то подобное в Java.

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

Для меня красота замысла производителя / потребителя заключается в том, что он вызывает жесткое разделение между различными частями программы, значительно облегчая отладку каждой из них и сводя к минимуму возможность проблем, связанных с общим состоянием. Единственная немного сложная часть здесь - это то, что вам придется включить соединение (сокет или что-то еще) как часть сообщения, которое становится общим в очередях, чтобы выходной поток знал, куда отправить ответ.

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

Client 1 message A
Client 1 message B
Client 2 message A

Можно ли обработать первое сообщение от Клиента 2 перед обработкой второго сообщения от Клиента 1? Если это так, то вы можете увеличить пропускную способность, используя логически несколько очередей - по одной на клиента. Тогда ваш «потребитель» становится несколькими потоками. Вам просто нужно убедиться, что в каждый момент времени обрабатывается только одно сообщение для каждого клиента.

1 голос
/ 18 февраля 2011

У меня будет один поток для каждого клиента, который выполняет анализ и обработку.Таким образом, обработка будет осуществляться в том порядке, в котором она была отправлена ​​/ доставлена.

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

Если ваша обработка относительно проста и не зависит от внешних систем, один поток должен обрабатывать 1 КБдо 20 000 сообщений в секунду.

Есть ли другие проблемы, которые вы хотели бы исправить?

1 голос
/ 18 февраля 2011

Я могу рекомендовать только для решений на основе Java.

Я бы использовал уже зрелую транспортную среду. Под «некоторыми» я имею в виду единственную, с которой я работал до сих пор - Apache MINA. Тем не менее, это работает, и это очень гибко.

Относительно обработки сообщений не по порядку - для сообщений, которые должны создаваться в том порядке, в котором они были получены, вы можете строить очереди и помещать такие сообщения в очереди.
Чтобы ограничить количество очередей, вы можете создать, например, 4 очереди и направить входящее сообщение в конкретную очередь в зависимости от последних 2 битов (с точностью до 0-3) хэша упорядоченной части сообщения (например, на client_id содержится в сообщении).

Если у вас есть более конкретные вопросы, я могу соответствующим образом обновить свой ответ.

...