当负载增加时 Dapper 崩溃
Dapper is crashing when load is increased
我在基于 .net 5.0 构建的支付处理应用程序中使用 dapper。在单元测试中,一切正常,但是当我使用 JMeter 加载 100 个用户时,在处理了一些事务之后,dapper 开始崩溃并出现以下错误:
Exception[System.InvalidOperationException: Connection must be open
for this operation at
Oracle.ManagedDataAccess.Client.OracleCommand.ValidateStatePriorToExecution()
at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteNonQuery()
at Dapper.SqlMapper.ExecuteCommand(IDbConnection cnn,
CommandDefinition& command, Action2 paramReader) in /_/Dapper/SqlMapper.cs:line 2822 at Dapper.SqlMapper.ExecuteImpl(IDbConnection cnn, CommandDefinition& command) in /_/Dapper/SqlMapper.cs:line 572 at Dapper.SqlMapper.Execute(IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Nullable
1 commandTimeout, Nullable`1
commandType) in /_/Dapper/SqlMapper.cs:line 443
SP执行代码如下:
public static int ExecuteSP(string spName, object parameters)
{
IDbConnection connection = ConnectionManager.GetConnection(_ConnectionString);
int result = connection.Execute(spName, parameters, null, null, CommandType.StoredProcedure);
ConnectionManager.CloseConnection();
return result;
}
public static IDbConnection GetConnection(string connectionString)
{
DefaultTypeMap.MatchNamesWithUnderscores = true;
if (_oracleConnection == null)
{
_oracleConnection = new OracleConnection(GetConnectionString(connectionString));
}
if (_oracleConnection.State == ConnectionState.Closed)
{
_oracleConnection.Open();
}
return _oracleConnection;
}
我在配置或使用 Dapper 时是否遗漏了什么?
这里的错误是使用 static
- 因此是共享 - 连接(即使没有显示,我们可以假设 _oracleConnection
是 static
因为它被访问来自 static
方法 GetConnection
).
连接不是线程安全的,并且通过使其static
,您的所有代码都共享一个连接。这往往会扩展到恰好一个用户,即一个并发请求 - 在此之上:几乎可以保证失败。
连接的范围应为逻辑代码段 - 可以是“单个方法”到“整个请求”之间的任何位置,但它们必须只能 被访问一次一个线程。您还应该确保连接在离开该范围时得到正确处理,以防止连接泄漏。
(顺便说一句:这个问题实际上与 Dapper 无关;任何类似的用法都会出现完全相同的问题 - 无论是 ADO.NET、Dapper、EF 还是其他任何东西)
我在基于 .net 5.0 构建的支付处理应用程序中使用 dapper。在单元测试中,一切正常,但是当我使用 JMeter 加载 100 个用户时,在处理了一些事务之后,dapper 开始崩溃并出现以下错误:
Exception[System.InvalidOperationException: Connection must be open for this operation at Oracle.ManagedDataAccess.Client.OracleCommand.ValidateStatePriorToExecution() at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteNonQuery()
at Dapper.SqlMapper.ExecuteCommand(IDbConnection cnn, CommandDefinition& command, Action2 paramReader) in /_/Dapper/SqlMapper.cs:line 2822 at Dapper.SqlMapper.ExecuteImpl(IDbConnection cnn, CommandDefinition& command) in /_/Dapper/SqlMapper.cs:line 572 at Dapper.SqlMapper.Execute(IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Nullable
1 commandTimeout, Nullable`1 commandType) in /_/Dapper/SqlMapper.cs:line 443
SP执行代码如下:
public static int ExecuteSP(string spName, object parameters)
{
IDbConnection connection = ConnectionManager.GetConnection(_ConnectionString);
int result = connection.Execute(spName, parameters, null, null, CommandType.StoredProcedure);
ConnectionManager.CloseConnection();
return result;
}
public static IDbConnection GetConnection(string connectionString)
{
DefaultTypeMap.MatchNamesWithUnderscores = true;
if (_oracleConnection == null)
{
_oracleConnection = new OracleConnection(GetConnectionString(connectionString));
}
if (_oracleConnection.State == ConnectionState.Closed)
{
_oracleConnection.Open();
}
return _oracleConnection;
}
我在配置或使用 Dapper 时是否遗漏了什么?
这里的错误是使用 static
- 因此是共享 - 连接(即使没有显示,我们可以假设 _oracleConnection
是 static
因为它被访问来自 static
方法 GetConnection
).
连接不是线程安全的,并且通过使其static
,您的所有代码都共享一个连接。这往往会扩展到恰好一个用户,即一个并发请求 - 在此之上:几乎可以保证失败。
连接的范围应为逻辑代码段 - 可以是“单个方法”到“整个请求”之间的任何位置,但它们必须只能 被访问一次一个线程。您还应该确保连接在离开该范围时得到正确处理,以防止连接泄漏。
(顺便说一句:这个问题实际上与 Dapper 无关;任何类似的用法都会出现完全相同的问题 - 无论是 ADO.NET、Dapper、EF 还是其他任何东西)