Различные формы интерфейса контракта службы WCF

Похоже, я могу свободно переключаться между следующими тремя разными версиями одного и того же API интерфейса контракта WCF, не нарушая работу клиентов:

[ServiceContract]
interface IService
{
    // Either synchronous
    // [OperationContract]
    // int SomeMethod(int arg);

    // Or TAP
    [OperationContract]
    Task<int> SomeMethodAsync(int arg);

    // Or APM
    // [OperationContract(AsyncPattern = true)]
    // IAsyncResult BeginSomeMethod(int arg, AsyncCallback callback, object state);
    // int EndSomeMethod(IAsyncResult ar);
}

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

Мои вопросы:

  • Могу ли я полагаться на это законное поведение? Это где-нибудь задокументировано?

Идея состоит в том, чтобы преобразовать набор синхронных методов в стиле SomeMethod в методы в стиле TAP SomeMethodAsync, чтобы использовать async/await в их реализации и, таким образом, улучшить масштабируемость службы WCF, не нарушая работу существующих клиентов.

Кроме того, известны проблемы с масштабированием службы WCF в .NET 3.5 и .NET 4.0. Они описаны в статье MSKB «Служба WCF может медленно масштабироваться под нагрузкой» и статье CodeProject " Настройка WCF для создания высокомасштабируемого асинхронного REST API ». По сути, было недостаточно реализовать API контрактов службы как естественно асинхронные, среда выполнения WCF все еще блокировала поток запроса.

  • Кто-нибудь знает, была ли эта проблема решена для .NET 4.5.x "из коробки"? Или еще требуются дополнительные настройки?

person noseratio    schedule 25.03.2014    source источник
comment
То же самое можно сделать с ASP.NET Web API 2. Вы можете использовать либо int SomeMethod(int arg), либо async Task<int> SomeMethodAsync(int arg), и оба будут идентичны пользователю. Оба будут синхронными на стороне клиента.   -  person Timothy Shields    schedule 26.03.2014
comment
@TimothyShields, верно, кроме веб-API, нет концепции метаданных для генерации клиентского прокси, AFAIK.   -  person noseratio    schedule 26.03.2014
comment
Чтобы ответить на ваш последний вопрос, некоторые из настроек были добавлены в 4.5.0, см. Раздел «Новые значения транспорта по умолчанию» в статье MSDN Что нового в Windows Communication Foundation 4.5   -  person Scott Chamberlain    schedule 26.03.2014
comment
Связывание этого и этого как связанные.   -  person noseratio    schedule 25.06.2014


Ответы (1)


Операции WCF могут быть определены с использованием синхронного, EAP или (начиная с .NET 4.5) TAP. Из MSDN:

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

Фактически вы можете иметь все 3 шаблона в одном интерфейсе контракта, и все они будут относиться к одному и тому же сообщению.

В сети нет никакой разницы, как вы выполняете операции. WSDL (который WCF строит из ABC каждой конечной точки - адреса, привязки и контракта) не содержит этой информации. Он создается на основе описания операций.

Если вы посмотрите на класс OperationDescription, который используется в ContractDescription, вы увидите, что каждая операция имеет следующие свойства: SyncMethod, BeginMethod, EndMethod и TaskMethod. При создании описания WCF объединит все методы в соответствии с именем операции в одну операцию. Если есть какое-то несоответствие между операциями с одним и тем же именем в разных шаблонах (например, с разными параметрами), WCF выдаст исключение с подробным описанием того, что именно не так. WCF автоматически предполагает (необязательно) суффикс «Async» для методов на основе задач и префикс «Начало / конец» для APM.

В этом смысле клиентская и серверная стороны совершенно не связаны. Утилита, которая генерирует прокси-классы из WSDL (svcutil), может создавать прокси для любого шаблона выполнения. Это даже не обязательно должна быть служба WCF.

На стороне сервера, если реализовано более одного шаблона, WCF будет использовать только один в следующем порядке приоритета: задача, синхронизация и APM. Это задокументировано где-то в MSDN, я просто не могу найти его прямо сейчас. Но вы можете посмотреть справочный источник здесь.

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

По поводу масштабирования (должен быть другой вопрос, ИМО)

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

Лучше всего в таких ситуациях проводить МНОГО сравнительного анализа.

person Eli Arbel    schedule 08.04.2014
comment
Отличный ответ, спасибо. У меня есть вопрос только о . На самом деле вы можете иметь все 3 шаблона в одном интерфейсе контракта, и все они будут относиться к одному и тому же сообщению. Очевидно, если я откажусь от комментариев ко всем трем версиям и сохраню [OperationContract] для каждой, не запутает ли это среда выполнения WCF? Я понимаю, что метаданные будут иметь только один API сообщений, но мне придется реализовать все три варианта в моем классе Service. Какой из них будет отображаться для обработки фактического сообщения? - person noseratio; 08.04.2014
comment
На стороне клиента - можно использовать любой из реализованных шаблонов. Даже svcutil обычно генерирует как синхронизирующие, так и асинхронные методы. На стороне сервера вам придется реализовать весь интерфейс, но WCF будет использовать только один метод для каждой операции в указанном выше порядке приоритета (сначала задачи, затем синхронизация, затем APM). Вы можете либо создать исключение в методах, которые не хотите реализовывать, либо использовать разные контракты для клиента и сервера. Пуристы SOA в любом случае сказали бы, что это правильный путь (клиенты сгенерированы из WSDL). - person Eli Arbel; 08.04.2014
comment
Вы можете попробовать сами. Вызовите ContractDescription.GetContract в своем интерфейсе и проверьте свойство Operations. - person Eli Arbel; 08.04.2014