2010-08-09 3 views
4

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

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

+0

Правильно ли считать, что это чрезвычайно дорогостоящая операция, которая требует сложной системы координации перекрестных запросов? – RQDQ

+0

есть. запрос занимает несколько секунд и не может быть кэширован. – NickD

ответ

1

Я не уверен, что было бы «лучшим» для архитектуры WCF, но вы должны подумать о том, чтобы установить InstanceContextMode в Single, поскольку вы, вероятно, будете выполнять множество шагов синхронизации для того, что вы хотите сделать Вот.

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

private IDictionary<string, RequestToken> RequestTokens = 
    new Dictionary<string, RequestToken>(); 

public MyResponse MyMethod(MyRequest request) 
{ 
    // get the MD5 for the request 
    var md5 = GetMD5Hash(request); 

    // check if another thread is processing/has processed an identical request 
    RequestToken token; 
    if (RequestTokens.TryGetValue(md5, out token)) 
    { 
     // if the token exists already then wait till we can acquire the lock 
     // which indicates the processing has finished and a response is ready 
     // for us to reuse 
     lock (token.Sync) 
     { 
     return token.Response; 
     } 
    } 
    else 
    { 
     var token = new Token(md5); 
     lock (token.Sync) 
     { 
     RequestTokens.Add(md5, token); 

     // do processing here.. 
     var response = .... 

     token.Response = response; 

     return response; 
     } 
    } 
} 

private class RequestToken 
{ 
    private readonly object _sync = new object(); 

    public RequestToken(string md5) 
    { 
     MD5 = md5; 
    } 

    public string MD5 { get; private set; } 

    public object Sync { get { return _sync; } } 

    public MyResponse Response { get; set; } 
} 

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

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

+0

Это самый простой подход, который наверняка работает. Но это именно то, что я хотел предотвратить. Я ищу что-то высокоэффективное, способное обрабатывать 1000 или более запросов в секунду. – NickD

+0

Вам действительно нужно блокировать все последующие запросы с помощью той же контрольной суммы MD5, пока не будет выполнен первый запрос? Очевидно, что подобная синхронизация влияет на то, сколько параллелизма вы можете протащить через свой сервис. Кроме того, вам, скорее всего, придется масштабировать на нескольких машинах, чтобы иметь возможность обрабатывать 1000+ запросов в секунду, если ваши операции дороги. И делать то, что вы пытаетесь сделать через машины, - это еще один зверь! – theburningmonk

+0

Я не хочу блокировать машины. это неэффективно, я думаю. я знаю, что множественные вызовы (> 100) ударили меня одновременно из-за плохо спроектированной сторонней системы, которая вызывает мой сервис. – NickD

0

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

+0

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

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