現在、ワークフロー サービスでいくつかの問題が発生しています。短いシーケンスで 4、5 を開始すると正常に動作しますが、この値を増やすと (~10 から開始)、次の例外が発生します。
サーバーが開始したシャットダウンにより、出力セッションが自動的に閉じられたため、このチャネルを使用してメッセージを送信することはできなくなりました。DispatchRuntime.AutomaticInputSessionShutdown を false に設定して自動クローズを無効にするか、リモート サーバーでシャットダウン プロトコルを変更することを検討してください。
問題はプロキシの作成方法にあると思います。次のコードを使用してプロキシを提供し、既存のものを再利用しようとします。
public abstract class ProxyProvider<TService>
where TService : class
{
/// <summary>
/// Static reference to the current time provider.
/// </summary>
private static ProxyProvider<TService> current = DefaultProxyProvider.Instance;
private TService service;
/// <summary>
/// Gets or sets the current time provider.
/// </summary>
/// <value>
/// The current time provider.
/// </value>
public static ProxyProvider<TService> Current
{
get
{
return ProxyProvider<TService>.current;
}
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
ProxyProvider<TService>.current = value;
}
}
/// <summary>
/// Resets to default.
/// </summary>
public static void ResetToDefault()
{
ProxyProvider<TService>.current = DefaultProxyProvider.Instance;
}
/// <summary>
/// Loads the proxy.
/// </summary>
/// <param name="forceNew">if set to <c>true</c> [force new].</param>
/// <returns>The instance of the proxy.</returns>
public virtual TService Provide(bool forceNew = false)
{
if (forceNew || !this.IsInstanceValid())
{
this.service = this.CreateInstance();
return this.service;
}
return this.service;
}
/// <summary>
/// Internals the load.
/// </summary>
/// <returns>The new created service.</returns>
protected abstract TService CreateInstance();
private bool IsInstanceValid()
{
var instance = this.service as ICommunicationObject;
if (instance == null)
{
return false;
}
return instance.State != CommunicationState.Faulted && instance.State != CommunicationState.Closed && instance.State != CommunicationState.Closing;
}
/// <summary>
/// Defines the default <see cref="ProxyProvider<TService>"/> which uses the System DateTime.UtcNow value.
/// </summary>
private sealed class DefaultProxyProvider : ProxyProvider<TService>
{
/// <summary>
/// Reference to the instance of the <see cref="ProxyProvider<TService>"/>.
/// </summary>
private static ProxyProvider<TService> instance;
/// <summary>
/// Gets the instance.
/// </summary>
public static ProxyProvider<TService> Instance
{
get
{
if (DefaultProxyProvider.instance == null)
{
DefaultProxyProvider.instance = new DefaultProxyProvider();
}
return DefaultProxyProvider.instance;
}
}
/// <summary>
/// Loads the specified force new.
/// </summary>
/// <returns>A non-disposed instance of the given service.</returns>
protected override TService CreateInstance()
{
var loadedService = Activator.CreateInstance<TService>();
return loadedService;
}
}
追加の「遅延」プロバイダーを使用すると、次のようになります。
public class CustomConstructorProxyProvider<TService> : ProxyProvider<TService>
where TService : class
{
private readonly Func<TService> constructor;
/// <summary>
/// Initializes a new instance of the <see cref="CustomConstructorProxyProvider<TService>"/> class.
/// </summary>
/// <param name="constructor">The constructor.</param>
public CustomConstructorProxyProvider(Func<TService> constructor)
{
this.constructor = constructor;
}
/// <summary>
/// Internals the load.
/// </summary>
/// <returns>The new created service.</returns>
protected override TService CreateInstance()
{
var service = this.constructor();
return service;
}
}
このように使用されます:
var proxy = ProxyProvider<IWorkflowService>.Current.Provide();
proxy.DoSomething();
次のように初期化します。
ProxyProvider<IWorkflowService>.Current = new CustomConstructorProxyProvider<IWorkflowService>(() => new WorkflowServiceProxy("endpoint"));
ワークフロー サービスは IIS によってホストされ、次の調整設定を追加しました。
<serviceThrottling
maxConcurrentCalls="512"
maxConcurrentInstances="2147483647"
maxConcurrentSessions="1024"/>
私のニーズにはこれで十分です。
望ましいスケーラビリティを実現するためにクライアントとサーバーを構成するのを誰かが手伝ってくれることを願っています (WorkflowInstance sql ストアを使用して、数百が順番に開始され、並行して実行されます)。
更新: すべてのサービスに NetTcpBinding を使用しています。
更新 2 : すべてのサービスは現在ローカルでホストされ、消費されています。
ありがとうフランチェスコ