简体   繁体   English

托管在另一个AppDomain中的WCF主机速度慢

[英]Slow WCF Host when hosted in another AppDomain

I am having a weird problem. 我有一个奇怪的问题。 If the WCF host is hosted in the original AppDomain, the code takes 1.25s to execute. 如果WCF主机托管在原始AppDomain中,则代码需要1.25秒执行。 However if I put it in a new AppDomain, despite the fact that I still use net.pipe or net.tcp to talk to it, the process takes 4.7s to run. 但是,即使我仍然使用net.pipe或net.tcp与之交谈,如果我将其放在新的AppDomain中,则该过程仍需要4.7s才能运行。 Here is the code with app.config in the commented out block on the bottom. 这是底部注释栏中带有app.config的代码。

namespace ConsoleApplication2
{
    using System;
    using System.Collections.Concurrent;
    using System.Diagnostics;
    using System.Linq;
    using System.Net;
    using System.Net.NetworkInformation;
    using System.Reflection;
    using System.ServiceModel;
    using System.Threading.Tasks;

    using Client;

    internal class Program
    {
        #region Methods

        private static void Main(string[] args)
        {
            var p = new Program();
            p.Execute();
        }

        #endregion

        public void Execute()
        {
            var hosts = Enumerable.Range(0, 1).Select(CreateNewHost).ToArray();
            var r = new Random();
            var cb = new ConcurrentDictionary<int, string>();
            Action a = () =>
            {
                try
                {
                    Parallel.For(
                        0,
                        10000,
                        i =>
                        {
                            //string ep = String.Format("net.pipe://localhost/iService{0}", hosts[r.Next(0, hosts.Length)]);
                            string ep = String.Format("net.tcp://localhost:{0}/iService", hosts[r.Next(0, hosts.Length)]);
                            string s=null;
                            //using (var cli = new ServiceClassClient("NetNamedPipeBinding_IServiceClass", ep))
                            using (var cli = new ServiceClassClient("NetTcpBinding_IServiceClass", ep))
                            {
                                s = cli.Ping();
                            }
                            if (!String.IsNullOrEmpty(s))
                            {
                                cb[i] = s;
                            }
                        });
                }
                catch (AggregateException aggregateException)
                {
                    Console.WriteLine(aggregateException);
                }
            };
            Console.WriteLine("\n\nIt took {0:G}", a.TimeThis());
            Console.ReadKey();
        }

        static int CreateNewHost(int s)
        {
            //uncomment for in-process host
            //var h1 = new Host();
            //return h1.Port;

            var appDomain = AppDomain.CreateDomain(
                "A" + s,
                null,
                new AppDomainSetup
                    {
                        LoaderOptimization = LoaderOptimization.MultiDomain,
                        DisallowBindingRedirects = true
                    });
            var assemblyName = Assembly.GetAssembly(typeof(Host)).FullName;
            var h = appDomain.CreateInstanceAndUnwrap(assemblyName, typeof(Host).FullName) as Host;
            return h.Port;
        }
    }

    //comment out MarshalByRefObject for in-process host
    public class Host:MarshalByRefObject
    {
        #region Fields

        private readonly ServiceHost host;

        private readonly int port;

        #endregion

        #region Constructors and Destructors

        public Host()
        {
            this.port = this.GetFreePort();
            var ub = new UriBuilder { Host = "localhost", Port = this.port, Scheme = "net.tcp" };
            var up = new UriBuilder { Host = "localhost", Scheme = "net.pipe", Path = "iService" + this.port };
            this.host = new ServiceHost(typeof(ServiceClass), ub.Uri);
            var netNamedPipeBinding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
            this.host.AddServiceEndpoint(typeof(IServiceClass), netNamedPipeBinding, up.Uri);
            var un = new UriBuilder { Host = "localhost", Port = this.port, Scheme = "net.tcp", Path = "iService" };
            var netTcpBinding = new NetTcpBinding(SecurityMode.None);
            this.host.AddServiceEndpoint(typeof(IServiceClass), netTcpBinding, un.Uri);

//#if DEBUG
            //var us = new UriBuilder { Host = "localhost", Port = this.port, Scheme = "http", Path = "iServiceMeta" };
            //var smb = new ServiceMetadataBehavior { HttpGetEnabled = true, HttpGetUrl = us.Uri };
            //this.host.Description.Behaviors.Add(smb);
//#endif
            this.host.Open();
            Console.WriteLine("Listening at {0}", this.host.BaseAddresses[0].AbsoluteUri);
        }

        #endregion

        #region Public Properties

        public int Port
        {
            get
            {
                return this.port;
            }
        }

        public ServiceHost ServiceHost
        {
            get
            {
                return this.host;
            }
        }

        #endregion

        #region Methods

        private int GetFreePort()
        {
            TcpConnectionInformation[] connections = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections();
            IPEndPoint[] listeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners();
            var udps = IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners();
            var r = new Random();
            int port;
            do
            {
                port = r.Next(1025, 65534);
            }
            while (listeners.Any(a => a.Port == port) || connections.Any(a => a.LocalEndPoint.Port == port) || udps.Any(a=>a.Port==port));
            return port;
        }

        #endregion
    }

    [ServiceContract]
    internal interface IServiceClass
    {
        #region Public Methods and Operators

        [OperationContract]
        string Ping();

        #endregion
    }

    internal class ServiceClass : IServiceClass
    {
        #region Public Methods and Operators

        public string Ping()
        {
            return ((new Random()).NextDouble() * (new Random()).NextDouble()).ToString("F11");
        }

        #endregion
    }

    public static class Extensions
    {
        #region Public Methods and Operators

        public static TimeSpan TimeThis(this Action action)
        {
            var sw = new Stopwatch();
            sw.Start();
            action.Invoke();
            sw.Stop();
            return sw.Elapsed;
        }

        #endregion
    }
}

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.18033
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace Client
{

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(ConfigurationName = "IServiceClass")]
    public interface IServiceClass
    {

        [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IServiceClass/Ping", ReplyAction = "http://tempuri.org/IServiceClass/PingResponse")]
        string Ping();
    }

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    public interface IServiceClassChannel : IServiceClass, System.ServiceModel.IClientChannel
    {
    }

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    public partial class ServiceClassClient : System.ServiceModel.ClientBase<IServiceClass>, IServiceClass
    {

        public ServiceClassClient()
        {
        }

        public ServiceClassClient(string endpointConfigurationName)
            : base(endpointConfigurationName)
        {
        }

        public ServiceClassClient(string endpointConfigurationName, string remoteAddress)
            : base(endpointConfigurationName, remoteAddress)
        {
        }

        public ServiceClassClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress)
            : base(endpointConfigurationName, remoteAddress)
        {
        }

        public ServiceClassClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress)
            : base(binding, remoteAddress)
        {
        }

        public string Ping()
        {
            return base.Channel.Ping();
        }
    }
}


/*
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <netNamedPipeBinding>
        <binding name="NetNamedPipeBinding_IServiceClass">
          <security mode="None" />
        </binding>
      </netNamedPipeBinding>
      <netTcpBinding>
        <binding name="NetTcpBinding_IServiceClass">
          <security mode="None" />
        </binding>
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint address="" binding="netNamedPipeBinding"
          bindingConfiguration="NetNamedPipeBinding_IServiceClass" contract="IServiceClass"
          name="NetNamedPipeBinding_IServiceClass" />
      <endpoint address="" binding="netTcpBinding"
          bindingConfiguration="NetTcpBinding_IServiceClass" contract="IServiceClass"
          name="NetTcpBinding_IServiceClass" />
    </client>
  </system.serviceModel>
</configuration>
*/

You might get improved performance by decorating your Main method with LoaderOptimization attribute. 通过使用LoaderOptimization属性装饰Main方法,可以提高性能。 This shares common resources across app domains. 这在应用程序域之间共享公共资源。

[LoaderOptimization(LoaderOptimization.MultiDomain)]

See this answer for more details. 有关更多详细信息,请参见此答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在新AppDomain中建立的第一个WCF连接非常慢 - First WCF connection made in new AppDomain is very slow 在另一个AppDomain中调用Await时没有SynchronizationContext - No SynchronizationContext when calling Await in a another AppDomain 在新的AppDomain中启动WCF服务以启用卷影副本(托管Windows服务) - Start WCF service in a new AppDomain to enable shadow copy (Windows Service hosted) 主机重命名后WCF服务变慢 - WCF service slow after host renamed 在部分受信任的AppDomain中调用WCF操作时,“请求失败” - “Request failed” when invoking a WCF operation in a partially-trusted AppDomain MEF和WCF-AppDomain问题 - MEF and WCF - Issues with AppDomain 当自托管主机应用程序甚至无法使用WCF服务本身时定义服务端点的意义是什么? - what is the point of defining service endpoints in a WCF service itself when a self-hosted host application can't even use it 从主机WinForms程序访问自托管WCF服务 - Accessing a Self-Hosted WCF Service From the Host WinForms Program 在IIS托管的代码中使用NetTcp绑定和配置来托管WCF服务 - Host WCF service using NetTcp binding and configuration in code hosted in IIS 在IIS中托管的WCF有很多打开请求,服务速度很慢 - WCF hosted in IIS has lots of open requests and the service is slow down
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM