메모리를 계속 먹기 때문에 몇 달에 한 번씩 수동으로 다시 시작해야하는 기존 Windows 서비스 (C#으로 작성 됨)를 디버깅합니다.NHibernate가있는 Windows 서비스가 사용 메모리를 늘리고 있습니다.
서비스는 그리 복잡하지 않습니다. 제품을 보유하고있는 외부 서버에서 json 파일을 요청합니다. 다음으로이 json 파일을 제품 목록으로 구문 분석합니다. 이러한 각 제품에 대해이 제품이 이미 데이터베이스에 있는지 확인하고 있습니다. 만약 존재하지 않는다면 속성이 업데이트 될 것입니다.
데이터베이스는 PostgreSQL 데이터베이스이며 우리는 ORM으로 NHibernate v3.2.0을 사용합니다.
서비스가 시작하고 30 대 이후는 일을 시작 :
나는 실행시 서비스를 프로파일 JetBrains의 DotMemory을 사용하고있다. SnapShot # 1은 첫 번째 실행 전에 만들어집니다. 스냅 샷 # 6은 5 회에 걸쳐 실행되었습니다. 다른 스냅 샷은 실행 후에도 생성됩니다. 각 실행 후에 볼 수 있듯이 개체 수가 약 증가함에 따라 증가합니다. 60k이고 사용 된 메모리는 매 실행 후 수 MB로 증가합니다.try
{
// Trying to fix certificate errors:
ServicePointManager.ServerCertificateValidationCallback += delegate
{
_logger.Debug("Cert validation work around");
return true;
};
_timer = new Timer(_interval)
{
AutoReset = false // makes it fire only once, restart when work is done to prevent multiple runs
};
_timer.Elapsed += DoServiceWork;
_timer.Start();
}
catch (Exception ex)
{
_logger.Error("Exception in OnStart: " + ex.Message, ex);
}
그리고 내 DoServiceWork :
가 여기 내 ONSTART 코드입니다 :
가까이 스냅 샷 # 6에서 찾고 는의 유지 크기가 대부분 NHibernate에 세션 객체에 의해 사용되는 표시
try
{
// Call execute
var processor = new SAPProductProcessor();
processor.Execute();
}
catch (Exception ex)
{
_logger.Error("Error in DoServiceWork", ex);
}
finally
{
// Next round:
_timer.Start();
}
SAPProductProcessor에서 2 회의 db 호출. 둘 다 루프에 있습니다. 제품이 테이블에 이미있는 경우 JSON 파일에서 모든 제품을 통해 I 루프와 제품 코드를 사용하여 확인 :
ProductDto dto;
using (var session = SessionFactory.OpenSession())
{
using (var transaction = session.BeginTransaction(IsolationLevel.ReadCommitted))
{
var criteria = session.CreateCriteria<ProductDto>();
criteria.Add(Restrictions.Eq("Code", code));
dto = criteria.UniqueResult<ProductDto>();
transaction.Commit();
}
}
return dto;
그리고를 productDto 내가 사용하는 저장 업데이트 될 때 :
using (var session = SessionFactory.OpenSession())
{
using (var transaction = session.BeginTransaction(IsolationLevel.ReadCommitted))
{
session.SaveOrUpdate(item);
transaction.Commit();
}
}
메모리와 객체의 수를 늘리지 않으려면 위의 코드를 어떻게 변경해야할지 모르겠습니다.
이미 using (var session = SessionFactory.OpenSession())
대신 var session = SessionFactory.GetCurrentSession();
을 사용했지만 메모리 증가를 막지 못했습니다. 내 데이터 액세스 클래스 MultiSessionFactoryProvider sessionFactoryProvider
의 생성자에서
업데이트가 주입된다. 그리고 기본 클래스는 : base(sessionFactoryProvider.GetFactory("data"))
으로 호출됩니다. 그때 끝에서 시작시 base.BeginSession
및 base.EndSession
를 호출 내 데이터 액세스 클래스에서
ISession session = ThreadLocalSessionContext.Unbind(_sessionFactory);
if (session != null)
{
session.Close();
}
:
ISession session = _sessionFactory.GetCurrentSession();
if (session == null)
{
session = _sessionFactory.OpenSession();
ThreadLocalSessionContext.Bind(session);
}
그리고 EndSession
이 기본 클래스는 방법 BeginSession
있습니다.
은 'DoServiceWork'싱글 톤입니까? 나는 SAPProductProcessor가 매번 생성된다는 것을 알았다. 아마도 그것은 보는 무엇입니까? –
SessionFactory는 속성입니까? SessionFactory는 어디에 생성됩니까? 프로세스 (또는 AppDomain)에 한 번만 만들어야합니다. –
비교를 열고 모든 새 개체를 열고 어떤 개체가 보관되어 있고 왜 있는지 확인합니다. –