[求助]WCF服务内存泄漏

push0529 2017-09-04 11:58:27
用WCF实现一个代理,使用PerSession模式,每收到一个请求创建一个AppDomain,加载第三方库,实现一些功能调用(必须要在新的AppDomain中才能实现)。

测试发现,跑一个晚上,大约处理20000多个连接请求后,内存会增加300M。

使用ANTS Memory Profiler分析工具发现,增长的instance主要集中在System.xml和System.ServiceModel.都是ServiceHost引用的。


...全文
528 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
push0529 2017-09-04
  • 打赏
  • 举报
回复
[code=csharpusing System; using System.Diagnostics; using System.ServiceModel; using System.ServiceModel.Description; using NLog; namespace MesServiceLib { [ServiceBehavior( #if WCF_ON_SINGLETON InstanceContextMode = InstanceContextMode.Single, #else InstanceContextMode = InstanceContextMode.PerSession, #endif ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false, IncludeExceptionDetailInFaults = true)] public class MesService : IMesService { #region configuration public const int DEF_SESSION_NUM = MesObjPool.MAX_OBJ_NUM; public const int DEF_SESSION_LIFE = 1 * 60; /* Seconds */ #endregion private static Logger logger = LogManager.GetCurrentClassLogger(); /* this is used to setup appDomain before MesService start run */ private static BeforeAll appDomains = new BeforeAll(); class BeforeAll { public BeforeAll() { logger.Trace("MesObjPool.Setup with Mock {0}", MesObjPool.Mock ? "enabled" : "disabled"); //MesObjPool.Setup(); } } private IMesService imp; public class WcfCtrl { private const string EP_ADDRESS = "net.tcp://%serverip%:8733/MesService"; public static string HostFail = "ServiceHost open failed"; private static ServiceHost mSelfHost = null; public static void Start(int MaxSessionNum = DEF_SESSION_NUM, int MaxSessionTime = DEF_SESSION_LIFE) { if (mSelfHost!=null) { return; } TestSupport.SetHalfSpeed(); string address = EP_ADDRESS.Replace("%serverip%", ConfigReader.GetItem("SERVERIP")); mSelfHost = new ServiceHost(typeof(MesService), new Uri(address)); try { NetTcpBinding binding = new NetTcpBinding(SecurityMode.None); binding.ReceiveTimeout = new TimeSpan(0, MaxSessionTime/60, 0); mSelfHost.AddServiceEndpoint(typeof(IMesService), binding, ""); ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = false; mSelfHost.Description.Behaviors.Add(smb); // IMetadataExchange only usable after ServiceMetadataBehavior added. mSelfHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex"); #region Max Concurrent Control ServiceThrottlingBehavior throttleBehavior = mSelfHost.Description.Behaviors.Find<ServiceThrottlingBehavior>(); if (throttleBehavior == null) { throttleBehavior = new ServiceThrottlingBehavior(); mSelfHost.Description.Behaviors.Add(throttleBehavior); } throttleBehavior.MaxConcurrentCalls = MaxSessionNum; throttleBehavior.MaxConcurrentInstances = MaxSessionNum; throttleBehavior.MaxConcurrentSessions = MaxSessionNum; #endregion mSelfHost.Open(); logger.Info("WcfCtrl.Start at {0}{1}", address, MesObjPool.Mock ? " with Mock" : ""); } catch (Exception e) { throw new Exception(HostFail + " : " + e.ToString()); } } public static void Stop() { try { /* new MES doesn't support shutdown */ //MesAdapter.MesEnviormentShutdown(); mSelfHost.Close(); mSelfHost = null; MesObjPool.Clean(); logger.Info("WcfCtrl.Stop"); } catch (CommunicationException ce) { Console.WriteLine("An exception occurred: {0}", ce.Message); mSelfHost.Abort(); } } } public bool Connect(string clientStation, out string errorMessage) { #if use_mes_in_appdomain imp = new MesAdapter(); #else imp = new MesAppDomain(clientStation); #endif bool ret = imp.Connect(clientStation, out errorMessage); if (!ret) { imp.Disconnect(clientStation, out errorMessage); imp = null; } return ret; } public bool Disconnect(string clientStation, out string errorMessage) { bool ret = imp.Disconnect(clientStation, out errorMessage); imp = null; return ret; } public bool GetWorkStep(string sn, out string workStep, out string errorMessage) { return imp.GetWorkStep(sn, out workStep, out errorMessage); } public bool GetStepState(string sn, out string StepState, out string errorMessage) { return imp.GetStepState(sn, out StepState, out errorMessage); } public bool MoveStandard(string sn, out string errorMessage) { return imp.MoveStandard(sn, out errorMessage); } public bool Hold(string sn, string reason, out string errorMessage) { return imp.Hold(sn, reason, out errorMessage); } public bool MoveIn(string sContainer, out string errorMessage) { return imp.MoveIn(sContainer, out errorMessage); } public bool MoveNonStd(string sChildSerialNum, string sWorkflow, string sWorkflowStep, bool bScrapFlag, out string errorMessage) { return imp.MoveNonStd(sChildSerialNum, sWorkflow, sWorkflowStep, bScrapFlag, out errorMessage); } public bool Release(string sContainerName, string sReleaseReason, out string errorMessage) { return imp.Release(sContainerName, sReleaseReason, out errorMessage); } } } ][/code]
push0529 2017-09-04
  • 打赏
  • 举报
回复

using System;
using System.Collections.Generic;
using System.ServiceModel;
using NLog;

namespace MesServiceLib
{
    public class MesProxy
    {
        private static Logger logger = LogManager.GetCurrentClassLogger();
        #region exceptions
        public static string ExceptionConnectFail = "Failed to connect server";
        public static string ExceptionServerLackOfResource = "Server resources are all occupied now";
        public static string ExceptionConnectBreakDueToSilent = "Server shutdown the connection";
        #endregion
        private const string EP_ADDRESS = "net.tcp://%serverip%:8733/MesService";
        private static IMesService _proxy = null;
        private static int reference = 0;
        private static object _lock = new object();

        public static IMesService GetInstance()
        {
            lock (_lock)
            {
                reference++;

                if (_proxy == null)
                {
                    string address = EP_ADDRESS.Replace("%serverip%", ConfigReader.GetItem("SERVERIP"));

                    EndpointAddress ep = new EndpointAddress(address);
                    NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);

                    ChannelFactory<IMesService> channelFactory = new ChannelFactory<IMesService>(binding, ep);
                    _proxy = channelFactory.CreateChannel();

                    bool retOk = true;
                    string errorMsg;
                    try
                    {
                        logger.Trace("GetInstance");

                        retOk = _proxy.Connect(ConfigReader.GetItem("RESOURCE"), out errorMsg);

                        if (!retOk)
                        {
                            logger.Error("DestroyInstance due to connect fail");
                            ((IClientChannel)_proxy).Close();
                            _proxy = null;

                            throw new Exception(ExceptionServerLackOfResource + ":" + errorMsg);
                        }
                    }
                    catch (Exception e)
                    {
                        logger.Error("Connect Failed by {0} : {1}", ConfigReader.GetItem("RESOURCE"), e.ToString());

                        if (!retOk)
                        {
                            throw e;
                        }
                        else
                        {
                            throw new Exception(ExceptionConnectFail + ":" + e);
                        }
                    }
                }
            }

            return _proxy;
        }

        public static void DestroyInstance()
        {
            try
            {
                lock (_lock)
                {
                    string errMsg;
                    if (_proxy != null)
                    {
                        logger.Trace("DestroyInstance");

                        _proxy.Disconnect("BITester", out errMsg);
                        ((IClientChannel)_proxy).Close();
                        _proxy = null;
                    }
                }
            }
            catch (Exception e)
            {
                /* The socket connection was aborted */
                try
                {
                    ((IClientChannel) _proxy).Close();
                }
                catch (Exception e2)
                {
                    ((IClientChannel)_proxy).Abort();
                    throw new Exception(ExceptionConnectBreakDueToSilent + ":" + e2);
                }
            }
        }

        public static void ShowSessionId()
        {
            IContextChannel contextChannel = _proxy as IContextChannel;
            using (OperationContextScope contextScope = new OperationContextScope(contextChannel))
            {
                Console.WriteLine("operationContextScope hashcode is {0}", contextScope.GetHashCode());
                if (null == OperationContext.Current.SessionId)
                {
                    Console.WriteLine("SessionId is null");
                }
                else
                {
                    Console.WriteLine("Session is {0}", OperationContext.Current.SessionId);
                }
            }
        }
    }
}
push0529 2017-09-04
  • 打赏
  • 举报
回复

using System;
using System.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Description;
using NLog;

namespace MesServiceLib
{
    [ServiceBehavior(
#if WCF_ON_SINGLETON
        InstanceContextMode = InstanceContextMode.Single,
#else
        InstanceContextMode = InstanceContextMode.PerSession,
#endif
        ConcurrencyMode = ConcurrencyMode.Multiple,
        UseSynchronizationContext = false,
        IncludeExceptionDetailInFaults = true)]
    public class MesService : IMesService
    {
        #region configuration
        public const int DEF_SESSION_NUM = MesObjPool.MAX_OBJ_NUM;
        public const int DEF_SESSION_LIFE = 1 * 60;                      /* Seconds */
        #endregion
        private static Logger logger = LogManager.GetCurrentClassLogger();
        /* this is used to setup appDomain before MesService start run */
        private static BeforeAll appDomains = new BeforeAll();
        class BeforeAll
        {
            public BeforeAll()
            {
                logger.Trace("MesObjPool.Setup with Mock {0}", MesObjPool.Mock ? "enabled" : "disabled");
                //MesObjPool.Setup();
            }
        }
        private IMesService imp;

        public class WcfCtrl
        {
            private const string EP_ADDRESS = "net.tcp://%serverip%:8733/MesService";
            public static string HostFail = "ServiceHost open failed";

            private static ServiceHost mSelfHost = null;
            public static void Start(int MaxSessionNum = DEF_SESSION_NUM, int MaxSessionTime = DEF_SESSION_LIFE)
            {
                if (mSelfHost!=null)
                {
                    return;
                }

                TestSupport.SetHalfSpeed();

                string address = EP_ADDRESS.Replace("%serverip%", ConfigReader.GetItem("SERVERIP"));
                mSelfHost = new ServiceHost(typeof(MesService), new Uri(address));

                try
                {
                    NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);
                    binding.ReceiveTimeout = new TimeSpan(0, MaxSessionTime/60, 0);
                    mSelfHost.AddServiceEndpoint(typeof(IMesService), binding, "");

                    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
                    smb.HttpGetEnabled = false;
                    mSelfHost.Description.Behaviors.Add(smb);

                    // IMetadataExchange only usable after ServiceMetadataBehavior added.
                    mSelfHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");

                    #region Max Concurrent Control
                    ServiceThrottlingBehavior throttleBehavior = mSelfHost.Description.Behaviors.Find<ServiceThrottlingBehavior>();
                    if (throttleBehavior == null)
                    {
                        throttleBehavior = new ServiceThrottlingBehavior();
                        mSelfHost.Description.Behaviors.Add(throttleBehavior);
                    }
                    throttleBehavior.MaxConcurrentCalls = MaxSessionNum;
                    throttleBehavior.MaxConcurrentInstances = MaxSessionNum;
                    throttleBehavior.MaxConcurrentSessions = MaxSessionNum;
                    #endregion

                    mSelfHost.Open();
                    logger.Info("WcfCtrl.Start at {0}{1}", address, MesObjPool.Mock ? " with Mock" : "");
                }
                catch (Exception e)
                {
                    throw new Exception(HostFail + " : " + e.ToString());
                }
            }
            public static void Stop()
            {
                try
                {
                    /* new MES doesn't support shutdown */
                    //MesAdapter.MesEnviormentShutdown();
                    mSelfHost.Close();
                    mSelfHost = null;
                    MesObjPool.Clean();
                    logger.Info("WcfCtrl.Stop");
                }
                catch (CommunicationException ce)
                {
                    Console.WriteLine("An exception occurred: {0}", ce.Message);
                    mSelfHost.Abort();
                }
            }
        }

        public bool Connect(string clientStation, out string errorMessage)
        {
#if use_mes_in_appdomain
            imp = new MesAdapter();
#else
            imp = new MesAppDomain(clientStation);
#endif
            bool ret = imp.Connect(clientStation, out errorMessage);
            if (!ret)
            {
                imp.Disconnect(clientStation, out errorMessage);
                imp = null;
            }

            return ret;
        }
        public bool Disconnect(string clientStation, out string errorMessage)
        {
            bool ret = imp.Disconnect(clientStation, out errorMessage);
            imp = null;
            return ret;
        }

        public bool GetWorkStep(string sn, out string workStep, out string errorMessage)
        {
            return imp.GetWorkStep(sn, out workStep, out errorMessage);
        }
        public bool GetStepState(string sn, out string StepState, out string errorMessage)
        {
            return imp.GetStepState(sn, out StepState, out errorMessage);
        }
        public bool MoveStandard(string sn, out string errorMessage)
        {
            return imp.MoveStandard(sn, out errorMessage);
        }
        public bool Hold(string sn, string reason, out string errorMessage)
        {
            return imp.Hold(sn, reason, out errorMessage);
        }
        public bool MoveIn(string sContainer, out string errorMessage)
        {
            return imp.MoveIn(sContainer, out errorMessage);
        }
        public bool MoveNonStd(string sChildSerialNum, string sWorkflow, string sWorkflowStep, bool bScrapFlag, out string errorMessage)
        {
            return imp.MoveNonStd(sChildSerialNum, sWorkflow, sWorkflowStep, bScrapFlag, out errorMessage);
        }
        public bool Release(string sContainerName, string sReleaseReason, out string errorMessage)
        {
            return imp.Release(sContainerName, sReleaseReason, out errorMessage);
        }
    }
}

12,162

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 Web Services
社区管理员
  • Web Services社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧