使用ab.exe監測100個併發/100次請求狀況下同步/異步訪問數據庫的性能差別

ab.exe介紹

   ab.exe是apache server的一個組件,用於監測併發請求,並顯示監測數據html

具體使用及下載地址請參考: http://www.cnblogs.com/gossip/p/4398784.html
 
本文的目的
   經過webapi接口模擬100個併發請求下,同步和異步訪問數據庫的性能差別
 
 
建立數據庫及數據
--建立表結構
CREATE TABLE dbo.[Cars] (
Id INT IDENTITY(1000,1) NOT NULL,
Model NVARCHAR(50) NULL,
Make NVARCHAR(50) NULL,
[Year] INT NOT NULL,
Price REAL NOT NULL,
CONSTRAINT [PK_Cars] PRIMARY KEY CLUSTERED (Id) ON [PRIMARY]
) ON [PRIMARY];
GO
 
--建立存儲過程
CREATE PROCEDURE [dbo].[sp$GetCars]
AS
-- 存儲過程執行過程當中等待一秒
WAITFOR DELAY '00:00:01';
SELECT * FROM Cars;
GO
 
--初始化數據 
INSERT INTO dbo.Cars VALUES('Car1', 'Model1', 2006, 24950);
INSERT INTO dbo.Cars VALUES('Car2', 'Model1', 2003, 56829);
INSERT INTO dbo.Cars VALUES('Car3', 'Model2', 2006, 17382);
INSERT INTO dbo.Cars VALUES('Car4', 'Model3', 2002, 72733);
 
 
編寫webapi程序
一、數據訪問類(包含同步/異步訪問數據庫的方法)
 public class GalleryContext
    {
        readonly string _spName = "sp$GetCars";
        readonly string _connectionString =
        ConfigurationManager.ConnectionStrings["TestDBConnStr"].ConnectionString;
 
        /// <summary>
        /// 同步獲取數據
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Car> GetCarsViaSP()
        {
            using (var conn = new SqlConnection(_connectionString))
            {
                using (var cmd = new SqlCommand())
                {
                    cmd.Connection = conn;
                    cmd.CommandText = _spName;
                    cmd.CommandType = CommandType.StoredProcedure;
 
                    conn.Open();
                    using (var reader = cmd.ExecuteReader())
                    {
                        return reader.Select(r => carBuilder(r)).ToList();
                    }
                }
            }
        }
 
        /// <summary>
        /// 異步獲取數據 
        /// </summary>
        /// <returns></returns>
        public async Task<IEnumerable<Car>> GetCarsViaSPAsync()
        {
            using (var conn = new SqlConnection(_connectionString))
            {
                using (var cmd = new SqlCommand())
                {
                    cmd.Connection = conn;
                    cmd.CommandText = _spName;
                    cmd.CommandType = CommandType.StoredProcedure;
                    conn.Open();
                    using (var reader = await cmd.ExecuteReaderAsync())  //調用異步方法
                    {
                        return reader.Select(r => carBuilder(r)).ToList();
                    }
                }
            }
        }
 
        //private helpers
        private Car carBuilder(SqlDataReader reader)
        {
            return new Car
            {
                Id = int.Parse(reader["Id"].ToString()),
                Make = reader["Make"is DBNull ? null : reader["Make"].ToString(),
                Model = reader["Model"is DBNull ? null : reader["Model"].ToString(),
                Year = int.Parse(reader["Year"].ToString()),
                Price = float.Parse(reader["Price"].ToString()),
            };
        }
    }  
 
二、數據庫對應實體類及輔助擴展方法
  public class Car
    {
        public int Id { getset; }
        public string Make { getset; }
        public string Model { getset; }
        public int Year { getset; }
        public float Price { getset; }
    } 
 
 public static class Extensions
    {
        public static IEnumerable<T> Select<T>(
        this SqlDataReader reader, Func<SqlDataReader, T> projection)
        {
            while (reader.Read())
            {
                yield return projection(reader);
            }
        }
    } 
 
三、webapi Controller調用方法
  //同步調用接口
    public class SPCarsSyncController : ApiController
    {
        readonly GalleryContext galleryContext = new GalleryContext();
        public IEnumerable<Car> Get()
        {
            return galleryContext.GetCarsViaSP();
        }
    }  
 
 //異步調用接口
    public class SPCarsAsyncController : ApiController
    {
        readonly GalleryContext galleryContext = new GalleryContext();
        public async Task<IEnumerable<Car>> Get()
        {
            return await galleryContext.GetCarsViaSPAsync();
        }
    } 
 
四、數據庫鏈接配置文件
<connectionStrings>
    <add name="TestDBConnStr"
    connectionString="Server=你的數據庫地址;Database=TestDB;User Id=sa;Password=123;Integrated Security=false;Max Pool Size=500;Asynchronous Processing=True;"
    providerName="System.Data.SqlClient" />
  </connectionStrings> 
 其中:
Max Pool Size:表示鏈接池的最大數量
Asynchronous Processing=True;表示數據庫支持異步處理
Integrated Security=false;此處設爲true或不設置會拋出異常
Login failed for user 'NT AUTHORITY\SYSTEM'
 
使用ab.exe模擬併發請求
模擬請求同步服務:
 
模擬請求異步服務:
 
結論:
    訪問相同的數據表及數據,
    使用同步方式共用時 20秒,平均每秒處理5個請求;
    使用異步方式共用時 10秒,平均每秒處理 10個請求;
相關文章
相關標籤/搜索