Как перехватить широковещательную рассылку ScaleoutMessage: (отредактировано: как отправить сообщение непосредственно на объединительную плату ServiceBus SignalR)

У меня есть следующий сценарий:

  1. Пользовательский запрос на определенный ресурс на сервере. Этот запрос является длительной задачей и очень похож на 2-3 секунды до 10 секунд. Мы выдаем JobTicket пользователю, так как наш пользователь хочет подождать.
  2. При получении запроса мы сохраняем этот запрос в постоянном хранилище и выдаем пользователю токен как JobTicket (GUID).
  3. Пользователь подключается к концентратору, чтобы получить информацию об этом GUID.

В фоновом режиме:

  1. У нас есть WAS Hosted, а также служба Windows для выполнения некоторых операций по этому запросу.
  2. По завершении служба WAS Hosted/Windows вызывает наше веб-приложение, что задание выполнено.
  3. Оттуда на основе тикета задания мы определяем, какой пользователь и при его подключении сообщаем пользователю, что его задание выполнено.

Теперь у нас есть ферма серверов, мы используем Windows Server On Prem ServiceBus 1.1, которая работает нормально, но проблема заключается в том, что мы не можем перехватывать широковещательные сообщения объединительной платы на основе ServiceBus, и сообщение отправляется всем клиентам. Поскольку у нас есть ферма, пользователь промежуточно может иметь разрыв соединения и подключаться к другому серверу на основе балансировщика нагрузки, поэтому нам нужно масштабировать с помощью служебной шины, поскольку она обеспечивает бесшовную интеграцию, и мы также используем для наших внутренних целей в нашем приложении, поэтому мы не хотим использовать какой-либо другой микс в сложном решении.

Я пытался использовать IHubPipelineModule, но по-прежнему транслировал сообщение масштабирования, не проходящее через это, я пытался напрямую подключить код SignalR и отлаживать его, но это занимает много времени. Я не хочу испортить что-то произвольное в реальном коде. Поскольку я вижу, что в OnReceive я вижу, что сообщение приходит, но не могу следовать дальше. Мне просто нужен небольшой механизм, с помощью которого я могу перехватывать широковещательные сообщения и следить за тем, чтобы они доходили до клиента, а не до всего клиента, тратя впустую ресурсы, а также заботу о безопасности.

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

Спасибо, Шреник


person Shrenik Jhaveri    schedule 09.07.2014    source источник
comment
Такой же вопрос задавался ранее в stackoverflow. com/questions/22839295/, который я нашел сейчас, но ответа нет. Спасибо, Шреник   -  person Shrenik Jhaveri    schedule 09.07.2014


Ответы (1)


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

Сценарий: 1. Веб-ферма: Хост, внешний пользователь, обращенный к веб-страницам. 2. Бэкенд-процесс: сочетание WebApi, SharePoint, службы Windows и т. д.

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

Существует пул служб Windows, отслеживающих сообщение на служебной шине с помощью SubscriptionClient и обрабатывающих это сообщение. По завершению процесс может длиться от 5 секунд до 30 секунд, а в некоторых случаях и больше. Нам нужно сообщить клиенту, что его работа выполнена, если он ожидает на веб-странице или ждет уведомления о завершении.

В этой истории мы используем SignalR для отправки клиенту уведомления о завершении задания.

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

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

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

В приведенном выше подходе у нас есть одно ограничение, связанное с тем, как служба Windows подключается к веб-клиенту, поскольку у нас нет аутентификации Windows, но у нас есть аутентификация на основе openid с ADFS. Теперь в таком случае веб-приложению требуется специальный код, в котором предоставляется отдельный идентификатор пользователя или пароль для службы Windows для связи или аутентификация Windows также разрешена для этого концентратора для служебной учетной записи службы Windows.

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

Так я сделал ниже с простотой, хотя мне понадобилась целая ночь, чтобы найти нашу внутреннюю часть SignalR. Но это работает:

Подход заключается в отправке сообщения непосредственно на объединительную плату ServiceBus, и, поскольку все веб-серверы уже подключены к объединительной плате ServiceBus, они получат сообщение.

К сожалению, SignalR не предоставляет такого механизма для отправки сообщения непосредственно на объединительную плату. Я думаю, что это модель pub/sub, поэтому они не хотят, чтобы кто-то взломал их систему :). или нарушение их шаблона, но в моем случае это имеет смысл из-за разных ролей и безопасности, я упростил код, как показано ниже:

  1. Создайте экземпляр ServiceBusMessageBus в моем коде так же, как показано ниже: хотя я создал отдельный экземпляр и храню его до конца жизни службы Windows, поэтому я не создаю экземпляр каждый раз:

ServiceBusMessageBus serviceBusBackplane = new ServiceBusMessageBus (новый DefaultDependencyResolver(), new ServiceBusScaleoutConfiguration (connectionString, appName));

  1. Создайте объект ClientHubInvocation: это сообщение, которое фактически создается в инфраструктуре SignalR при широковещательном сообщении на основе объединительной платы:

                    ClientHubInvocation hubData = new ClientHubInvocation
                    {
                        Args = new object[] { msg },
                        Hub = "JobStatusHub",
                        Method = "onJobStatus",
                        State = null,
                    };
    
  2. Создайте объект Message, который принимает ServiceBusMessageBus.Publish. Да, так что это метод, который фактически вызывается в базовом классе ScaleoutMessageBus.Publish. Этот класс фактически отвечает за отправку сообщения в тему и другим подписчикам на других узлах сервера. Почему бы не использовать это напрямую. Теперь, чтобы создать объект сообщения, вам понадобится следующий код:

Сообщение backplaneMessage = новое сообщение (sourceId, "hg-JobStatusHub." + имя, новый ArraySegment (Encoding.UTF8.GetBytes (JsonConvert.SerializeObject (hubData)))));

В приведенном выше втором параметре есть что-то интересное. В случае, если вы хотите опубликовать для всех клиентов, тогда синтаксис «h-», в моем случае для конкретного пользователя группы, поэтому синтаксис «hg-.. Вы можете проверить код здесь: https://github.com/SignalR/SignalR/blob/bc9412bcab0f5ef097c7dc919e3ea1b37fc8718c/src/Microsoft.AspNet.SignalR.Core/Infrastructure/PrefixHelper.cs

  1. Опубликуйте свое сообщение непосредственно на объединительной плате, как показано ниже:

await serviceBusBackplane.Publish(backplaneMessage);

Я бы хотел, чтобы этот класс PrefixHelper был общедоступным.

Помните: это не рекомендуется и не изолирует от будущих обновлений для SignalR, так как они могут измениться внутри, поэтому любое обновление может сопровождаться небольшим затруднением для изменения этого кода. Но в целом это работает. Команда Hope SignalR предоставляет некоторый готовый механизм для отправки сообщения непосредственно на объединительную плату.

Спасибо

person Shrenik Jhaveri    schedule 09.07.2014