Prerequisites
- What is your product version?10.1
- What is your product type (Angular or MVC)?Angular
- What is product framework type (.net framework or .net core)?
Please review the issues we are facing in an Enterprise customer application related to connection pool etc. Please note this application is in the critical UAT stage
Our requirement is to have some 800 workflows which should be real-time. We implemented this using hangfire with,
- One background job which runs every 30 seconds to monitor the workflows. – This job checks if there are any active workflow in the DB. If yes, then it starts that workflow as a separate job.
- This monitor will create separate one-time background Jobs for each workflow – In separate workflow background job, we have operations related to DB. Fetching the records from DB and updating data back to DB So, let’s say if we have around 300 workflow active jobs at a time then we could have 300 background job executing at the same time and hitting to same DB .
Now we are facing connection leak/pool issues and application crashes with a few workflows running in the background.
Another requirement is to load the pages within 3-4 seconds. We tried some performance fixes and brought it near to 5-7 seconds. Is there any way to improve this further?
We are using AspnetZero 10.1 as of now. Can you please confirm if upgrading to the latest 10.5 will address our concerns above?
Looking forward to your urgent response @ismcagdas.. We can also discuss the issue over a meeting.
Thanks
10 Answer(s)
-
0
Hi @omkarchoudhari
I suggest you to upgrade ABP NuGet packages to 6.6.1 (or better 6.6.2 which we will release this week). After that, the performance of the web pages will increase. For background jobs, instead of using UnitOfWork attribute on your job methods, we suggest you to manually start a unitOfWork as shown below. The UnitOfWork attribute uses interception and it causes slowness and connection pool issues with high number of requests.
using (var unitOfWork = _unitOfWorkManager.Begin()) { // YOUR CODE HERE await unitOfWork.CompleteAsync(); }
-
0
Hello @ismcagdas,
Does this mean upgrade to aspnetzero 10.5 version ? or Just upgrade only ABP Nuget packages ? How do we upgrade only Niget in the current aspnetzero version (we are using 10.1 version) ?
Can you please guide us ?
Thanks
-
0
Hi @omkarchoudhari
Yes, only ABP NuGet packages. The fastest option is to search for "xxx" (the one you are using) in csproj files and replace it with 6.6.1. Please fo this operation by opening *.All.sln file.
-
0
Thanks @ismcagdas . We are trying this.... Will let you know.
-
0
-
0
Hi,
You need to add [UnitOfWork] attribute to DoWork method.
-
0
-
0
Hi **@omkarchoudhari **
Sorry for my late reply. This happens mostly when you don't update some of the ABP NuGet packages. Could oyu check that on your solution ?
Thanks,
-
0
Hi, Sorry for digging this up, but I have a similar issue with Postgres and idle connections not freeing/closing (leading to PostgresException 53300), and I suspect background workers after reading this thread.
So I understand that using [UnitOfWork] there is bad (which we did use), correct? We're still using version 8.1 of Zero (.net core).
Our background worker has to check many records for all tenants, like so:
public class XVerificationWorker : PeriodicBackgroundWorkerBase, ISingletonDependency { private readonly IRepository<Tenant> _tenantRepository; private readonly IUserEmailer _userEmailer; private readonly XService _xService; private readonly IUnitOfWorkManager _unitOfWorkManager; DateTime lastCheck = DateTime.UtcNow.Date.AddDays(-1); public XVerificationWorker(AbpTimer timer, XService xService, IRepository<Tenant> tenantRepository, IUserEmailer userEmailer, IUnitOfWorkManager unitOfWorkManager) : base(timer) { _tenantRepository = tenantRepository; _userEmailer = userEmailer; _xService = xService; //Timer.Period = 3600000; Timer.Period = 60; _unitOfWorkManager = unitOfWorkManager; } //[UnitOfWork] //Bad?! protected override void DoWork() { if (lastCheck == DateTime.UtcNow.Date || DateTime.UtcNow.Hour < 1) return; lastCheck = DateTime.UtcNow.Date; List<Tenant> affectedTenants = new List<Tenant>(); using (var unitOfWork = _unitOfWorkManager.Begin()) { affectedTenants = _tenantRepository.GetAll().ToList(); unitOfWork.Dispose(); } foreach (Tenant t in affectedTenants) { try { using (var unitOfWork = _unitOfWorkManager.Begin()) { //using (CurrentUnitOfWork.SetTenantId(t.Id)) using (_unitOfWorkManager.Current.SetTenantId(t.Id)) { if (t.Id != 0) try { Task.WaitAll(_xService.FullXVerification()); } catch (Exception ex) { Logger.Error(ex.Message, ex); Task.WaitAll(_userEmailer.TryToSendXVerificationFailedMail(ex.Message)); } } Task.WaitAll(unitOfWork.CompleteAsync()); } } catch (Exception ex) { Logger.Error(ex.Message, ex); } } } }
-> Is that good code now?
Before, we were using it like so:
[UnitOfWork] protected override void DoWork() { [...] foreach (Tenant t in affectedTenants) { [...] using (CurrentUnitOfWork.SetTenantId(t.Id)) { if (t.Id != 0) try { Task.WaitAll(_xService.FullXVerification()); } catch (Exception ex) { Logger.Error(ex.Message, ex); Task.WaitAll(_userEmailer.TryToSendXVerificationFailedMail(ex.Message)); } } } }
Thank you!
-
0
After some more investigation and testing I don't think it's due to the background workers, we will probably open a new thread regarding the idle connections issue. Would still be nice to know the best practice for UoW in background jobs though :-)