Надежный n-уровневый WCF (проблема с потоками?) - PullRequest
2 голосов
/ 02 февраля 2010

Я работаю над приложением n-Tier, использующим WCF между слоями, так что:

Уровень 1: приложение Silverlight Вызывает поисковый запрос

        IClientBroker clientBroker = UIContext.CreateWcfInterface<IClientBroker>("Data/ClientBroker.svc");
        clientBroker.BeginSearchForClients(SearchTerm, 20, (result) =>
        {
            SearchResult[] results = ((IClientBroker)result.AsyncState).EndSearchForClients(result).ToArray();

            // do stuff, update UI, etc.

        }, clientBroker);

Уровень 2: веб-служба WCF, использующая basicHttp для вызова Silverlight. Это действует как прокси для 3-го уровня.

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
class ClientBroker : IClientBroker 
{
            [OperationContract] // as defined in IClientBroker
    public SearchResult[] SearchForClients(string keywords, int? maxResults)
    {
        ClientBrokerClient clientBroker = CreateClientBrokerClient();

        SearchResult[] searchResults=clientBroker.SearchForClients(keywords, maxResults);
        return searchResults;
    }
    }

Уровень 3: это «сервер», так как он предлагает конечную точку net.tcp (позволяющую защищенным клиентам подключаться без использования Silverlight). Это конечная цель запроса.

    public class ClientBroker : IClientBroker // note this is different to tier 2 interface
    {

        public SearchResult[] SearchForClients(string keywords, int? maxResults)
        {
                    // do stuff
            if (maxResults.HasValue)
            {
                return results.Take(maxResults.Value).ToArray();
            }
            else
            {
                return results.ToArray();
            }
        }
     }

Итак, мои звонки идут:

Silverlight -> httpBasic -> IIS-служба прокси WCF -> net.tcp -> EXE-служба WCF

Это хорошо работает. Я могу передавать заголовки через слои, поддерживать сессии и т. Д. И это довольно аккуратно.

НО это всего лишь несколько звонков, чтобы вызвать тайм-аут в сообщении.

Время, необходимое серверу-EXE для выполнения своей работы, ничтожно мало. Проблема, с которой я сталкиваюсь, заключается в том, что сервер «зависает» при возврате результатов на уровень 2.

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

Я оглянулся и увидел, что идеальный способ сделать это - заставить мой Tier 2 работать асинхронно, как показано в коде ниже:

    public SearchResult[] SearchForClients(string keywords, int? maxResults)
    {
        ClientBrokerClient clientBroker = CreateClientBrokerClient();
        clientBroker.BeginSearchForClients(keywords, maxResults, result =>
            {
                SearchResult[] searchResults=((ClientBrokerClient)result.AsyncState).EndSearchForClients(result);
                // how to return results from here?
            }, clientBroker);

    }

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

UPDATE:

С тех пор мой сервер (уровень 3) прошел путь от клиента, избегая уровня 2, делая много запросов от него. Кажется, что канал WCF net.tcp для Уровня 3 очень прочный.

ОБНОВЛЕНИЕ 2:

Этот пост в блоге описан с использованием шаблона IAsyncResult, к которому я здесь обратился. Я лаю не на том дереве? http://blogs.msdn.com/wenlong/archive/2009/02/09/scale-wcf-application-better-with-asynchronous-programming.aspx

ОБНОВЛЕНИЕ 3:

Хорошо, этот абзац из этого блога:

"Если вы строите N-ярусный WCF услуги, у вас будет сервис WCF операции вызова клиентских прокси WCF для других бэкэнд-сервисов. В этом случае, вы должны убедиться, что средний уровень (уровень маршрутизации) имеет асинхронная операция обслуживания вызов асинхронного прокси WCF операции. Таким образом, ваш средний уровень не закончится при обработке многих медленных операций. "

, кажется, подтверждает мои подозрения, что проблема заключается в среднем уровне (Уровень 2). Как я могу добиться этой асинхронности Begin / End? Нужно ли делать это вручную или я могу сохранить инструменты VS для генерации прокси-классов для меня? (ДЕЙСТВИТЕЛЬНО не хочу делать это вручную, контракты имеют некоторую степень изменчивости)

1 Ответ

0 голосов
/ 03 февраля 2010

Ну, я думаю, что решил это.Эта тема помогла мне:

Служба wcf останавливается после нескольких запросов

По сути, я не закрывал клиентские прокси на своем уровне 2, что, как я понимаю, может привести кблокировка.Эволюция кода была такой, что я закончил тем, что удалил блоки using () {}, чтобы облегчить исключения, которые не погасли с помощью прокси клиента.Тем не менее, я реструктурировал и перепроверил, и мой код уровня 2 теперь выглядит так:

    public SearchResult[] SearchForClients(string keywords, int? maxResults)
    {
        ClientBrokerClient clientBroker = CreateClientBrokerClient();

        SearchResult[] searchResults=clientBroker.SearchForClients(keywords, maxResults);
        clientBroker.Close();
        return searchResults;
    }

... и исключения не погашены.

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