我有带有两个控制器的简单asp.net WebApi项目。 第一个控制器使用 System.Linq ,并且在重负载下会出现死锁。其次使用 MongoDB.Driver.Linq 并运行良好。
我使用了ab -c 10 -n 200000 -p post -H'内容类型:application / json'-T'application / json''http://localhost:1989/api/SystemLinq/find'
为什么使用System.linq会出现死锁?
仅当读取数据后引发新的Exception时才发生死锁。我用IExceptionFilter捕获的异常。完整项目https://github.com/artyukh/AspNetMongoDeadlock
具有死锁的控制器
SELECT l1.username "User",
l2.username "Following"
FROM login l1
INNER JOIN followers f
ON f.idsta = l1.id
INNER JOIN login l2
ON l2.id = f.idfol
WHERE l1.id = 3;
工作控制器
using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
using System.Linq;
using TestDeadlock.Core;
namespace TestDeadlock.Controllers
{
[Route("api/[controller]")]
public class SystemLinqController : Controller
{
private MongoContext _context;
public SystemLinqController(MongoContext context)
{
_context = context;
}
[HttpPost]
[Route("find")]
public void Find([FromBody]AuthenticateInputDTO input)
{
var result = _context.UserSet.AsQueryable().Where(u => u.Email == input.Username).FirstOrDefault();
if (result == null)
throw new BusinessException("User not found");
}
}
}
ConfigureServices
using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using TestDeadlock.Core;
namespace TestDeadlock.Controllers
{
[Route("api/[controller]")]
public class MongoLinqController : Controller
{
private MongoContext _context;
public MongoLinqController(MongoContext context)
{
_context = context;
}
[HttpPost]
[Route("find")]
public void Find([FromBody]AuthenticateInputDTO input)
{
var result = _context.UserSet.AsQueryable().Where(u => u.Email == input.Username).FirstOrDefault();
if (result == null)
throw new BusinessException("User not found");
}
}
}
GlobalExceptionFilter
public void ConfigureServices(IServiceCollection services)
{
var appSettings = Configuration.GetSection("AppSettings");
// Add framework services.
services.AddMvc(options =>
{
options.Filters.Add(new GlobalExceptionFilter());
});
services.AddMvc();
services.Configure<MongoSettings>(options =>
{
options.ConnectionString
= Configuration.GetSection("MongoConnection:ConnectionString").Value;
options.Database
= Configuration.GetSection("MongoConnection:Database").Value;
});
services.AddSingleton<MongoContext>();
}