0

何かが発生したときにメールやプッシュ メッセージを iPhone に送信するプログラムの一部があります。これは、MSMQ を使用して 2 つの別個の WCF サービスを呼び出すことによって行われます。このガイド (モデル 4.0)に従って、汎用的でテストしやすいものにしました。私は一般的なチャネルの作成が好きですが、私の質問は、プロキシとチャネル ファクトリが本当に正しく閉じられているかどうか、または 10000 ユーザー環境に達したときにこれが爆発するかどうかです (最終的にはそうなります)。このコードは、50 ユーザーのテスト環境で完全に機能します。

したがって、次のコードを確認してください。

サービス プロキシ

public class ServiceProxy<TChannel> : IServiceProxy<TChannel> where TChannel : ICommunicationObject
{
    private readonly TChannel InnerChannel;

    public ServiceProxy(TChannel innerChannel)
    {
        this.InnerChannel = innerChannel;
    }

    public void Execute(Action<TChannel> operation)
    {
        try
        {
            operation(InnerChannel);
            InnerChannel.Close();
        }
        catch (CommunicationException)
        {
            InnerChannel.Abort();
        }
        catch (TimeoutException)
        {
            InnerChannel.Abort();
        }
        catch (Exception)
        {
            InnerChannel.Abort();
            throw;
        }
    }

    public TResult Execute<TResult>(Func<TChannel, TResult> operation)
    {
        TResult result = default(TResult);

        try
        {
            result = operation(InnerChannel);
            InnerChannel.Close();
        }
        catch (CommunicationException)
        {
            InnerChannel.Abort();
        }
        catch (TimeoutException)
        {
            InnerChannel.Abort();
        }
        catch (Exception)
        {
            InnerChannel.Abort();
            throw;
        }

        return result;
    }
}

サービス プロキシ ファクトリ

public class ServiceProxyFactory : IServiceProxyFactory
{
    public IServiceProxy<TChannel> GetProxy<TChannel>(string endpointName) where TChannel : ICommunicationObject
    {
        var factory = new ChannelFactory<TChannel>(endpointName);
        return new ServiceProxy<TChannel>(factory.CreateChannel());
    }
}

サービス呼び出しの実行(簡単にするために戻り値の型はありません)

public class MessageSender : IMessageSender
{
    private const string PushServiceEndpoint = "PushEndpointName";
    private const string MailServiceEndpoint = "MailEndpointName";

    private readonly IServiceProxyFactory ServiceProxyFactory;

    public MessageSender()
    {
        ServiceProxyFactory = new ServiceProxyFactory();
    }

    public void NotifyMe(*some args*)
    {
        ServiceProxyFactory.GetProxy<MailServiceChannel>(MailServiceEndpoint)
                     .Execute(a => a.SendEmail(*some args*));
    }

質問は次のとおりです。

実行後に ServiceProxy を閉じる必要がありますか?

GetProxy() を呼び出すたびに ChannelFactory を作成するのが賢明ですか? その場合、この ChannelFactory を再度閉じる必要がありますか?

呼び出しごとに ServiceProxy を生成するのは、本当にパフォーマンスにやさしいのでしょうか? (私には本当に重いように思えますが、誰かが私が間違っていることを証明できるかもしれません).

この投稿ではインターフェイスを省略しましたが、それらは非常にシンプルであり、プロキシとインターフェイスを使用したこのセットアップ全体は、単体テストと統合テストで非常にうまく機能します。

コーディング ウィザードの何人かがこれについて意見を持っていることを願っています。これを共有してください。

前もって感謝します!

4

1 に答える 1

1

主なパフォーマンスへの影響は、ChannelFactory.

ChannelFactory インスタンスの作成には次の操作が含まれるため、オーバーヘッドが発生します。 ContractDescription ツリーの構築

Reflecting all of the required CLR types

Constructing the channel stack

Disposing of resources

https://msdn.microsoft.com/en-us/library/hh314046%28v=vs.110%29.aspx

WCF チームはClientBase<TChannel>クラスのキャッシングを実装しました。自動生成されたプロキシ クラスがある場合に適しています。pureChannelFactoryを使用しているため、パフォーマンスを向上させるために、各呼び出しでファクトリを作成することに注意する必要があります。

ChannelFactory<TChannel>適切な解決策は、独自のキャッシングを実装することです (その方法については良いアイデアがあります)。したがって、最後に、のようなキャッシュされたインスタンスを使用する必要はServiceProxyFactoryありません。new ChannelFactory<TChannel>(endpointName);CachedChannelFactory<TChannel>.GetInstance()

編集: Michele Leroux Bustamante によって書かれた別の良い記事があり、いつキャッシュするかしないかを説明しています

于 2015-11-03T10:35:48.633 に答える