As with a connected service, the ConcurrencyMode
property governs concurrent playback of queued messages. With a per-call service, all queued
messages are played at once to different instances as fast as they come off the queue, up to
the limit of the configured throttle. There is no need to configure for reentrancy to
support callbacks, because the operation contexts can never have callback references. There
is also no need to configure for multiple concurrent access, because no two messages will
ever share an instance. In short, with a queued per-call service, the concurrency mode is
ignored.
When it comes to a sessionful queued service, you are required to configure the service
with ConcurrencyMode.Single
. The reason is that it is the
only concurrency mode that allows you to turn off auto-completion, which is essential to
maintain the session semantic. The calls in the message are always played to the same
service instance, one at a time.
A queued singleton is really the only instancing mode that has any leeway with its
concurrency mode. If the singleton is configured with ConcurrencyMode.Single
, WCF will retrieve the messages all at once from the
queue (up to the thread pool and throttling limits) and then queue up the calls in the
internal queue the context lock maintains. Calls will be dispatched to the singleton one at
a time. If the singleton is configured with ConcurrencyMode.Multiple
, WCF will retrieve the messages all at once from the
queue (up to the thread pool and throttling limits) and play them concurrently to the
singleton. Obviously, in that case the singleton must provide for synchronized access to its
state. If the singleton is also transactional, it is prone to transactional deadlocks over
prolonged isolation maintained throughout each transaction.
Queued calls have a nasty side effect of excelling in turning a low level of load into a high level of stress. Imagine an offline queued service that sustained relatively low load, such as a call per minute for one day. Once the host is launched, WCF flushes the queued calls (all 1,440 of them) to the service all at once, subjecting it to high stress. The fact that there are over 1,000 messages in the queue does not mean that your design supports 1,000 concurrent instances and calls.
Throttling a queued service is your way of controlling the stress on the service and
avoiding turning load into stress. The important value to throttle is the number of
concurrent playbacks. This is an effective way of throttling the number of played
messages, because if the maximum number of concurrent calls is exceeded (overall stress),
the excess messages will stay in the queue. With a per-call service, the throttle controls
the overall number of allowed concurrent instances (and their implied resource
consumption). With a per-session service, the throttle controls the number of allowed
sessions. In the case of a queued singleton, you can combine a throttle value with
ConcurrencyMode.Multiple
to control just how many
concurrent players are allowed (stress) and how many messages to keep in the queue
(buffered load).
3.144.97.216