Время жизни экземпляра службы WCF?

в процессе создания службы WCF я столкнулся с новым для меня термином. В основном при указании InstanceContextMode У меня есть несколько вариантов, в том числе:PerSession, PerCall и Single. Вот код из образца, который я изучаю:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class EvalService : IEvalService { ...

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

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

4 ответов


по документам:

только один объект InstanceContext используется для всех входящих вызовов и не утилизируется после звонков. Если объект службы не существует, он будет создан.

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

отвечая на ваш вопрос - Да, это так завод.

обновление добавлен образец: Я изменил несколько образцов из MSDN, чтобы показать эффекты InstanceContextMode.Single. Вы увидите, что количество операций будет продолжать увеличиваться, даже если я использую двух разных клиентов. Если я изменю InstanceContextMode to PerCall, счетчик будет отличаться (он будет равен нулю).

self-hosted service:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class CalculatorService : ICalculatorInstance
{
    static Object syncObject = new object();
    static int instanceCount;
    int instanceId;
    int operationCount;

    public CalculatorService()
    {
        lock (syncObject)
        {
            instanceCount++;
            instanceId = instanceCount;
        }
    }

    public double Add(double n1, double n2)
    {
        operationCount++;
        return n1 + n2;
    }

    public double Subtract(double n1, double n2)
    {
        Interlocked.Increment(ref operationCount);
        return n1 - n2;
    }

    public double Multiply(double n1, double n2)
    {
        Interlocked.Increment(ref operationCount);
        return n1 * n2;
    }

    public double Divide(double n1, double n2)
    {
        Interlocked.Increment(ref operationCount);
        return n1 / n2;
    }

    public string GetInstanceContextMode()
    {   // Return the InstanceContextMode of the service
        ServiceHost host = (ServiceHost)OperationContext.Current.Host;
        ServiceBehaviorAttribute behavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
        return behavior.InstanceContextMode.ToString();
    }

    public int GetInstanceId()
    {   // Return the id for this instance
        return instanceId;
    }

    public int GetOperationCount()
    {   // Return the number of ICalculator operations performed 
        // on this instance
        lock (syncObject)
        {
            return operationCount;
        }
    }
}

public class Program
{

    static void Main(string[] args)
    {
        Uri baseAddress = new Uri("http://localhost:12345/calc");
        using (ServiceHost host = new ServiceHost(typeof(CalculatorService), baseAddress))
        {
            // Enable metadata publishing.
            ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
            smb.HttpGetEnabled = true;
            smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
            host.Description.Behaviors.Add(smb);

            // Open the ServiceHost to start listening for messages. Since
            // no endpoints are explicitly configured, the runtime will create
            // one endpoint per base address for each service contract implemented
            // by the service.
            host.Open();

            Console.WriteLine("The service is ready at {0}", baseAddress);
            Console.WriteLine("Press <Enter> to stop the service.");
            Console.ReadLine();

            // Close the ServiceHost.
            host.Close();
        }
        Console.WriteLine();
        Console.WriteLine("Press <ENTER> to terminate client.");
        Console.ReadLine();
    }
}

клиент:

class Program
{
    static void Main()
    {
        // Create a client.
        CalculatorInstanceClient client = new CalculatorInstanceClient();
        string instanceMode = client.GetInstanceContextMode();
        Console.WriteLine("InstanceContextMode: {0}", instanceMode);
        Console.WriteLine("client1's turn");
        Console.WriteLine("2 + 2 = {0}", client.Add(2, 2).ToString());
        Console.WriteLine("3 - 1 = {0}", client.Subtract(3, 1).ToString());
        Console.WriteLine("number of operations = {0}", client.GetOperationCount().ToString());

        // Create a second client.
        CalculatorInstanceClient client2 = new CalculatorInstanceClient();

        Console.WriteLine("client2's turn");
        Console.WriteLine("2 + 2 = {0}", client2.Add(2, 2).ToString());
        Console.WriteLine("3 - 1 = {0}", client2.Subtract(3, 1).ToString());
        Console.WriteLine("number of operations = {0}", client2.GetOperationCount().ToString());

        Console.WriteLine();
        Console.WriteLine("Press <ENTER> to terminate client.");
        Console.ReadLine();
    }
}

InstanceContextMode.Single соответствует одноэлементной службе, т. е. сторона сервера экземпляра службы одинакова для всех входящих запросов.

несколько комментариев:

  • служба может быть прекращена хостом, даже если он является одноэлементным, это, вероятно, так, если ваша служба размещена в iis
  • это контекст экземпляра, который является одноэлементным, который может быть отделен от фактических экземпляров службы (но давайте сохраним его простым для сейчас...)
  • если исключение не поймано должным образом в одноэлементной службе, это может предотвратить любой последующий запрос на успех

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

хотя это, вероятно, будет деталь реализации, я сомневаюсь, что ваш класс persistet (он должен быть сериализуемым для этого, что не является требованием). Один экземпляр просто существует до тех пор, пока он необходим (т. е. связанный ServiceHost открыт).


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

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