| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Dispatcher
- {
- using System;
- using System.Runtime;
- using System.ServiceModel;
- using System.ServiceModel.Diagnostics;
- using System.ServiceModel.Diagnostics.Application;
- interface ISessionThrottleNotification
- {
- void ThrottleAcquired();
- }
- public sealed class ServiceThrottle
- {
- internal const int DefaultMaxConcurrentCalls = 16;
- internal const int DefaultMaxConcurrentSessions = 100;
- internal static int DefaultMaxConcurrentCallsCpuCount = DefaultMaxConcurrentCalls * OSEnvironmentHelper.ProcessorCount;
- internal static int DefaultMaxConcurrentSessionsCpuCount = DefaultMaxConcurrentSessions * OSEnvironmentHelper.ProcessorCount;
- FlowThrottle calls;
- FlowThrottle sessions;
- QuotaThrottle dynamic;
- FlowThrottle instanceContexts;
- ServiceHostBase host;
- ServicePerformanceCountersBase servicePerformanceCounters;
- bool isActive;
- object thisLock = new object();
- internal ServiceThrottle(ServiceHostBase host)
- {
- if (!((host != null)))
- {
- Fx.Assert("ServiceThrottle.ServiceThrottle: (host != null)");
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("host");
- }
- this.host = host;
- this.MaxConcurrentCalls = ServiceThrottle.DefaultMaxConcurrentCallsCpuCount;
- this.MaxConcurrentSessions = ServiceThrottle.DefaultMaxConcurrentSessionsCpuCount;
- this.isActive = true;
- }
- FlowThrottle Calls
- {
- get
- {
- lock (this.ThisLock)
- {
- if (this.calls == null)
- {
- this.calls = new FlowThrottle(this.GotCall, ServiceThrottle.DefaultMaxConcurrentCallsCpuCount,
- ServiceThrottle.MaxConcurrentCallsPropertyName, ServiceThrottle.MaxConcurrentCallsConfigName);
- this.calls.SetRatio(this.RatioCallsToken);
- }
- return this.calls;
- }
- }
- }
- FlowThrottle Sessions
- {
- get
- {
- lock (this.ThisLock)
- {
- if (this.sessions == null)
- {
- this.sessions = new FlowThrottle(this.GotSession, ServiceThrottle.DefaultMaxConcurrentSessionsCpuCount,
- ServiceThrottle.MaxConcurrentSessionsPropertyName, ServiceThrottle.MaxConcurrentSessionsConfigName);
- this.sessions.SetRatio(this.RatioSessionsToken);
- }
- return this.sessions;
- }
- }
- }
- QuotaThrottle Dynamic
- {
- get
- {
- lock (this.ThisLock)
- {
- if (this.dynamic == null)
- {
- this.dynamic = new QuotaThrottle(this.GotDynamic, new object());
- this.dynamic.Owner = "ServiceHost";
- }
- this.UpdateIsActive();
- return this.dynamic;
- }
- }
- }
- internal int ManualFlowControlLimit
- {
- get { return this.Dynamic.Limit; }
- set { this.Dynamic.SetLimit(value); }
- }
- const string MaxConcurrentCallsPropertyName = "MaxConcurrentCalls";
- const string MaxConcurrentCallsConfigName = "maxConcurrentCalls";
- public int MaxConcurrentCalls
- {
- get { return this.Calls.Capacity; }
- set
- {
- this.ThrowIfClosedOrOpened(MaxConcurrentCallsPropertyName);
- this.Calls.Capacity = value;
- this.UpdateIsActive();
- if (null != this.servicePerformanceCounters)
- {
- this.servicePerformanceCounters.SetThrottleBase((int)ServicePerformanceCounters.PerfCounters.CallsPercentMaxCallsBase, this.Calls.Capacity);
- }
- }
- }
- const string MaxConcurrentSessionsPropertyName = "MaxConcurrentSessions";
- const string MaxConcurrentSessionsConfigName = "maxConcurrentSessions";
- public int MaxConcurrentSessions
- {
- get { return this.Sessions.Capacity; }
- set
- {
- this.ThrowIfClosedOrOpened(MaxConcurrentSessionsPropertyName);
- this.Sessions.Capacity = value;
- this.UpdateIsActive();
- if (null != this.servicePerformanceCounters)
- {
- this.servicePerformanceCounters.SetThrottleBase((int)ServicePerformanceCounters.PerfCounters.SessionsPercentMaxSessionsBase, this.Sessions.Capacity);
- }
- }
- }
- const string MaxConcurrentInstancesPropertyName = "MaxConcurrentInstances";
- const string MaxConcurrentInstancesConfigName = "maxConcurrentInstances";
- public int MaxConcurrentInstances
- {
- get { return this.InstanceContexts.Capacity; }
- set
- {
- this.ThrowIfClosedOrOpened(MaxConcurrentInstancesPropertyName);
- this.InstanceContexts.Capacity = value;
- this.UpdateIsActive();
- if (null != this.servicePerformanceCounters)
- {
- this.servicePerformanceCounters.SetThrottleBase((int)ServicePerformanceCounters.PerfCounters.InstancesPercentMaxInstancesBase, this.InstanceContexts.Capacity);
- }
- }
- }
- FlowThrottle InstanceContexts
- {
- get
- {
- lock (this.ThisLock)
- {
- if (this.instanceContexts == null)
- {
- this.instanceContexts = new FlowThrottle(this.GotInstanceContext, Int32.MaxValue,
- ServiceThrottle.MaxConcurrentInstancesPropertyName, ServiceThrottle.MaxConcurrentInstancesConfigName);
- this.instanceContexts.SetRatio(this.RatioInstancesToken);
- if (this.servicePerformanceCounters != null)
- {
- InitializeInstancePerfCounterSettings();
- }
- }
- return this.instanceContexts;
- }
- }
- }
- internal bool IsActive
- {
- get { return this.isActive; }
- }
- internal object ThisLock
- {
- get { return this.thisLock; }
- }
- internal void SetServicePerformanceCounters(ServicePerformanceCountersBase counters)
- {
- this.servicePerformanceCounters = counters;
- //instance throttle is created through the behavior, set the perf counter callbacks if initialized
- if (this.instanceContexts != null)
- {
- InitializeInstancePerfCounterSettings();
- }
- //this.calls and this.sessions throttles are created by the constructor. Set the perf counter callbacks
- InitializeCallsPerfCounterSettings();
- InitializeSessionsPerfCounterSettings();
- }
- void InitializeInstancePerfCounterSettings()
- {
- Fx.Assert(this.instanceContexts != null, "Expect instanceContext to be initialized");
- Fx.Assert(this.servicePerformanceCounters != null, "expect servicePerformanceCounters to be set");
- this.instanceContexts.SetAcquired(this.AcquiredInstancesToken);
- this.instanceContexts.SetReleased(this.ReleasedInstancesToken);
- this.instanceContexts.SetRatio(this.RatioInstancesToken);
- this.servicePerformanceCounters.SetThrottleBase((int)ServicePerformanceCounters.PerfCounters.InstancesPercentMaxInstancesBase, this.instanceContexts.Capacity);
- }
- void InitializeCallsPerfCounterSettings()
- {
- Fx.Assert(this.calls != null, "Expect calls to be initialized");
- Fx.Assert(this.servicePerformanceCounters != null, "expect servicePerformanceCounters to be set");
- this.calls.SetAcquired(this.AcquiredCallsToken);
- this.calls.SetReleased(this.ReleasedCallsToken);
- this.calls.SetRatio(this.RatioCallsToken);
- this.servicePerformanceCounters.SetThrottleBase((int)ServicePerformanceCounters.PerfCounters.CallsPercentMaxCallsBase, this.calls.Capacity);
- }
- void InitializeSessionsPerfCounterSettings()
- {
- Fx.Assert(this.sessions != null, "Expect sessions to be initialized");
- Fx.Assert(this.servicePerformanceCounters != null, "expect servicePerformanceCounters to be set");
- this.sessions.SetAcquired(this.AcquiredSessionsToken);
- this.sessions.SetReleased(this.ReleasedSessionsToken);
- this.sessions.SetRatio(this.RatioSessionsToken);
- this.servicePerformanceCounters.SetThrottleBase((int)ServicePerformanceCounters.PerfCounters.SessionsPercentMaxSessionsBase, this.sessions.Capacity);
- }
- bool PrivateAcquireCall(ChannelHandler channel)
- {
- return (this.calls == null) || this.calls.Acquire(channel);
- }
- bool PrivateAcquireSessionListenerHandler(ListenerHandler listener)
- {
- if ((this.sessions != null) && (listener.Channel != null) && (listener.Channel.Throttle == null))
- {
- listener.Channel.Throttle = this;
- return this.sessions.Acquire(listener);
- }
- else
- {
- return true;
- }
- }
- bool PrivateAcquireSession(ISessionThrottleNotification source)
- {
- return (this.sessions == null || this.sessions.Acquire(source));
- }
- bool PrivateAcquireDynamic(ChannelHandler channel)
- {
- return (this.dynamic == null) || this.dynamic.Acquire(channel);
- }
- bool PrivateAcquireInstanceContext(ChannelHandler channel)
- {
- if ((this.instanceContexts != null) && (channel.InstanceContext == null))
- {
- channel.InstanceContextServiceThrottle = this;
- return this.instanceContexts.Acquire(channel);
- }
- else
- {
- return true;
- }
- }
- internal bool AcquireCall(ChannelHandler channel)
- {
- lock (this.ThisLock)
- {
- return (this.PrivateAcquireCall(channel));
- }
- }
- internal bool AcquireInstanceContextAndDynamic(ChannelHandler channel, bool acquireInstanceContextThrottle)
- {
- lock (this.ThisLock)
- {
- if (!acquireInstanceContextThrottle)
- {
- return this.PrivateAcquireDynamic(channel);
- }
- else
- {
- return (this.PrivateAcquireInstanceContext(channel) &&
- this.PrivateAcquireDynamic(channel));
- }
- }
- }
- internal bool AcquireSession(ISessionThrottleNotification source)
- {
- lock (this.ThisLock)
- {
- return this.PrivateAcquireSession(source);
- }
- }
- internal bool AcquireSession(ListenerHandler listener)
- {
- lock (this.ThisLock)
- {
- return this.PrivateAcquireSessionListenerHandler(listener);
- }
- }
- void GotCall(object state)
- {
- ChannelHandler channel = (ChannelHandler)state;
- lock (this.ThisLock)
- {
- channel.ThrottleAcquiredForCall();
- }
- }
- void GotDynamic(object state)
- {
- ((ChannelHandler)state).ThrottleAcquired();
- }
- void GotInstanceContext(object state)
- {
- ChannelHandler channel = (ChannelHandler)state;
- lock (this.ThisLock)
- {
- if (this.PrivateAcquireDynamic(channel))
- channel.ThrottleAcquired();
- }
- }
- void GotSession(object state)
- {
- ((ISessionThrottleNotification)state).ThrottleAcquired();
- }
- internal void DeactivateChannel()
- {
- if (this.isActive)
- {
- if (this.sessions != null)
- this.sessions.Release();
- }
- }
- internal void DeactivateCall()
- {
- if (this.isActive)
- {
- if (this.calls != null)
- this.calls.Release();
- }
- }
- internal void DeactivateInstanceContext()
- {
- if (this.isActive)
- {
- if (this.instanceContexts != null)
- {
- this.instanceContexts.Release();
- }
- }
- }
- internal int IncrementManualFlowControlLimit(int incrementBy)
- {
- return this.Dynamic.IncrementLimit(incrementBy);
- }
- void ThrowIfClosedOrOpened(string memberName)
- {
- if (this.host.State == CommunicationState.Opened)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxImmutableThrottle1, memberName)));
- }
- else
- {
- this.host.ThrowIfClosedOrOpened();
- }
- }
- void UpdateIsActive()
- {
- this.isActive = ((this.dynamic != null) ||
- ((this.calls != null) && (this.calls.Capacity != Int32.MaxValue)) ||
- ((this.sessions != null) && (this.sessions.Capacity != Int32.MaxValue)) ||
- ((this.instanceContexts != null) && (this.instanceContexts.Capacity != Int32.MaxValue)));
- }
- internal void AcquiredCallsToken()
- {
- this.servicePerformanceCounters.IncrementThrottlePercent((int)ServicePerformanceCounters.PerfCounters.CallsPercentMaxCalls);
- }
- internal void ReleasedCallsToken()
- {
- this.servicePerformanceCounters.DecrementThrottlePercent((int)ServicePerformanceCounters.PerfCounters.CallsPercentMaxCalls);
- }
- internal void RatioCallsToken(int count)
- {
- if (TD.ConcurrentCallsRatioIsEnabled())
- {
- TD.ConcurrentCallsRatio(count, this.MaxConcurrentCalls);
- }
- }
- internal void AcquiredInstancesToken()
- {
- this.servicePerformanceCounters.IncrementThrottlePercent((int)ServicePerformanceCounters.PerfCounters.InstancesPercentMaxInstances);
- }
- internal void ReleasedInstancesToken()
- {
- this.servicePerformanceCounters.DecrementThrottlePercent((int)ServicePerformanceCounters.PerfCounters.InstancesPercentMaxInstances);
- }
- internal void RatioInstancesToken(int count)
- {
- if (TD.ConcurrentInstancesRatioIsEnabled())
- {
- TD.ConcurrentInstancesRatio(count, this.MaxConcurrentInstances);
- }
- }
- internal void AcquiredSessionsToken()
- {
- this.servicePerformanceCounters.IncrementThrottlePercent((int)ServicePerformanceCounters.PerfCounters.SessionsPercentMaxSessions);
- }
- internal void ReleasedSessionsToken()
- {
- this.servicePerformanceCounters.DecrementThrottlePercent((int)ServicePerformanceCounters.PerfCounters.SessionsPercentMaxSessions);
- }
- internal void RatioSessionsToken(int count)
- {
- if (TD.ConcurrentSessionsRatioIsEnabled())
- {
- TD.ConcurrentSessionsRatio(count, this.MaxConcurrentSessions);
- }
- }
- }
- }
|