3

在我的服务器端代码 (WCF) 中使用 TransactionScope 类时出现性能问题。

我的代码从客户端获取请求,创建 TransactionScope 并执行短操作(通常长达 100 毫秒)。

请参阅下面模拟我的服务器端代码的附加代码。当有100个或更多并发用户时,需要超过1秒的问题!创建新的 TransactionScope(请参阅 GetTransaction() 方法)。

当并发用户达到 200 个时,会抛出 TransactionAborted 。

你有什么想法?

class Program
     {
         private static ConcurrentQueue<double> m_Queue = new ConcurrentQueue<double>();

     static void Main(string[] args)
     {
         Console.WriteLine("Press any key to start ...");
         Console.ReadKey();

         for (int i = 0; i < 100; i++)
         {
             Thread t = new Thread(new ThreadStart(Method));
             t.IsBackground = true;
             t.Start();
         }

         Thread.Sleep(2000);
         Console.WriteLine("Max {0}, Min {1}, Avg {2}, Total {3}", m_Queue.Max(), m_Queue.Min(), m_Queue.Average(), m_Queue.Count);
         Console.ReadKey();
     }


     private static void Method() 
     {
         using (TransactionScope scope = GetTransaction())
         {
             Thread.Sleep(100);
             scope.Complete();
         }
     }

     public static TransactionScope GetTransaction()
     {
         var start = DateTime.Now;

         TransactionOptions options = new TransactionOptions();
         options.IsolationLevel = IsolationLevel.ReadCommitted;
         var t = new TransactionScope(TransactionScopeOption.Required, options);

         // Log creation time
         m_Queue.Enqueue((DateTime.Now.Subtract(start)).TotalMilliseconds);

         return t;
     }

 }
4

2 回答 2

0

初步答案:

如果我用一个简单的 List 而不是 ConcurrentQueue 来测试它(我没有安装 .net 4.5),那么你的代码在我这边工作得很好。

由于您同时启动 200 个线程,因此您的行:

Console.WriteLine("Max {0}, Min {1}, Avg {2}, Total {3}", m_Queue.Max(), m_Queue.Min(), m_Queue.Average(), m_Queue.Count);

基本上开始迭代队列,这会阻塞队列,这会导致仍在启动的线程在尝试将项目添加到队列时冻结,进而导致事务超时。

如果没有上面提到的控制台写行,你可以试试吗?另外,尝试使用普通列表。

一个解决方案是在尝试执行 max/min/avg/total 函数之前等待线程完成。

需要注意的一件事是,我在测试中得到的总数不是完整的 100 或 200。它只是稍微低于一点,这意味着仍有线程启动。

更新:

如果有帮助。如果我在方法中移动 enqueue 调用,我遇到的任何问题都会得到解决。这对你的情况有用吗?

public static TransactionScope GetTransaction() {
    var start = DateTime.Now;

    // Log creation time
    m_Queue.Enqueue((DateTime.Now.Subtract(start)).TotalMilliseconds);

    TransactionOptions options = new TransactionOptions();
    options.IsolationLevel = IsolationLevel.ReadCommitted;
    var t = new TransactionScope(TransactionScopeOption.Required, options);

    return t;
}
于 2013-07-22T08:32:28.733 回答
0

删除您的“入队”行,看看问题是否仍然存在。

另一件事,我很好奇在事务范围内执行的“短操作”。他们可能将事务协调器从 LTM 升级到 MSDTC,这可能解释了更多并发命中的缓慢性。

于 2013-07-22T10:54:23.570 回答