2016-09-15 5 views
1

Мы находимся в процессе реорганизации всех или большой части наших методов контроллера .NET 4.6 MVC WebAPI для методов async.Реализация Awaitable Async метода для NCache Get

Похоже, что это будет хорошо работать для методов, которые имеют более низкий уровень вызова метода, который является ожидаемым, например выполнение команды SQL; однако мы используем распределенную структуру кэширования в памяти от Alachisoft под названием NCache (4.6 SP2, если быть точным), которая не предлагает никаких асинхронных методов.

Было бы целесообразно создать вспомогательный метод async, который мог бы вызывать ожидаемый Task<object> тип возврата?

Традиционно с использованием API NCache вы используете Get объект из кеша Key в следующем пользовании;

NCacheObject.Get(string); 

Предложение заключается в создании вспомогательного метода следующего:

protected static async Task<Object> GetAsync(string key, Cache nCache) 
{ 
    Task<Object> getTask = new Task<Object>(() => nCache.Get(key)); 
    getTask.Start(); 
    return await getTask.ConfigureAwait(false); 
} 

Так что это позволит затем полный водопад async методов до метода входа контроллера как такового;

public static async Task<Tuple<List<SomeModel>, bool, string>> GetSomeModelList(string apiKey) 
{ 
    return newTuple<List<SomeModel>, bool, string>(await GetAsync("GetSomeModelKey", CacheInstance).ConfigureAwait(false), true, "Success message"); 
} 

И, наконец, метод контроллера;

[HttpGet, Route("Route/Method")] 
public async Task<ResponseOutputModel<List<SomeModel>>> GetSomeModelList() 
{ 
    ResponseOutputModel<List<SomeModel>> resp = new ResponseOutputModel<List<SomeModel>>(); 

    try 
    { 
     Tuple<List<SomeModel>, Boolean, String> asyncResp = await CacheProcessing.GetSomeModelList(GetApiKey()).ConfigureAwait(false); 

     resp.Response = asyncResp.Item1; 
     resp.Success = asyncResp.Item2; 
     resp.Message = asyncResp.Item3; 
    } 
    catch (Exception ex) 
    { 
     LoggingHelper.Write(ex); 
     resp.StatusCode = Enumerations.ApiResponseStatusCodes.ProcessingError; 
     resp.Success = false; 
     resp.Message = ex.Message; 
    } 

    return resp; 
} 

Это усложнит рефакторинга, как оригинальные методы фактически имели выходные параметры для bool success и string message; но, похоже, это можно выполнить прилично и быстро, используя Tuple<>; иначе мы могли бы просто создать модель типа возврата.

Чтобы сделать это правильно, было бы много методов для рефакторинга; вполне обязательство.

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

ответ

4

было бы целесообразен созданием вспомогательного метода асинхронного, который подвергнет awaitable возвращаемого типа задачи?

Nope.

Предложение создать вспомогательный метод следующего

Это просто в очередь в памяти работы в пул потоков.

(Примечание стороны:.. Конструктор задача никогда не следует использовать Ever Если вам нужно стоять в очереди работать в пул потоков, используйте Task.Run вместо конструктора задачи с Start)

ли эта работа, как и ожидалось , и быть лучшим решением для достижения цели?

Возможно ли, что это стоит всех усилий, с конечной целью увеличения масштабируемости и последующей «производительности» веб-серверов?

Это тот же вопрос. Целью является масштабируемость; асинхронность - это всего лишь одно средство, чтобы помочь вам в этом.

Asynchrony обеспечивает масштабируемость на ASP.NET, поскольку он освобождает поток, который может обрабатывать другие запросы. Однако, если вы создаете методы, которые являются асинхронными , используя другой поток, то это не поможет вам вообще. Я называю эту «фальшивую асинхронность» - эти методы выглядят асинхронными, но они действительно просто синхронно работают в пуле потоков.

В отличие от истинной асинхронности, фальшивая асинхронность на самом деле повредит вашей масштабируемости.

+0

Интересно. Я надеялся, что вы увидите это и прокомментируете; Раньше я читал ваши сообщения в блоге. Таким образом, проблема, которую я видел до сих пор, заключается в том, что метод «Get» для NCache несет существенное время ожидания, поскольку он ожидает задержки сетевого трафика и обработки запроса с самого сервера. После дальнейших обзоров, кажется, единственные реальные элементы, которые я мог бы асинхронно/ждут, - это вызовы DB для ExecuteNonQueryAsync; методы, которые заполняют и возвращают таблицы данных, как представляется, тоже не ожидаются. – Sivart

+0

@Sivart: Нет, (очень старые) API-интерфейсы таблиц данных не будут хорошо работать с async, даже если MS попыталась их написать. Новые EF более дружелюбны к асинхронным. Лучше всего, чтобы NCache поднял проблему со своими разработчиками. –

1

Поскольку это кеш памяти, и я говорю об этом из любого прямого опыта с NCache, но опыт с другими системами кеширования.

  1. Да, это будет работать, конечно. Я предпочел бы выбрать структуру ответа или общий класс, который позволит мне определить свой тип ответа (если это вообще возможно). Кортежи не плохие, вероятно, были бы более результативными, если бы вы выбрали классы. Но они не легки на глазах.
  2. Теперь, когда дело доходит до производительности, есть один вопрос. Вот вам сервер кеш-памяти, и вы хотите, чтобы вы быстро читали-записывали. Доступ к memcache должен быть простым. Поскольку вы прямо обращаетесь к памяти здесь, с точки зрения производительности, это не даст вам многого. Вы уверены, что ваш код полностью асинхронный, и вы правильно используете threadpool, чтобы все было в порядке? Да, конечно, но все, что он когда-либо сделал, это добавить дополнительный слой или работать, когда вы обращаетесь к кешу.
  3. И как только вы собираетесь использовать асинхронный режим, убедитесь, что ваш кеш памяти является потокобезопасным.:)