1

現在、ワークフロー サービスでいくつかの問題が発生しています。短いシーケンスで 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&lt;TService&gt;"/> which uses the System DateTime.UtcNow value.
    /// </summary>
    private sealed class DefaultProxyProvider : ProxyProvider<TService>
    {
        /// <summary>
        /// Reference to the instance of the <see cref="ProxyProvider&lt;TService&gt;"/>.
        /// </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&lt;TService&gt;"/> 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 : すべてのサービスは現在ローカルでホストされ、消費されています。

ありがとうフランチェスコ

4

0 に答える 0