Asp.net web api 池中每个新连接的每个请求的WebApi HttpClient

Asp.net web api 池中每个新连接的每个请求的WebApi HttpClient,asp.net-web-api,httpclient,Asp.net Web Api,Httpclient,在我的例子中,我通过HttpClient向服务器端发出web请求。但每次连接池中都会有一个新连接。程序只使用了一个连接字符串。新连接增长过快,然后超过最大池大小100。我必须研究关于数据库连接池和IIS的问题 sqlserver数据库连接字符串: <connectionStrings> <add name="WERP2ConnectionString" connectionString="Data Source=localhost;Initial Catalog=W

在我的例子中,我通过HttpClient向服务器端发出web请求。但每次连接池中都会有一个新连接。程序只使用了一个连接字符串。新连接增长过快,然后超过最大池大小100。我必须研究关于数据库连接池和IIS的问题

sqlserver数据库连接字符串:

  <connectionStrings>
    <add name="WERP2ConnectionString" connectionString="Data Source=localhost;Initial Catalog=WERP2-1108;User ID=sa;Password=sasa;Connect Timeout=15;Encrypt=False;"/>
  </connectionStrings>

客户端程序:

static void Main(string[] args)
{
    for (int i = 0; i < 5; i++)
    {
        Console.WriteLine("api test: {0}", i);
        ApiTest();   //to mimic the 5 different users make the api request.
    }
    Console.ReadLine();
}


private static void ApiTest()
{
    using (HttpClient client = new HttpClient())
    {
        client.BaseAddress = new Uri("http://localhost/StressApi/");
        client.DefaultRequestHeaders.Accept.Add(
            new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
        var response = client.GetAsync("api/order/GetOrder").Result;
        if (response.IsSuccessStatusCode)
        {
            var message = response.Content.ReadAsStringAsync().Result;
            if (!string.IsNullOrEmpty(message))
            {
                Console.WriteLine(message);
            }
        }
        else
        {
            Console.WriteLine("Error Code" +
            response.StatusCode + " : Message - " + response.ReasonPhrase);
        }
        //Console.ReadLine();
    }
}
static void Main(字符串[]args)
{
对于(int i=0;i<5;i++)
{
WriteLine(“api测试:{0}”,i);
ApiTest();//模拟5个不同的用户发出api请求。
}
Console.ReadLine();
}
专用静态无效测试()
{
使用(HttpClient=new HttpClient())
{
client.BaseAddress=新Uri(“http://localhost/StressApi/");
client.DefaultRequestHeaders.Accept.Add(
新的System.Net.Http.Headers.MediaTypeWithQualityHeaderValue(“应用程序/json”);
var response=client.GetAsync(“api/order/GetOrder”).Result;
if(响应。IsSuccessStatusCode)
{
var message=response.Content.ReadAsStringAsync().Result;
如果(!string.IsNullOrEmpty(消息))
{
控制台写入线(消息);
}
}
其他的
{
Console.WriteLine(“错误代码”+
response.StatusCode+”:消息-“+response.ReasonPhrase);
}
//Console.ReadLine();
}
}
WebApi控制器:

public class OrderController : ApiController
{
    [HttpGet]
    public HttpResponseMessage GetOrder()
    {
        OrderModel model = new OrderModel();
        var entity = model.GetByID();
        HttpResponseMessage response = Request.CreateResponse<OrderEntity>(HttpStatusCode.OK, entity);

        return response;
    }
}

public class OrderEntity
{
    public int ID { get; set; }
    public string OrderCode { get; set; }
    public int OrderType { get; set; }
}

public class OrderModel
{
    public OrderEntity GetByID()
    {
        OrderEntity entity = new OrderEntity();

        string sql = @"select * from salorder where id=97";
        using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["WERP2ConnectionString"].ToString()))
        using (SqlCommand cmd = new SqlCommand(sql, conn))
        {
            // don't forget to actually open the connection before using it
            conn.Open();
            try
            {
                using (SqlDataReader dataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
                {
                    while (dataReader.Read())
                    {
                        // do something
                        Console.WriteLine(dataReader.GetValue(0) + " - " + dataReader.GetValue(1) + " - " + dataReader.GetValue(2));
                        entity.ID = int.Parse(dataReader.GetValue(0).ToString());
                        entity.OrderCode = dataReader.GetValue(1).ToString();
                        entity.OrderType = int.Parse(dataReader.GetValue(2).ToString());
                        //dataReader
                    }
                }
            }
            finally
            {
                //SqlConnection.ClearPool(conn);
            }
        }
        return entity;
    }
}
公共类OrderController:ApicController
{
[HttpGet]
公共HttpResponseMessage GetOrder()
{
OrderModel模型=新的OrderModel();
var entity=model.GetByID();
HttpResponseMessage response=Request.CreateResponse(HttpStatusCode.OK,实体);
返回响应;
}
}
公共类OrderEntity
{
公共int ID{get;set;}
公共字符串顺序码{get;set;}
公共int-OrderType{get;set;}
}
公共类排序模型
{
public OrderEntity GetByID()
{
OrderEntity=新的OrderEntity();
字符串sql=@“从salorder中选择*,其中id=97”;
使用(SqlConnection conn=newsqlconnection(ConfigurationManager.ConnectionStrings[“WERP2ConnectionString”].ToString())
使用(SqlCommand cmd=newsqlcommand(sql,conn))
{
//在使用之前,不要忘记实际打开连接
conn.Open();
尝试
{
使用(SqlDataReader-dataReader=cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
while(dataReader.Read())
{
//做点什么
Console.WriteLine(dataReader.GetValue(0)+“-”+dataReader.GetValue(1)+“-”+dataReader.GetValue(2));
entity.ID=int.Parse(dataReader.GetValue(0.ToString());
entity.OrderCode=dataReader.GetValue(1.ToString();
entity.OrderType=int.Parse(dataReader.GetValue(2.ToString());
//数据阅读器
}
}
}
最后
{
//SqlConnection.ClearPool(conn);
}
}
返回实体;
}
}
每个sql查询都会在sqlserver中生成一个进程,我们可以在sqlserver活动监视器中找到它们,共有5条记录,因为我重复了5次查询

如果我们使用SP_WHO命令,我们还可以验证5条过程记录,它们处于休眠等待命令状态

我对如何避免这种连接泄漏问题感到困惑。虽然我每次都进行相同的sql查询,但仍然会重新生成新的连接。我已经测试过,这些连接将在20秒内回收利用。当然,我可以重置IIS或回收应用程序池来释放它们。但这在在线系统中是绝对不能接受的。请有人能提些建议吗?谢谢


顺便说一下,该编程是使用.NET Framework 4.0、IIS7和SQLSERVER2008 R2运行的。

HttpClient将在每个请求中打开一个新套接字。因此,建议使用此的单个实例

有关更多信息,请访问下面的链接


我尝试处理httpclient对象,甚至使用{…}块重写它,但连接计数仍然是5。我们必须在连接字符串中添加connection lieftime参数,但我认为httpclient中有一些技巧,或者我必须使用httpwebrequest而不是httpclient自己重写代码。