Лучшая практика для срока службы прокси WCF - или как часто закрывать прокси WCF?

Я работал над приложением WPF, которое использует WCF для доступа к логике и базе данных на стороне сервера.

I начался с одного прокси-объекта клиента WCF, который я неоднократно использовал для вызова методов на сервере. После некоторого использования прокси сервер в конечном итоге выдаст исключение: System.ServiceModel.EndpointNotFoundException: не было конечной точки, прослушивающей http: //.../Service/BillingService.svc, которая могла бы принять сообщение. Часто это вызвано неправильным адресом или действием SOAP. См. InnerException, если есть, для получения дополнительных сведений. ---> System.Net.WebException: невозможно подключиться к удаленному серверу ---> System.Net.Sockets.SocketException: операция с сокетом не может быть выполнена из-за недостатка места в буфере или из-за очереди full .

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

После небольшого поиска я определил, что мне нужно периодически закрывать () прокси. Образцы, которые я нашел, вырожденно малы. Этот дал несколько полезных советов, но не ответил на вопрос. Я также встречал рекомендации , чтобы избежать использования шаблона using () (и вместо этого применить try / catch / finally), потому что метод Dispose прокси-сервера может вызвать исключение (фу).

Похоже, рекомендуется шаблон формируется следующим образом:

[TestClass]
public class WCFClientUnitTest
{
    BillingServiceClient _service;

    [TestMethod]
    public void TestGetAddressModel()
    {
        List customers = null;

        try
        {
            _service = new BillingServiceClient();
            customers = _service.GetCustomers().ToList();
        }
        catch
        {
            _service.Abort();
            _service = null;
            throw;
        }
        finally
        {
            if ((_service != null) &&
                (_service.State == System.ServiceModel.CommunicationState.Opened))
                _service.Close();
            _service = null;
        }

        if (customers != null)
            foreach (CustomerModel customer in customers)
            {
                try
                {
                    _service = new BillingServiceClient();
                    AddressModel address = (AddressModel)_service.GetAddressModel(customer.CustomerID);

                    Assert.IsNotNull(address, "GetAddressModel returned null");
                }
                catch
                {
                    _service.Abort();
                    _service = null;
                    throw;
                }
                finally
                {
                    if ((_service != null) &&
                        (_service.State == System.ServiceModel.CommunicationState.Opened))
                        _service.Close();
                        _service = null;
                }
            }
    }

Итак, мой вопрос все еще вращается вокруг того, как долго я должен поддерживать работу прокси-сервера клиента? Должен ли я открывать / закрывать его для каждого запроса на обслуживание? Мне это кажется чрезмерным. Разве у меня не будет значительного снижения производительности?

Что я действительно хочу сделать, так это создать и открыть канал и сделать краткую серию повторяющихся, коротких, последовательных сервисных вызовов по каналу. Затем аккуратно закройте канал.

В качестве примечания, пока я еще не реализовал это, Вскоре я добавлю в службу модель безопасности (как SSL, так и ACL), чтобы ограничить круг лиц, которые могут вызывать методы службы. В одном из ответов на этот пост упоминается, что повторное согласование контекста аутентификации и безопасности делает повторное открытие канала для каждого вызова службы бесполезным, но просто рекомендует избегать построения контекста безопасности.


РЕДАКТИРОВАТЬ 11/3/2010 : Это кажется важным, поэтому я добавляю его к вопросу ...

В ответ на комментарий / предложение Эндрю Шеперда я повторно выполнил свой модульный тест с выключением TrendMicro AntiVirus, одновременно отслеживая вывод из netstat -b. Netstat смог зафиксировать значительный рост открытых портов, принадлежащих WebDev.WebServer40.exe. Подавляющее большинство портов находились в состоянии TIME_WAIT. состояние TIME_WAIT на длительный период времени. Время указано в RFC793 как удвоенный максимальный сегмент Срок службы (MSL). MSL указан как 2 минуты. Итак, сокет может быть в Состояние TIME_WAIT до 4 минут. Некоторые системы реализуют разные значения (менее 2 минут) для MSL.

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

Следовательно, мне нужно выбрать один из двух путей: 1) попытаться выполнить пакетные вызовы служб, чтобы они повторно использовали сокет на стороне сервера 2) изменить мой контракт на обслуживание, чтобы я мог возвращать большие порции данных с меньшим количеством вызовов.

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

20
задан Community 23 May 2017 в 12:32
поделиться